Changeset 710c1e9 in mainline
- Timestamp:
- 2018-07-13T16:54:22Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 868d75c
- Parents:
- e3787a0
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-01 17:23:12)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-13 16:54:22)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/futex.h
re3787a0 r710c1e9 86 86 #endif 87 87 88 /** Try to down the futex.89 *90 * @param futex Futex.91 *92 * @return true if the futex was acquired.93 * @return false if the futex was not acquired.94 *95 */96 static inline bool futex_trydown(futex_t *futex)97 {98 return cas(&futex->val, 1, 0);99 }100 101 88 /** Down the futex with timeout, composably. 102 89 * … … 115 102 * 116 103 */ 117 static inline errno_t futex_down_composable(futex_t *futex, struct timeval *expires)104 static inline errno_t futex_down_composable(futex_t *futex, const struct timeval *expires) 118 105 { 119 106 // TODO: Add tests for this. 120 107 121 /* No timeout by default. */ 122 suseconds_t timeout = 0; 123 124 if (expires) { 125 struct timeval tv; 126 getuptime(&tv); 127 if (tv_gteq(&tv, expires)) { 108 if ((atomic_signed_t) atomic_predec(&futex->val) >= 0) 109 return EOK; 110 111 suseconds_t timeout; 112 113 if (!expires) { 114 /* No timeout. */ 115 timeout = 0; 116 } else { 117 if (expires->tv_sec == 0) { 128 118 /* We can't just return ETIMEOUT. That wouldn't be composable. */ 129 119 timeout = 1; 130 120 } else { 131 timeout = tv_sub_diff(expires, &tv); 121 struct timeval tv; 122 getuptime(&tv); 123 timeout = tv_gteq(&tv, expires) ? 1 : 124 tv_sub_diff(expires, &tv); 132 125 } 133 126 … … 135 128 } 136 129 137 if ((atomic_signed_t) atomic_predec(&futex->val) < 0) 138 return (errno_t) __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout); 139 140 return EOK; 130 return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout); 141 131 } 142 132 … … 153 143 { 154 144 if ((atomic_signed_t) atomic_postinc(&futex->val) < 0) 155 return (errno_t)__SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count);145 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count); 156 146 157 147 return EOK; 158 148 } 159 149 160 static inline errno_t futex_down_timeout(futex_t *futex, struct timeval *expires) 161 { 150 static inline errno_t futex_down_timeout(futex_t *futex, const struct timeval *expires) 151 { 152 if (expires && expires->tv_sec == 0 && expires->tv_usec == 0) { 153 /* Nonblocking down. */ 154 155 /* 156 * Try good old CAS a few times. 157 * Not too much though, we don't want to bloat the caller. 158 */ 159 for (int i = 0; i < 2; i++) { 160 atomic_signed_t old = atomic_get(&futex->val); 161 if (old <= 0) 162 return ETIMEOUT; 163 164 if (cas(&futex->val, old, old - 1)) 165 return EOK; 166 } 167 168 // TODO: builtin atomics with relaxed ordering can make this 169 // faster. 170 171 /* 172 * If we don't succeed with CAS, we can't just return failure 173 * because that would lead to spurious failures where 174 * futex_down_timeout returns ETIMEOUT despite there being 175 * available tokens. That could break some algorithms. 176 * We also don't want to loop on CAS indefinitely, because 177 * that would make the semaphore not wait-free, even when all 178 * atomic operations and the underlying base semaphore are all 179 * wait-free. 180 * Instead, we fall back to regular down_timeout(), with 181 * an already expired deadline. That way we delegate all these 182 * concerns to the base semaphore. 183 */ 184 } 185 162 186 /* 163 187 * This combination of a "composable" sleep followed by futex_up() on … … 171 195 } 172 196 197 /** Try to down the futex. 198 * 199 * @param futex Futex. 200 * 201 * @return true if the futex was acquired. 202 * @return false if the futex was not acquired. 203 * 204 */ 205 static inline bool futex_trydown(futex_t *futex) 206 { 207 /* 208 * down_timeout with an already expired deadline should behave like 209 * trydown. 210 */ 211 struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; 212 return futex_down_timeout(futex, &tv) == EOK; 213 } 214 173 215 /** Down the futex. 174 216 *
Note:
See TracChangeset
for help on using the changeset viewer.