1 #pragma once
2 
3 #include "atomic.h"
4 
5 #include <limits.h>
6 #include <zircon/syscalls.h>
7 #include <stdatomic.h>
8 
9 void __wait(atomic_int* futex, atomic_int* waiters, int current_value);
10 
11 /* Self-synchronized-destruction-safe lock functions */
12 #define UNLOCKED 0
13 #define LOCKED_NO_WAITERS 1
14 #define LOCKED_MAYBE_WAITERS 2
15 
lock(atomic_int * l)16 static inline void lock(atomic_int* l) {
17     if (a_cas_shim(l, UNLOCKED, LOCKED_NO_WAITERS)) {
18         a_cas_shim(l, LOCKED_NO_WAITERS, LOCKED_MAYBE_WAITERS);
19         do
20             __wait(l, UNLOCKED, LOCKED_MAYBE_WAITERS);
21         while (a_cas_shim(l, UNLOCKED, LOCKED_MAYBE_WAITERS));
22     }
23 }
24 
unlock(atomic_int * l)25 static inline void unlock(atomic_int* l) {
26     if (atomic_exchange(l, UNLOCKED) == LOCKED_MAYBE_WAITERS)
27         _zx_futex_wake(l, 1);
28 }
29 
unlock_requeue(atomic_int * l,zx_futex_t * r)30 static inline void unlock_requeue(atomic_int* l, zx_futex_t* r) {
31     atomic_store(l, UNLOCKED);
32     _zx_futex_requeue(l, /* wake count */ 0, /* l futex value */ UNLOCKED,
33                       r, /* requeue count */ 1, /* requeue owner */ ZX_HANDLE_INVALID);
34 }
35