From d5a7c8e4ad719e84dbb4904c532f906a1ef5a77b Mon Sep 17 00:00:00 2001 From: pcpa Date: Thu, 8 Sep 2022 16:48:43 -0300 Subject: Implement a simple compare and swap atomic operation. * lib/jit_fallback.c: Implement fallback compare and swap with pthreads. * check/Makefile.am: Update for new cas{r,i} simple test. * check/catomic.c, check/catomic.ok: New test case for simple compare and swap atomic operation. * check/lightning.c: Add entries to be able to use the new compare and swap atomic operation. Still missing a general test, only the basic C version. * include/lightning.h.in: Include pthread.h, even if not needing a fallback compare and swap. * include/lightning/jit_private.h: Add support for a register pair in second argument. Required by the new casr and casi operations. * lib/jit_aarch64-cpu.c, lib/jit_aarch64-sz.c, lib/jit_aarch64.c, lib/jit_ppc-cpu.c, lib/jit_ppc-sz.c, lib/jit_ppc.c, lib/jit_x86-cpu.c, lib/jit_x86-sz.c, lib/jit_x86.c: Implement inline code for compare and swap. * lib/jit_arm-cpu.c, lib/jit_arm-sz.c, lib/jit_arm.c: Implement inline code for compare and swap if cpu is armv7, otherwise, use a fallback with pthreads. * lib/jit_alpha-cpu.c, lib/jit_alpha-sz.c, lib/jit_alpha.c, lib/jit_hppa-cpu.c, lib/jit_hppa-sz.c, lib/jit_hppa.c, lib/jit_ia64-cpu.c, lib/jit_ia64-sz.c, lib/jit_ia64.c, lib/jit_mips-cpu.c, lib/jit_mips-sz.c, lib/jit_mips.c, lib/jit_riscv-cpu.c, lib/jit_riscv-sz.c, lib/jit_riscv.c, lib/jit_s390-cpu.c, lib/jit_s390-sz.c, lib/jit_s390.c, lib/jit_sparc-cpu.c, lib/jit_sparc-sz.c, lib/jit_sparc.c: Implement fallback compare and swap with pthreads. At least some of these should be updated for inline code generation. * lib/jit_names.c, lib/jit_print.c: lib/lightning.c: Update for the new compare and swap operation. * doc/body.texi: Add simple documentation of the compare and swap new operation. --- lib/jit_fallback.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 lib/jit_fallback.c (limited to 'lib/jit_fallback.c') diff --git a/lib/jit_fallback.c b/lib/jit_fallback.c new file mode 100644 index 0000000..89a6295 --- /dev/null +++ b/lib/jit_fallback.c @@ -0,0 +1,178 @@ +#if PROTO +#define fallback_save(r0) _fallback_save(_jit, r0) +static void _fallback_save(jit_state_t*, jit_int32_t); +#define fallback_load(r0) _fallback_load(_jit, r0) +static void _fallback_load(jit_state_t*, jit_int32_t); +#define fallback_save_regs(r0) _fallback_save_regs(_jit, r0) +static void _fallback_save_regs(jit_state_t*, jit_int32_t); +#define fallback_load_regs(r0) _fallback_load_regs(_jit, r0) +static void _fallback_load_regs(jit_state_t*, jit_int32_t); +#define fallback_calli(i0, i1) _fallback_calli(_jit, i0, i1) +static void _fallback_calli(jit_state_t*, jit_word_t, jit_word_t); +#define fallback_casx(r0,r1,r2,r3,im) _fallback_casx(_jit,r0,r1,r2,r3,im) +static void _fallback_casx(jit_state_t *, jit_int32_t, jit_int32_t, + jit_int32_t, jit_int32_t, jit_word_t); +#endif + +#if CODE +static void +_fallback_save(jit_state_t *_jit, jit_int32_t r0) +{ + jit_int32_t offset, regno, spec; + for (offset = 0; offset < JIT_R_NUM; offset++) { + spec = _rvs[offset].spec; + regno = jit_regno(spec); + if (regno == r0) { + if (!(spec & jit_class_sav)) + stxi(_jitc->function->regoff[offset], rn(JIT_FP), regno); + break; + } + } +} + +static void +_fallback_load(jit_state_t *_jit, jit_int32_t r0) +{ + jit_int32_t offset, regno, spec; + for (offset = 0; offset < JIT_R_NUM; offset++) { + spec = _rvs[offset].spec; + regno = jit_regno(spec); + if (regno == r0) { + if (!(spec & jit_class_sav)) + ldxi(regno, rn(JIT_FP), _jitc->function->regoff[offset]); + break; + } + } +} + +static void +_fallback_save_regs(jit_state_t *_jit, jit_int32_t r0) +{ + jit_int32_t offset, regno, spec; + for (offset = 0; offset < JIT_R_NUM; offset++) { + regno = JIT_R(offset); + spec = _rvs[regno].spec; + if ((spec & jit_class_gpr) && regno == r0) + continue; + if (!(spec & jit_class_sav)) { + if (!_jitc->function->regoff[regno]) { + _jitc->function->regoff[regno] = + jit_allocai(sizeof(jit_word_t)); + _jitc->again = 1; + } + jit_regset_setbit(&_jitc->regsav, regno); + emit_stxi(_jitc->function->regoff[regno], JIT_FP, regno); + } + } + /* If knew for certain float registers are not used by + * pthread_mutex_lock and pthread_mutex_unlock, could skip this */ + for (offset = 0; offset < JIT_F_NUM; offset++) { + regno = JIT_F(offset); + spec = _rvs[regno].spec; + if (!(spec & jit_class_sav)) { + if (!_jitc->function->regoff[regno]) { + _jitc->function->regoff[regno] = + jit_allocai(sizeof(jit_word_t)); + _jitc->again = 1; + } + jit_regset_setbit(&_jitc->regsav, regno); + emit_stxi_d(_jitc->function->regoff[regno], JIT_FP, regno); + } + } +} + +static void +_fallback_load_regs(jit_state_t *_jit, jit_int32_t r0) +{ + jit_int32_t offset, regno, spec; + for (offset = 0; offset < JIT_R_NUM; offset++) { + regno = JIT_R(offset); + spec = _rvs[regno].spec; + if ((spec & jit_class_gpr) && regno == r0) + continue; + if (!(spec & jit_class_sav)) { + jit_regset_clrbit(&_jitc->regsav, regno); + emit_ldxi(regno, JIT_FP, _jitc->function->regoff[regno]); + } + } + /* If knew for certain float registers are not used by + * pthread_mutex_lock and pthread_mutex_unlock, could skip this */ + for (offset = 0; offset < JIT_F_NUM; offset++) { + regno = JIT_F(offset); + spec = _rvs[regno].spec; + if (!(spec & jit_class_sav)) { + jit_regset_clrbit(&_jitc->regsav, regno); + emit_ldxi_d(regno, JIT_FP, _jitc->function->regoff[regno]); + } + } +} + +static void +_fallback_calli(jit_state_t *_jit, jit_word_t i0, jit_word_t i1) +{ +# if defined(__mips__) + movi(rn(_A0), i1); +# elif defined(__arm__) + movi(rn(_R0), i1); +# elif defined(__sparc__) + movi(rn(_O0), i1); +# elif defined(__ia64__) + /* avoid confusion with pushargi patching */ + if (i1>= -2097152 && i0 <= 2097151) + MOVI(_jitc->rout, i1); + else + MOVL(_jitc->rout, i1); +# elif defined(__hppa__) + movi(_R26_REGNO, i1); +# elif defined(__s390__) || defined(__s390x__) + movi(rn(_R2), i1); +# elif defined(__alpha__) + movi(rn(_A0), i1); +# elif defined(__riscv__) + movi(rn(JIT_RA0), i1); +# endif + calli(i0); +} + +static void +_fallback_casx(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, + jit_int32_t r2, jit_int32_t r3, jit_word_t i0) +{ + jit_int32_t r1_reg, iscasi; + jit_word_t jump, done; + /* XXX only attempts to fallback cas for lightning jit code */ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + if ((iscasi = r1 == _NOREG)) { + r1_reg = jit_get_reg(jit_class_gpr); + r1 = rn(r1_reg); + } + fallback_save_regs(r0); + if (iscasi) + movi(r1, i0); + fallback_calli((jit_word_t)pthread_mutex_lock, (jit_word_t)&mutex); + fallback_load(r1); + ldr(r0, r1); + fallback_load(r2); + eqr(r0, r0, r2); + fallback_save(r0); + jump = bnei(_jit->pc.w, r0, 1); + fallback_load(r3); +# if __WORDSIZE == 32 + str_i(r1, r3); +# else + str_l(r1, r3); +# endif + /* done: */ + done = _jit->pc.w; + fallback_calli((jit_word_t)pthread_mutex_unlock, (jit_word_t)&mutex); + fallback_load(r0); +# if defined(__arm__) + patch_at(arm_patch_jump, jump, done); +# else + patch_at(jump, done); +# endif + fallback_load_regs(r0); + if (iscasi) + jit_unget_reg(r1_reg); +} +#endif -- cgit v1.2.3

AltStyle によって変換されたページ (->オリジナル) /