diff --git a/src/libAtomVM/CMakeLists.txt b/src/libAtomVM/CMakeLists.txt index 37c2e02bc4..eba7b1fba4 100644 --- a/src/libAtomVM/CMakeLists.txt +++ b/src/libAtomVM/CMakeLists.txt @@ -261,6 +261,7 @@ define_if_function_exists(libAtomVM execve "unistd.h" PRIVATE HAVE_EXECVE) define_if_function_exists(libAtomVM tcgetattr "termios.h" PRIVATE HAVE_TCGETATTR) define_if_function_exists(libAtomVM closefrom "unistd.h" PRIVATE HAVE_CLOSEFROM) define_if_function_exists(libAtomVM getcwd "unistd.h" PUBLIC HAVE_GETCWD) +define_if_function_exists(libAtomVM sched_yield "sched.h" PUBLIC HAVE_SCHED_YIELD) define_if_symbol_exists(libAtomVM POSIX_SPAWN_CLOEXEC_DEFAULT "spawn.h" PRIVATE HAVE_POSIX_SPAWN_CLOEXEC_DEFAULT) define_if_symbol_exists(libAtomVM O_CLOEXEC "fcntl.h" PRIVATE HAVE_O_CLOEXEC) define_if_symbol_exists(libAtomVM O_DIRECTORY "fcntl.h" PRIVATE HAVE_O_DIRECTORY) diff --git a/src/libAtomVM/smp.h b/src/libAtomVM/smp.h index 33416f0324..1a6399a99d 100644 --- a/src/libAtomVM/smp.h +++ b/src/libAtomVM/smp.h @@ -207,16 +207,42 @@ static inline void smp_spinlock_init(SpinLock *lock) lock->lock = 0; } +#if !defined(SMP_SPIN_YIELD) && defined(HAVE_SCHED_YIELD) +#include +#define SMP_SPIN_YIELD() ((void) sched_yield()) +#endif + +#if defined(SMP_SPIN_YIELD) && !defined(SMP_SPIN_YIELD_INTERVAL) +/* + * Number of failed CAS attempts between two yields. Low enough to let + * serialized scheduler threads make progress under Valgrind/CI, while avoiding + * a syscall on very short transient contention. + */ +#define SMP_SPIN_YIELD_INTERVAL 64U +#endif + /** * @brief Lock a spinlock. * @param lock the spin lock to lock */ static inline void smp_spinlock_lock(SpinLock *lock) { +#ifdef SMP_SPIN_YIELD + unsigned int spins = 0; +#endif int current; - do { + while (true) { current = 0; - } while (!ATOMIC_COMPARE_EXCHANGE_WEAK_INT(&lock->lock, ¤t, 1)); + if (ATOMIC_COMPARE_EXCHANGE_WEAK_INT(&lock->lock, ¤t, 1)) { + return; + } +#ifdef SMP_SPIN_YIELD + if (++spins >= SMP_SPIN_YIELD_INTERVAL) { + spins = 0; + SMP_SPIN_YIELD(); + } +#endif + } } /**