Changeset b59318e in mainline for uspace/lib/c/include/futex.h
- Timestamp:
- 2018-06-26T17:34:48Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ab6edb6
- Parents:
- f6372be9
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:01:43)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:34:48)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/include/futex.h
rf6372be9 rb59318e 36 36 #define LIBC_FUTEX_H_ 37 37 38 #include <assert.h> 38 39 #include <atomic.h> 39 40 #include <errno.h> … … 98 99 } 99 100 100 /** Down the futex. 101 /** Down the futex with timeout, composably. 102 * 103 * This means that when the operation fails due to a timeout or being 104 * interrupted, the next futex_up() is ignored, which allows certain kinds of 105 * composition of synchronization primitives. 106 * 107 * In most other circumstances, regular futex_down_timeout() is a better choice. 101 108 * 102 109 * @param futex Futex. 103 110 * 104 111 * @return ENOENT if there is no such virtual address. 112 * @return ETIMEOUT if timeout expires. 105 113 * @return EOK on success. 106 114 * @return Error code from <errno.h> otherwise. 107 115 * 108 116 */ 109 static inline errno_t futex_down (futex_t *futex)117 static inline errno_t futex_down_composable(futex_t *futex, struct timeval *expires) 110 118 { 119 // TODO: Add tests for this. 120 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)) { 128 /* We can't just return ETIMEOUT. That wouldn't be composable. */ 129 timeout = 1; 130 } else { 131 timeout = tv_sub_diff(expires, &tv); 132 } 133 134 assert(timeout > 0); 135 } 136 111 137 if ((atomic_signed_t) atomic_predec(&futex->val) < 0) 112 return (errno_t) __SYSCALL 1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count);138 return (errno_t) __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout); 113 139 114 140 return EOK; … … 132 158 } 133 159 160 static inline errno_t futex_down_timeout(futex_t *futex, struct timeval *expires) 161 { 162 /* 163 * This combination of a "composable" sleep followed by futex_up() on 164 * failure is necessary to prevent breakage due to certain race 165 * conditions. 166 */ 167 errno_t rc = futex_down_composable(futex, expires); 168 if (rc != EOK) 169 futex_up(futex); 170 return rc; 171 } 172 173 /** Down the futex. 174 * 175 * @param futex Futex. 176 * 177 * @return ENOENT if there is no such virtual address. 178 * @return EOK on success. 179 * @return Error code from <errno.h> otherwise. 180 * 181 */ 182 static inline errno_t futex_down(futex_t *futex) 183 { 184 return futex_down_timeout(futex, NULL); 185 } 186 134 187 #endif 135 188
Note:
See TracChangeset
for help on using the changeset viewer.