diff --git a/Utilities/sync.h b/Utilities/sync.h index f6b1a4fc17..2d805ff14c 100644 --- a/Utilities/sync.h +++ b/Utilities/sync.h @@ -17,6 +17,8 @@ #include #include #include +#elif __APPLE__ +#include #endif #ifdef _WIN32 @@ -76,6 +78,46 @@ inline int futex(volatile void* uaddr, int futex_op, uint val, const timespec* t { #ifdef __linux__ return syscall(SYS_futex, uaddr, futex_op, static_cast(val), timeout, nullptr, static_cast(mask)); +#elif __APPLE__ + switch (futex_op) + { + case FUTEX_WAIT_PRIVATE: + case FUTEX_WAIT_BITSET_PRIVATE: + { + if (timeout) + { + const uint64_t nsec = timeout->tv_nsec + timeout->tv_sec * 1000000000ull; + return os_sync_wait_on_address_with_timeout(const_cast(uaddr), static_cast(val), sizeof(uint), OS_SYNC_WAIT_ON_ADDRESS_NONE, OS_CLOCK_MACH_ABSOLUTE_TIME, nsec); + } + else + { + return os_sync_wait_on_address(const_cast(uaddr), static_cast(val), sizeof(uint), OS_SYNC_WAIT_ON_ADDRESS_NONE); + } + } + + case FUTEX_WAKE_PRIVATE: + case FUTEX_WAKE_BITSET_PRIVATE: + { + for (;;) + { + int ret = 0; + if (val == INT32_MAX) + { + ret = os_sync_wake_by_address_all(const_cast(uaddr), sizeof(uint), OS_SYNC_WAKE_BY_ADDRESS_NONE); + } + else if (val-- >= 0) + { + ret = os_sync_wake_by_address_any(const_cast(uaddr), sizeof(uint), OS_SYNC_WAKE_BY_ADDRESS_NONE); + } + if (val <= 0 || val == INT32_MAX || (ret < 0 && errno == ENOENT)) + { + return ret; + } + } + } + } + errno = EINVAL; + return -1; #else static struct futex_manager {