patomic: Fix support for macOS pre-10.12

For now we will unconditionally use ulock APIs on arm64 (which requires macOS 11 anyway) and weak-link it (with fallback to pthreads implementation) on Intel

See also #1780
This commit is contained in:
rdb 2025-12-18 13:41:38 +01:00
parent 4705b32943
commit 6acdcc5a8a
3 changed files with 22 additions and 5 deletions

View File

@ -454,6 +454,12 @@ patomic_notify_one(volatile uint32_t *value) {
#elif defined(_WIN32)
_patomic_wake_one_func((void *)value);
#elif defined(__APPLE__)
#ifndef __arm64__
if (UNLIKELY(__ulock_wake == nullptr || __ulock_wait == nullptr)) {
_patomic_notify_all(value);
return;
}
#endif
__ulock_wake(UL_COMPARE_AND_WAIT, (void *)value, 0);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);
@ -472,6 +478,12 @@ patomic_notify_all(volatile uint32_t *value) {
#elif defined(_WIN32)
_patomic_wake_all_func((void *)value);
#elif defined(__APPLE__)
#ifndef __arm64__
if (UNLIKELY(__ulock_wake == nullptr || __ulock_wait == nullptr)) {
_patomic_notify_all(value);
return;
}
#endif
__ulock_wake(UL_COMPARE_AND_WAIT | ULF_WAKE_ALL, (void *)value, 0);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);

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(__APPLE__) && defined(HAVE_POSIX_THREADS)
#elif !defined(CPPPARSER) && !defined(__linux__) && (!defined(__APPLE__) || !defined(__arm64__)) && defined(HAVE_POSIX_THREADS)
// Same as above, but using pthreads.
struct alignas(64) WaitTableEntry {

View File

@ -36,9 +36,6 @@
// 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)
@ -173,9 +170,17 @@ 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(__APPLE__) && defined(HAVE_POSIX_THREADS)
#elif defined(__APPLE__) && defined(__arm64__)
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);
#elif !defined(__linux__) && 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);
#ifdef __APPLE__
// Use conditionally since we can't count on support before 10.12.
extern "C" int __ulock_wait(uint32_t op, void *addr, uint64_t value, uint32_t timeout) __attribute__((weak_import));
extern "C" int __ulock_wake(uint32_t op, void *addr, uint64_t wake_value) __attribute__((weak_import));
#endif
#endif
#include "patomic.I"