diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -506,22 +507,42 @@ } BlockingMutex::BlockingMutex() { + // Initialize all member variables to 0 internal_memset(this, 0, sizeof(*this)); + static_assert(sizeof(os_unfair_lock_t) <= sizeof(opaque_storage_), + "Not enough space in opaque storage to use os_unfair_lock"); + static_assert(sizeof(OSSpinLock) <= sizeof(opaque_storage_), + "Not enough space in opaque storage to use OSSpinLock"); } +static bool UnfairLockAvailable() { return bool(os_unfair_lock_lock); } +static_assert(OS_UNFAIR_LOCK_INIT._os_unfair_lock_opaque == 0, + "os_unfair_lock does not initialize to 0"); +static_assert(OS_SPINLOCK_INIT == 0, "OSSpinLock does not initialize to 0"); + void BlockingMutex::Lock() { - CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); - CHECK_EQ(OS_SPINLOCK_INIT, 0); CHECK_EQ(owner_, 0); - OSSpinLockLock((OSSpinLock*)&opaque_storage_); + if (UnfairLockAvailable()) { + os_unfair_lock_lock((os_unfair_lock *)&opaque_storage_); + } else { + OSSpinLockLock((OSSpinLock *)&opaque_storage_); + } } void BlockingMutex::Unlock() { - OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); + if (UnfairLockAvailable()) { + os_unfair_lock_unlock((os_unfair_lock *)&opaque_storage_); + } else { + OSSpinLockUnlock((OSSpinLock *)&opaque_storage_); + } } void BlockingMutex::CheckLocked() { - CHECK_NE(*(OSSpinLock*)&opaque_storage_, 0); + if (UnfairLockAvailable()) { + CHECK_NE((*(os_unfair_lock *)&opaque_storage_)._os_unfair_lock_opaque, 0); + } else { + CHECK_NE(*(OSSpinLock *)&opaque_storage_, 0); + } } u64 NanoTime() {