Index: compiler-rt/trunk/lib/tsan/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/tsan/CMakeLists.txt +++ compiler-rt/trunk/lib/tsan/CMakeLists.txt @@ -47,6 +47,7 @@ if(APPLE) list(APPEND TSAN_SOURCES + rtl/tsan_interceptors_mac.cc rtl/tsan_libdispatch_mac.cc rtl/tsan_platform_mac.cc rtl/tsan_platform_posix.cc) Index: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc =================================================================== --- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -0,0 +1,91 @@ +//===-- tsan_interceptors_mac.cc ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer (TSan), a race detector. +// +// Mac-specific interceptors. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_MAC + +#include "interception/interception.h" +#include "tsan_interceptors.h" + +#include + +namespace __tsan { + +TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockLock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockLock, lock); + REAL(OSSpinLockLock)(lock); + Acquire(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, OSSpinLockTry, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockTry)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockTry, lock); + bool result = REAL(OSSpinLockTry)(lock); + if (result) + Acquire(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(OSSpinLockUnlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(OSSpinLockUnlock, lock); + Release(thr, pc, (uptr)lock); + REAL(OSSpinLockUnlock)(lock); +} + +TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(os_lock_lock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_lock, lock); + REAL(os_lock_lock)(lock); + Acquire(thr, pc, (uptr)lock); +} + +TSAN_INTERCEPTOR(bool, os_lock_trylock, void *lock) { + CHECK(!cur_thread()->is_dead); + 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) + Acquire(thr, pc, (uptr)lock); + return result; +} + +TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) { + CHECK(!cur_thread()->is_dead); + if (!cur_thread()->is_inited) { + return REAL(os_lock_unlock)(lock); + } + SCOPED_TSAN_INTERCEPTOR(os_lock_unlock, lock); + Release(thr, pc, (uptr)lock); + REAL(os_lock_unlock)(lock); +} + +} // namespace __tsan + +#endif // SANITIZER_MAC Index: compiler-rt/trunk/test/tsan/Darwin/osspinlock-norace.cc =================================================================== --- compiler-rt/trunk/test/tsan/Darwin/osspinlock-norace.cc +++ compiler-rt/trunk/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