From a8e2c8e5b8aee67da562d8a3a87aee5b3b403005 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 16 May 2025 18:03:32 -0500 Subject: [PATCH] Address #1596 - Use atomic intrinsics to check allow_interrupt flag. Use a relaxed memory order if possible to mitigate performance issues as much as possible. relaxed memory order should be sufficient. --- src/core/capi.c | 10 ++++++++++ src/core/ev.c | 3 ++- src/core/vm.c | 2 +- src/include/janet.h | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/capi.c b/src/core/capi.c index 5a6a2e68..628394e1 100644 --- a/src/core/capi.c +++ b/src/core/capi.c @@ -589,6 +589,16 @@ JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) { #endif } +JanetAtomicInt janet_atomic_load_relaxed(JanetAtomicInt volatile *x) { +#ifdef _MSC_VER + return _InterlockedOrNoFence(x, 0); +#elif defined(JANET_USE_STDATOMIC) + return atomic_load_explicit(x, memory_order_relaxed); +#else + return __atomic_load_n(x, __ATOMIC_RELAXED); +#endif +} + /* Some definitions for function-like macros */ JANET_API JanetStructHead *(janet_struct_head)(JanetStruct st) { diff --git a/src/core/ev.c b/src/core/ev.c index d9ce3f48..d0fbca56 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -1457,7 +1457,7 @@ JanetFiber *janet_loop1(void) { /* Run scheduled fibers unless interrupts need to be handled. */ while (janet_vm.spawn.head != janet_vm.spawn.tail) { /* Don't run until all interrupts have been marked as handled by calling janet_interpreter_interrupt_handled */ - if (janet_vm.auto_suspend) break; + if (janet_atomic_load_relaxed(&janet_vm.auto_suspend)) break; JanetTask task = {NULL, janet_wrap_nil(), JANET_SIGNAL_OK, 0}; janet_q_pop(&janet_vm.spawn, &task, sizeof(task)); if (task.fiber->gc.flags & JANET_FIBER_EV_FLAG_SUSPENDED) janet_ev_dec_refcount(); @@ -3231,6 +3231,7 @@ JANET_CORE_FN(cfun_ev_deadline, janet_free(tto); janet_panicf("%s", janet_strerror(err)); } + janet_assert(!pthread_detach(worker), "pthread_detach"); #endif to.has_worker = 1; to.worker = worker; diff --git a/src/core/vm.c b/src/core/vm.c index 6ad79053..a0dae1c8 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -115,7 +115,7 @@ #define vm_maybe_auto_suspend(COND) #else #define vm_maybe_auto_suspend(COND) do { \ - if ((COND) && janet_vm.auto_suspend) { \ + if ((COND) && janet_atomic_load_relaxed(&janet_vm.auto_suspend)) { \ fiber->flags |= (JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP); \ vm_return(JANET_SIGNAL_INTERRUPT, janet_wrap_nil()); \ } \ diff --git a/src/include/janet.h b/src/include/janet.h index 8e6ca968..74d0661f 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -667,6 +667,7 @@ typedef int32_t JanetAtomicInt; JANET_API JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x); JANET_API JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x); JANET_API JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x); +JANET_API JanetAtomicInt janet_atomic_load_relaxed(JanetAtomicInt volatile *x); /* We provide three possible implementations of Janets. The preferred * nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the