Changeset 508b0df1 in mainline for uspace/lib/c/generic/private
- Timestamp:
- 2018-09-06T20:21:52Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 78de83de, fc10e1b
- Parents:
- 4621d23
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-08-13 03:53:39)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-09-06 20:21:52)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/private/futex.h
r4621d23 r508b0df1 37 37 38 38 #include <assert.h> 39 #include < atomic.h>39 #include <stdatomic.h> 40 40 #include <errno.h> 41 41 #include <libc.h> … … 43 43 44 44 typedef struct futex { 45 atomic_t val;45 volatile atomic_int val; 46 46 #ifdef CONFIG_DEBUG_FUTEX 47 47 void *owner; … … 53 53 #ifdef CONFIG_DEBUG_FUTEX 54 54 55 #define FUTEX_INITIALIZE(val) { { (val) }, NULL }55 #define FUTEX_INITIALIZE(val) { (val) , NULL } 56 56 #define FUTEX_INITIALIZER FUTEX_INITIALIZE(1) 57 57 … … 73 73 #else 74 74 75 #define FUTEX_INITIALIZE(val) { { (val) }}75 #define FUTEX_INITIALIZE(val) { (val) } 76 76 #define FUTEX_INITIALIZER FUTEX_INITIALIZE(1) 77 77 … … 107 107 // TODO: Add tests for this. 108 108 109 if ( (atomic_signed_t) atomic_predec(&futex->val) >=0)109 if (atomic_fetch_sub_explicit(&futex->val, 1, memory_order_acquire) > 0) 110 110 return EOK; 111 112 /* There wasn't any token. We must defer to the underlying semaphore. */ 111 113 112 114 usec_t timeout; … … 129 131 } 130 132 131 return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout);133 return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) futex, (sysarg_t) timeout); 132 134 } 133 135 … … 143 145 static inline errno_t futex_up(futex_t *futex) 144 146 { 145 if ( (atomic_signed_t) atomic_postinc(&futex->val) < 0)146 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count);147 if (atomic_fetch_add_explicit(&futex->val, 1, memory_order_release) < 0) 148 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) futex); 147 149 148 150 return EOK; … … 152 154 const struct timespec *expires) 153 155 { 154 if (expires && expires->tv_sec == 0 && expires->tv_nsec == 0) {155 /* Nonblocking down. */156 157 /*158 * Try good old CAS a few times.159 * Not too much though, we don't want to bloat the caller.160 */161 for (int i = 0; i < 2; i++) {162 atomic_signed_t old = atomic_get(&futex->val);163 if (old <= 0)164 return ETIMEOUT;165 166 if (cas(&futex->val, old, old - 1))167 return EOK;168 }169 170 // TODO: builtin atomics with relaxed ordering can make this171 // faster.172 173 /*174 * If we don't succeed with CAS, we can't just return failure175 * because that would lead to spurious failures where176 * futex_down_timeout returns ETIMEOUT despite there being177 * available tokens. That could break some algorithms.178 * We also don't want to loop on CAS indefinitely, because179 * that would make the semaphore not wait-free, even when all180 * atomic operations and the underlying base semaphore are all181 * wait-free.182 * Instead, we fall back to regular down_timeout(), with183 * an already expired deadline. That way we delegate all these184 * concerns to the base semaphore.185 */186 }187 188 156 /* 189 157 * This combination of a "composable" sleep followed by futex_up() on … … 208 176 { 209 177 /* 210 * down_timeout with an already expired deadline should behave like 211 * trydown. 178 * We can't just use CAS here. 179 * If we don't succeed with CAS, we can't return failure 180 * because that would lead to spurious failures where 181 * futex_down_timeout returns ETIMEOUT despite there being 182 * available tokens. That would break some algorithms. 183 * We also don't want to loop on CAS indefinitely, because 184 * that would make the semaphore not wait-free, even when all 185 * atomic operations and the underlying base semaphore are all 186 * wait-free. 187 * It's much less trouble (and code bloat) to just do regular 188 * down_timeout(), with an already expired deadline. 212 189 */ 213 190 struct timespec tv = { .tv_sec = 0, .tv_nsec = 0 };
Note:
See TracChangeset
for help on using the changeset viewer.