| #pragma once |
| |
| #include "atomic.h" |
| |
| #include <limits.h> |
| #include <zircon/syscalls.h> |
| #include <stdatomic.h> |
| |
| void __wait(atomic_int* futex, atomic_int* waiters, int current_value); |
| |
| /* Self-synchronized-destruction-safe lock functions */ |
| #define UNLOCKED 0 |
| #define LOCKED_NO_WAITERS 1 |
| #define LOCKED_MAYBE_WAITERS 2 |
| |
| static inline void lock(atomic_int* l) { |
| if (a_cas_shim(l, UNLOCKED, LOCKED_NO_WAITERS)) { |
| a_cas_shim(l, LOCKED_NO_WAITERS, LOCKED_MAYBE_WAITERS); |
| do |
| __wait(l, UNLOCKED, LOCKED_MAYBE_WAITERS); |
| while (a_cas_shim(l, UNLOCKED, LOCKED_MAYBE_WAITERS)); |
| } |
| } |
| |
| static inline void unlock(atomic_int* l) { |
| if (atomic_exchange(l, UNLOCKED) == LOCKED_MAYBE_WAITERS) |
| _zx_futex_wake(l, 1); |
| } |
| |
| static inline void unlock_requeue(atomic_int* l, zx_futex_t* r) { |
| atomic_store(l, UNLOCKED); |
| _zx_futex_requeue(l, /* wake count */ 0, /* l futex value */ UNLOCKED, |
| r, /* requeue count */ 1, /* requeue owner */ ZX_HANDLE_INVALID); |
| } |