From 034f1ea3587b32de558399c30a86f84b68828db0 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 21 Oct 2023 14:46:51 +0200 Subject: [PATCH] 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 --- dtool/src/dtoolbase/patomic.I | 6 ++++++ dtool/src/dtoolbase/patomic.cxx | 2 +- dtool/src/dtoolbase/patomic.h | 11 ++++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/dtool/src/dtoolbase/patomic.I b/dtool/src/dtoolbase/patomic.I index 346ca8cfed..d1395c9e90 100644 --- a/dtool/src/dtoolbase/patomic.I +++ b/dtool/src/dtoolbase/patomic.I @@ -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 diff --git a/dtool/src/dtoolbase/patomic.cxx b/dtool/src/dtoolbase/patomic.cxx index 58d52a7e42..1b939a58c6 100644 --- a/dtool/src/dtoolbase/patomic.cxx +++ b/dtool/src/dtoolbase/patomic.cxx @@ -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 { diff --git a/dtool/src/dtoolbase/patomic.h b/dtool/src/dtoolbase/patomic.h index 604d028392..02d1ab6ebc 100644 --- a/dtool/src/dtoolbase/patomic.h +++ b/dtool/src/dtoolbase/patomic.h @@ -32,6 +32,15 @@ #include #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