diff options
Diffstat (limited to 'deps/lightening/tests/z_atomic.c')
-rw-r--r-- | deps/lightening/tests/z_atomic.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/deps/lightening/tests/z_atomic.c b/deps/lightening/tests/z_atomic.c new file mode 100644 index 0000000..8612d15 --- /dev/null +++ b/deps/lightening/tests/z_atomic.c @@ -0,0 +1,88 @@ +#include "test.h" + +#include <threads.h> + +/* note non-atomic counter! */ +size_t num = 0; +long lock_var = 0; +void (*spin_lock)(void); +void (*spin_unlock)(void); + +/* arbitrary number, as long as its large enough to likely allow other threads + * to spawn. */ +#define THREAD_INCREMENTS 1000000 +static int +loop(void *arg) +{ + for (size_t i = 0; i < THREAD_INCREMENTS; ++i) { + (*spin_lock)(); + num++; + (*spin_unlock)(); + } + + return 0; +} + +#define NUM_THREADS 10 +static void +run_loops() +{ + thrd_t threads[NUM_THREADS]; + for (size_t i = 0; i < NUM_THREADS; ++i) + ASSERT(thrd_create(&threads[i], loop, NULL) == thrd_success); + + for (size_t i = 0; i < NUM_THREADS; ++i) + ASSERT(thrd_join(threads[i], NULL) == thrd_success); + + ASSERT(num == NUM_THREADS * THREAD_INCREMENTS); +} + +static size_t +run_test(jit_state_t *_jit, uint8_t *arena_base, size_t arena_size) +{ + jit_begin(_jit, arena_base, arena_size); + + /* based on https://rigtorp.se/spinlock/ */ + spin_lock = jit_address(_jit); + { + size_t frame = jit_enter_jit_abi(_jit, 0, 0, 0); + void *do_exchange = jit_address(_jit); + void *while_load = jit_address(_jit); + /* do { */ + /* while (atomic_load(lock_var)); */ + jit_movi(_jit, JIT_R1, (jit_imm_t)&lock_var); + jit_ldr_atomic(_jit, JIT_R0, JIT_R1); + jit_patch_there(_jit, jit_bnei(_jit, JIT_R0, 0), while_load); + /* } while (atomic_exchange(lock_var, 1)); */ + jit_movi(_jit, JIT_R0, 1); + jit_swap_atomic(_jit, JIT_R0, JIT_R1, JIT_R0); + jit_patch_there(_jit, jit_bnei(_jit, JIT_R0, 0), do_exchange); + jit_leave_jit_abi(_jit, 0, 0, frame); + jit_ret(_jit); + } + + spin_unlock = jit_address(_jit); + { + size_t frame = jit_enter_jit_abi(_jit, 0, 0, 0); + jit_movi(_jit, JIT_R0, 0); + jit_movi(_jit, JIT_R1, (jit_imm_t)&lock_var); + jit_str_atomic(_jit, JIT_R1, JIT_R0); + jit_leave_jit_abi(_jit, 0, 0, frame); + jit_ret(_jit); + } + + size_t size; + void *p = jit_end(_jit, &size); + + if (p) + run_loops(); + else + return size; + + return 0; +} + +int main(int argc, char *argv[]) +{ + return main_compiler(argc, argv, run_test); +} |