summaryrefslogtreecommitdiff
path: root/lib/libc/internal/include/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/internal/include/atomic.h')
-rw-r--r--lib/libc/internal/include/atomic.h32
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();
}
}