patomic: Implement futexes on macOS using ulock API

This is what is also used by the libc++ futex implementation on macOS, and should be more efficient than the fallback hash table approach
This commit is contained in:
rdb 2023-10-21 14:46:51 +02:00
parent 78f8e1eaa9
commit 034f1ea358
3 changed files with 17 additions and 2 deletions

View File

@ -433,6 +433,8 @@ patomic_wait(const volatile uint32_t *value, uint32_t old) {
while (*value == old) {
_patomic_wait_func((volatile void *)value, &old, sizeof(uint32_t), INFINITE);
}
#elif defined(__APPLE__)
__ulock_wait(UL_COMPARE_AND_WAIT, (void *)value, old, 0);
#elif defined(HAVE_POSIX_THREADS)
_patomic_wait(value, old);
#else
@ -451,6 +453,8 @@ patomic_notify_one(volatile uint32_t *value) {
// WakeByAddressSingle((void *)value);
#elif defined(_WIN32)
_patomic_wake_one_func((void *)value);
#elif defined(__APPLE__)
__ulock_wake(UL_COMPARE_AND_WAIT, (void *)value, 0);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);
#endif
@ -467,6 +471,8 @@ patomic_notify_all(volatile uint32_t *value) {
// WakeByAddressAll((void *)value);
#elif defined(_WIN32)
_patomic_wake_all_func((void *)value);
#elif defined(__APPLE__)
__ulock_wake(UL_COMPARE_AND_WAIT | ULF_WAKE_ALL, (void *)value, 0);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);
#endif

View File

@ -125,7 +125,7 @@ initialize_wait(volatile VOID *addr, PVOID cmp, SIZE_T size, DWORD timeout) {
return emulated_wait(addr, cmp, size, timeout);
}
#elif !defined(CPPPARSER) && !defined(__linux__) && defined(HAVE_POSIX_THREADS)
#elif !defined(CPPPARSER) && !defined(__linux__) && !defined(__APPLE__) && defined(HAVE_POSIX_THREADS)
// Same as above, but using pthreads.
struct alignas(64) WaitTableEntry {

View File

@ -32,6 +32,15 @@
#include <unistd.h>
#endif
#ifdef __APPLE__
// Undocumented API, see https://outerproduct.net/futex-dictionary.html
#define UL_COMPARE_AND_WAIT 1
#define ULF_WAKE_ALL 0x00000100
extern "C" int __ulock_wait(uint32_t op, void *addr, uint64_t value, uint32_t timeout);
extern "C" int __ulock_wake(uint32_t op, void *addr, uint64_t wake_value);
#endif
#if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
/**
@ -164,7 +173,7 @@ ALWAYS_INLINE void patomic_notify_all(volatile uint32_t *value);
EXPCL_DTOOL_DTOOLBASE extern BOOL (__stdcall *_patomic_wait_func)(volatile VOID *, PVOID, SIZE_T, DWORD);
EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_one_func)(PVOID);
EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_all_func)(PVOID);
#elif !defined(__linux__) && defined(HAVE_POSIX_THREADS)
#elif !defined(__linux__) && !defined(__APPLE__) && defined(HAVE_POSIX_THREADS)
EXPCL_DTOOL_DTOOLBASE void _patomic_wait(const volatile uint32_t *value, uint32_t old);
EXPCL_DTOOL_DTOOLBASE void _patomic_notify_all(volatile uint32_t *value);
#endif