Changes in uspace/lib/c/generic/futex.c [a35b458:f6372be9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/futex.c
ra35b458 rf6372be9 34 34 35 35 #include <futex.h> 36 37 #include <assert.h> 36 38 #include <atomic.h> 39 #include <fibril.h> 40 #include <io/kio.h> 41 42 #include "private/fibril.h" 43 44 //#define DPRINTF(...) kio_printf(__VA_ARGS__) 45 #define DPRINTF(...) ((void)0) 37 46 38 47 /** Initialize futex counter. … … 47 56 } 48 57 58 #ifdef CONFIG_DEBUG_FUTEX 49 59 50 #ifdef FUTEX_UPGRADABLE 60 void __futex_assert_is_locked(futex_t *futex, const char *name) 61 { 62 void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED); 63 fibril_t *self = (fibril_t *) fibril_get_id(); 64 if (owner != self) { 65 DPRINTF("Assertion failed: %s (%p) is not locked by fibril %p (instead locked by fibril %p).\n", name, futex, self, owner); 66 } 67 assert(owner == self); 68 } 51 69 52 int _upgrade_futexes = 0; 53 static futex_t upg_and_wait_futex = FUTEX_INITIALIZER; 70 void __futex_assert_is_not_locked(futex_t *futex, const char *name) 71 { 72 void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED); 73 fibril_t *self = (fibril_t *) fibril_get_id(); 74 if (owner == self) { 75 DPRINTF("Assertion failed: %s (%p) is already locked by fibril %p.\n", name, futex, self); 76 } 77 assert(owner != self); 78 } 54 79 55 void futex_upgrade_all_and_wait(void)80 void __futex_lock(futex_t *futex, const char *name) 56 81 { 57 futex_down(&upg_and_wait_futex); 82 /* We use relaxed atomics to avoid violating C11 memory model. 83 * They should compile to regular load/stores, but simple assignments 84 * would be UB by definition. 85 */ 58 86 59 if (!_upgrade_futexes) { 60 rcu_assign(_upgrade_futexes, 1); 61 _rcu_synchronize(BM_BLOCK_THREAD); 87 fibril_t *self = (fibril_t *) fibril_get_id(); 88 DPRINTF("Locking futex %s (%p) by fibril %p.\n", name, futex, self); 89 __futex_assert_is_not_locked(futex, name); 90 futex_down(futex); 91 92 void *prev_owner = __atomic_exchange_n(&futex->owner, self, __ATOMIC_RELAXED); 93 assert(prev_owner == NULL); 94 95 atomic_inc(&self->futex_locks); 96 } 97 98 void __futex_unlock(futex_t *futex, const char *name) 99 { 100 fibril_t *self = (fibril_t *) fibril_get_id(); 101 DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self); 102 __futex_assert_is_locked(futex, name); 103 __atomic_store_n(&futex->owner, NULL, __ATOMIC_RELAXED); 104 atomic_dec(&self->futex_locks); 105 futex_up(futex); 106 } 107 108 bool __futex_trylock(futex_t *futex, const char *name) 109 { 110 fibril_t *self = (fibril_t *) fibril_get_id(); 111 bool success = futex_trydown(futex); 112 if (success) { 113 void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED); 114 assert(owner == NULL); 115 116 __atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED); 117 118 atomic_inc(&self->futex_locks); 119 120 DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self); 121 } else { 122 DPRINTF("Trylock on futex %s (%p) by fibril %p failed.\n", name, futex, self); 62 123 } 63 124 64 futex_up(&upg_and_wait_futex); 125 return success; 126 } 127 128 void __futex_give_to(futex_t *futex, void *new_owner, const char *name) 129 { 130 fibril_t *self = fibril_self(); 131 fibril_t *no = new_owner; 132 DPRINTF("Passing futex %s (%p) from fibril %p to fibril %p.\n", name, futex, self, no); 133 134 __futex_assert_is_locked(futex, name); 135 atomic_dec(&self->futex_locks); 136 atomic_inc(&no->futex_locks); 137 __atomic_store_n(&futex->owner, new_owner, __ATOMIC_RELAXED); 65 138 } 66 139
Note:
See TracChangeset
for help on using the changeset viewer.