diff options
Diffstat (limited to 'lib/libc/internal/include/atomic.h')
| -rw-r--r-- | lib/libc/internal/include/atomic.h | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/lib/libc/internal/include/atomic.h b/lib/libc/internal/include/atomic.h index e0593021..d40c1eae 100644 --- a/lib/libc/internal/include/atomic.h +++ b/lib/libc/internal/include/atomic.h @@ -1,22 +1,32 @@ #ifndef __LIBC_ATOMIC_H #define __LIBC_ATOMIC_H +#include <libc/futex.h> +#include <sched.h> #include <stdatomic.h> +#include <unistd.h> #define LIBC_LOCK(__lock) __libc_lock(&((__lock))) -#define LIBC_UNLOCK(__lock) atomic_flag_clear(&((__lock))) +#define LIBC_UNLOCK(__lock) __libc_unlock(&((__lock))) -static __inline void __libc_lock(volatile atomic_flag *lock) +__attribute__((__always_inline__)) __inline void __libc_unlock(volatile atomic_flag *lock) { - while (atomic_flag_test_and_set_explicit(lock, memory_order_acquire)) { - unsigned int spins = 1; - do { - for (unsigned int i = 0; i < spins; i++) - __asm__ volatile("pause"); - if (spins < 64) - spins *= 2; - } while (atomic_flag_test_and_set_explicit( - lock, memory_order_relaxed)); + atomic_flag_clear_explicit(lock, memory_order_release); + __futex_wake((volatile int *)lock, 1); +} + +__attribute__((__always_inline__)) __inline void __libc_lock(volatile atomic_flag *lock) +{ + if (atomic_flag_test_and_set_explicit(lock, memory_order_acquire) == 0) + return; + + while (1) { + __futex_wait((volatile int *)lock, 1); + + if (atomic_flag_test_and_set_explicit(lock, memory_order_acquire) == 0) + return; + + sched_yield(); } } |
