Index: lib/tsan/rtl/tsan_platform_mac.cc =================================================================== --- lib/tsan/rtl/tsan_platform_mac.cc +++ lib/tsan/rtl/tsan_platform_mac.cc @@ -15,15 +15,18 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_MAC +#include "interception/interception.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_posix.h" #include "sanitizer_common/sanitizer_procmaps.h" +#include "tsan_interceptors.h" #include "tsan_platform.h" #include "tsan_rtl.h" #include "tsan_flags.h" +#include #include #include #include @@ -184,6 +187,64 @@ return false; } +TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) { + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockLock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockLock, lock); + REAL(OSSpinLockLock)(lock); + MutexLock(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, OSSpinLockTry, volatile OSSpinLock *lock) { + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockTry)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockTry, lock); + bool result = REAL(OSSpinLockTry)(lock); + if (result) + MutexLock(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) { + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockUnlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockUnlock, lock); + MutexUnlock(thr, pc, (uptr)lock); + REAL(OSSpinLockUnlock)(lock); +} + +TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) { + if (!cur_thread()->is_inited) { + return REAL(os_lock_lock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_lock, lock); + REAL(os_lock_lock)(lock); + MutexLock(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, os_lock_trylock, void *lock) { + if (!cur_thread()->is_inited) { + return REAL(os_lock_trylock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_trylock, lock); + bool result = REAL(os_lock_trylock)(lock); + if (result) + MutexLock(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) { + if (!cur_thread()->is_inited) { + return REAL(os_lock_unlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_unlock, lock); + MutexUnlock(thr, pc, (uptr)lock); + REAL(os_lock_unlock)(lock); +} + } // namespace __tsan #endif // SANITIZER_MAC Index: test/tsan/Darwin/osspinlock-norace.cc =================================================================== --- test/tsan/Darwin/osspinlock-norace.cc +++ test/tsan/Darwin/osspinlock-norace.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +#include +#include +#include + +int Global; +OSSpinLock lock; + +void *Thread(void *x) { + OSSpinLockLock(&lock); + Global++; + OSSpinLockUnlock(&lock); + return NULL; +} + +int main() { + fprintf(stderr, "Hello world.\n"); + + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread, NULL); + pthread_create(&t[1], NULL, Thread, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + + fprintf(stderr, "Done.\n"); +} + +// CHECK: Hello world. +// CHECK: Done. +// CHECK-NOT: WARNING: ThreadSanitizer