diff options
author | Greg V <[email protected]> | 2017-12-24 19:55:46 +0300 |
---|---|---|
committer | Eric Engestrom <[email protected]> | 2019-03-03 19:48:49 +0000 |
commit | 7dc2f4788288ec9c7ab63e37fdea750c08503eca (patch) | |
tree | 9520c79d0cee45d00ec379d81456986bc41658d7 | |
parent | 00f838fa730f5c765902fe2e5ce9754df5276e91 (diff) |
util: emulate futex on FreeBSD using umtx
Obtained from: FreeBSD ports
Acked-by: Emil Velikov <[email protected]>
Acked-by: Eric Engestrom <[email protected]>
-rw-r--r-- | src/util/futex.h | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/util/futex.h b/src/util/futex.h index 4402893069d..a8b2c0f3527 100644 --- a/src/util/futex.h +++ b/src/util/futex.h @@ -51,6 +51,40 @@ static inline int futex_wait(uint32_t *addr, int32_t value, const struct timespe FUTEX_BITSET_MATCH_ANY); } +#elif defined(__FreeBSD__) + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/umtx.h> +#include <sys/time.h> + +static inline int futex_wake(uint32_t *addr, int count) +{ + assert(count == (int)(uint32_t)count); /* Check that bits weren't discarded */ + return _umtx_op(addr, UMTX_OP_WAKE, (uint32_t)count, NULL, NULL) == -1 ? errno : 0; +} + +static inline int futex_wait(uint32_t *addr, int32_t value, struct timespec *timeout) +{ + void *uaddr = NULL, *uaddr2 = NULL; + + assert(value == (int)(uint32_t)value); /* Check that bits weren't discarded */ + + if (timeout != NULL) { + const struct _umtx_time tmo = { + ._timeout = *timeout, + ._flags = UMTX_ABSTIME, + ._clockid = CLOCK_MONOTONIC + }; + uaddr = (void *)(uintptr_t)sizeof(tmo); + uaddr2 = (void *)&tmo; + } + + return _umtx_op(addr, UMTX_OP_WAIT_UINT, (uint32_t)value, uaddr, uaddr2) == -1 ? errno : 0; +} + #endif #endif /* UTIL_FUTEX_H */ |