Changeset f6372be9 in mainline
- Timestamp:
- 2018-06-26T17:34:23Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b59318e
- Parents:
- 38e3427
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-25 20:50:53)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:34:23)
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
r38e3427 rf6372be9 385 385 ! CONFIG_UBSAN_KERNEL (n/y) 386 386 387 % Track owner for futexes in userspace. 388 ! CONFIG_DEBUG_FUTEX (y/n) 389 387 390 % Deadlock detection support for spinlocks 388 391 ! [CONFIG_DEBUG=y&CONFIG_SMP=y] CONFIG_DEBUG_SPINLOCK (y/n) -
uspace/lib/c/generic/fibril.c
r38e3427 rf6372be9 150 150 case FIBRIL_FROM_DEAD: 151 151 /* Make sure the async_futex is held. */ 152 assert((atomic_signed_t) async_futex.val.count <= 0);152 futex_assert_is_locked(&async_futex); 153 153 154 154 /* If we are going to manager and none exists, create it */ … … 162 162 fibril_t, link); 163 163 164 /* Bookkeeping. */ 165 futex_give_to(&async_futex, dstf); 166 164 167 if (stype == FIBRIL_FROM_DEAD) 165 168 dstf->clean_after_me = srcf; … … 167 170 case FIBRIL_PREEMPT: 168 171 case FIBRIL_FROM_MANAGER: 172 futex_assert_is_not_locked(&async_futex); 173 169 174 if (list_empty(&ready_list)) { 170 175 futex_unlock(&fibril_futex); … … 196 201 break; 197 202 } 203 204 /* Bookkeeping. */ 205 futex_give_to(&fibril_futex, dstf); 198 206 199 207 /* Swap to the next fibril. */ -
uspace/lib/c/generic/futex.c
r38e3427 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 59 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 } 69 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 } 79 80 void __futex_lock(futex_t *futex, const char *name) 81 { 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 */ 86 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); 123 } 124 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); 138 } 139 140 #endif 141 49 142 /** @} 50 143 */ -
uspace/lib/c/include/futex.h
r38e3427 rf6372be9 39 39 #include <errno.h> 40 40 #include <libc.h> 41 #include <time.h> 41 42 42 43 typedef struct futex { 43 44 atomic_t val; 45 #ifdef CONFIG_DEBUG_FUTEX 46 _Atomic void *owner; 47 #endif 44 48 } futex_t; 45 49 46 50 extern void futex_initialize(futex_t *futex, int value); 51 52 #ifdef CONFIG_DEBUG_FUTEX 53 54 #define FUTEX_INITIALIZE(val) {{ (val) }, NULL } 55 #define FUTEX_INITIALIZER FUTEX_INITIALIZE(1) 56 57 void __futex_assert_is_locked(futex_t *, const char *); 58 void __futex_assert_is_not_locked(futex_t *, const char *); 59 void __futex_lock(futex_t *, const char *); 60 void __futex_unlock(futex_t *, const char *); 61 bool __futex_trylock(futex_t *, const char *); 62 void __futex_give_to(futex_t *, void *, const char *); 63 64 #define futex_lock(futex) __futex_lock((futex), #futex) 65 #define futex_unlock(futex) __futex_unlock((futex), #futex) 66 #define futex_trylock(futex) __futex_trylock((futex), #futex) 67 68 #define futex_give_to(futex, new_owner) __futex_give_to((futex), (new_owner), #futex) 69 #define futex_assert_is_locked(futex) __futex_assert_is_locked((futex), #futex) 70 #define futex_assert_is_not_locked(futex) __futex_assert_is_not_locked((futex), #futex) 71 72 #else 47 73 48 74 #define FUTEX_INITIALIZE(val) {{ (val) }} … … 52 78 #define futex_trylock(fut) futex_trydown((fut)) 53 79 #define futex_unlock(fut) (void) futex_up((fut)) 80 81 #define futex_give_to(fut, owner) ((void)0) 82 #define futex_assert_is_locked(fut) assert((atomic_signed_t) (fut)->val.count <= 0) 83 #define futex_assert_is_not_locked(fut) ((void)0) 84 85 #endif 54 86 55 87 /** Try to down the futex.
Note:
See TracChangeset
for help on using the changeset viewer.