1 //! Atomic intrinsics are implemented using a global lock for now, as Cranelift doesn't support
2 //! atomic operations yet.
4 // FIXME implement atomic instructions in Cranelift.
8 #[cfg(all(feature = "jit", unix))]
10 static mut __cg_clif_global_atomic_mutex
: libc
::pthread_mutex_t
= libc
::PTHREAD_MUTEX_INITIALIZER
;
12 pub(crate) fn init_global_lock(
13 module
: &mut impl Module
,
14 bcx
: &mut FunctionBuilder
<'_
>,
18 // When using JIT, dylibs won't find the __cg_clif_global_atomic_mutex data object defined here,
19 // so instead we define it in the cg_clif dylib.
24 let mut data_ctx
= DataContext
::new();
25 data_ctx
.define_zeroinit(1024); // 1024 bytes should be big enough on all platforms.
26 data_ctx
.set_align(16);
27 let atomic_mutex
= module
29 "__cg_clif_global_atomic_mutex",
35 module
.define_data(atomic_mutex
, &data_ctx
).unwrap();
37 let pthread_mutex_init
= module
41 &cranelift_codegen
::ir
::Signature
{
42 call_conv
: module
.target_config().default_call_conv
,
45 module
.target_config().pointer_type(), /* *mut pthread_mutex_t */
48 module
.target_config().pointer_type(), /* *const pthread_mutex_attr_t */
51 returns
: vec
![AbiParam
::new(types
::I32
/* c_int */)],
56 let pthread_mutex_init
= module
.declare_func_in_func(pthread_mutex_init
, bcx
.func
);
58 let atomic_mutex
= module
.declare_data_in_func(atomic_mutex
, bcx
.func
);
59 let atomic_mutex
= bcx
61 .global_value(module
.target_config().pointer_type(), atomic_mutex
);
63 let nullptr
= bcx
.ins().iconst(module
.target_config().pointer_type(), 0);
65 bcx
.ins().call(pthread_mutex_init
, &[atomic_mutex
, nullptr
]);
68 pub(crate) fn init_global_lock_constructor(
69 module
: &mut impl Module
,
70 constructor_name
: &str,
72 let sig
= Signature
::new(CallConv
::SystemV
);
73 let init_func_id
= module
74 .declare_function(constructor_name
, Linkage
::Export
, &sig
)
77 let mut ctx
= Context
::new();
78 ctx
.func
= Function
::with_name_signature(ExternalName
::user(0, 0), sig
);
80 let mut func_ctx
= FunctionBuilderContext
::new();
81 let mut bcx
= FunctionBuilder
::new(&mut ctx
.func
, &mut func_ctx
);
83 let block
= bcx
.create_block();
84 bcx
.switch_to_block(block
);
86 crate::atomic_shim
::init_global_lock(module
, &mut bcx
, false);
88 bcx
.ins().return_(&[]);
89 bcx
.seal_all_blocks();
96 &mut cranelift_codegen
::binemit
::NullTrapSink {}
,
103 pub(crate) fn lock_global_lock(fx
: &mut FunctionCx
<'_
, '_
, impl Module
>) {
104 let atomic_mutex
= fx
108 "__cg_clif_global_atomic_mutex",
115 let pthread_mutex_lock
= fx
119 "pthread_mutex_lock",
121 &cranelift_codegen
::ir
::Signature
{
122 call_conv
: fx
.cx
.module
.target_config().default_call_conv
,
123 params
: vec
![AbiParam
::new(
124 fx
.cx
.module
.target_config().pointer_type(), /* *mut pthread_mutex_t */
126 returns
: vec
![AbiParam
::new(types
::I32
/* c_int */)],
131 let pthread_mutex_lock
= fx
134 .declare_func_in_func(pthread_mutex_lock
, fx
.bcx
.func
);
136 let atomic_mutex
= fx
.cx
.module
.declare_data_in_func(atomic_mutex
, fx
.bcx
.func
);
137 let atomic_mutex
= fx
140 .global_value(fx
.cx
.module
.target_config().pointer_type(), atomic_mutex
);
142 fx
.bcx
.ins().call(pthread_mutex_lock
, &[atomic_mutex
]);
145 pub(crate) fn unlock_global_lock(fx
: &mut FunctionCx
<'_
, '_
, impl Module
>) {
146 let atomic_mutex
= fx
150 "__cg_clif_global_atomic_mutex",
157 let pthread_mutex_unlock
= fx
161 "pthread_mutex_unlock",
163 &cranelift_codegen
::ir
::Signature
{
164 call_conv
: fx
.cx
.module
.target_config().default_call_conv
,
165 params
: vec
![AbiParam
::new(
166 fx
.cx
.module
.target_config().pointer_type(), /* *mut pthread_mutex_t */
168 returns
: vec
![AbiParam
::new(types
::I32
/* c_int */)],
173 let pthread_mutex_unlock
= fx
176 .declare_func_in_func(pthread_mutex_unlock
, fx
.bcx
.func
);
178 let atomic_mutex
= fx
.cx
.module
.declare_data_in_func(atomic_mutex
, fx
.bcx
.func
);
179 let atomic_mutex
= fx
182 .global_value(fx
.cx
.module
.target_config().pointer_type(), atomic_mutex
);
184 fx
.bcx
.ins().call(pthread_mutex_unlock
, &[atomic_mutex
]);