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 =
11 libc::PTHREAD_MUTEX_INITIALIZER;
13 pub(crate) fn init_global_lock(
14 module: &mut impl Module,
15 bcx: &mut FunctionBuilder<'_>,
19 // When using JIT, dylibs won't find the __cg_clif_global_atomic_mutex data object defined here,
20 // so instead we define it in the cg_clif dylib.
25 let mut data_ctx = DataContext::new();
26 data_ctx.define_zeroinit(1024); // 1024 bytes should be big enough on all platforms.
27 data_ctx.set_align(16);
28 let atomic_mutex = module
30 "__cg_clif_global_atomic_mutex",
36 module.define_data(atomic_mutex, &data_ctx).unwrap();
38 let pthread_mutex_init = module
42 &cranelift_codegen::ir::Signature {
43 call_conv: module.target_config().default_call_conv,
46 module.target_config().pointer_type(), /* *mut pthread_mutex_t */
49 module.target_config().pointer_type(), /* *const pthread_mutex_attr_t */
52 returns: vec![AbiParam::new(types::I32 /* c_int */)],
57 let pthread_mutex_init = module.declare_func_in_func(pthread_mutex_init, bcx.func);
59 let atomic_mutex = module.declare_data_in_func(atomic_mutex, bcx.func);
60 let atomic_mutex = bcx
62 .global_value(module.target_config().pointer_type(), atomic_mutex);
64 let nullptr = bcx.ins().iconst(module.target_config().pointer_type(), 0);
66 bcx.ins().call(pthread_mutex_init, &[atomic_mutex, nullptr]);
69 pub(crate) fn init_global_lock_constructor(
70 module: &mut impl Module,
71 constructor_name: &str,
73 let sig = Signature::new(CallConv::SystemV);
74 let init_func_id = module
75 .declare_function(constructor_name, Linkage::Export, &sig)
78 let mut ctx = Context::new();
79 ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
81 let mut func_ctx = FunctionBuilderContext::new();
82 let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
84 let block = bcx.create_block();
85 bcx.switch_to_block(block);
87 crate::atomic_shim::init_global_lock(module, &mut bcx, false);
89 bcx.ins().return_(&[]);
90 bcx.seal_all_blocks();
97 &mut cranelift_codegen::binemit::NullTrapSink {},
104 pub(crate) fn lock_global_lock(fx: &mut FunctionCx<'_, '_, impl Module>) {
105 let atomic_mutex = fx
109 "__cg_clif_global_atomic_mutex",
116 let pthread_mutex_lock = fx
120 "pthread_mutex_lock",
122 &cranelift_codegen::ir::Signature {
123 call_conv: fx.cx.module.target_config().default_call_conv,
124 params: vec![AbiParam::new(
125 fx.cx.module.target_config().pointer_type(), /* *mut pthread_mutex_t */
127 returns: vec![AbiParam::new(types::I32 /* c_int */)],
132 let pthread_mutex_lock = fx
135 .declare_func_in_func(pthread_mutex_lock, fx.bcx.func);
137 let atomic_mutex = fx.cx.module.declare_data_in_func(atomic_mutex, fx.bcx.func);
138 let atomic_mutex = fx
141 .global_value(fx.cx.module.target_config().pointer_type(), atomic_mutex);
143 fx.bcx.ins().call(pthread_mutex_lock, &[atomic_mutex]);
146 pub(crate) fn unlock_global_lock(fx: &mut FunctionCx<'_, '_, impl Module>) {
147 let atomic_mutex = fx
151 "__cg_clif_global_atomic_mutex",
158 let pthread_mutex_unlock = fx
162 "pthread_mutex_unlock",
164 &cranelift_codegen::ir::Signature {
165 call_conv: fx.cx.module.target_config().default_call_conv,
166 params: vec![AbiParam::new(
167 fx.cx.module.target_config().pointer_type(), /* *mut pthread_mutex_t */
169 returns: vec![AbiParam::new(types::I32 /* c_int */)],
174 let pthread_mutex_unlock = fx
177 .declare_func_in_func(pthread_mutex_unlock, fx.bcx.func);
179 let atomic_mutex = fx.cx.module.declare_data_in_func(atomic_mutex, fx.bcx.func);
180 let atomic_mutex = fx
183 .global_value(fx.cx.module.target_config().pointer_type(), atomic_mutex);
185 fx.bcx.ins().call(pthread_mutex_unlock, &[atomic_mutex]);