Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -228,6 +228,16 @@ libignore()->OnLibraryLoaded(0); } +// The following two hooks can be used by for cooperative scheduling when +// locking. +#ifdef TSAN_EXTERNAL_HOOKS +void OnPotentiallyBlockingRegionBegin(); +void OnPotentiallyBlockingRegionEnd(); +#else +SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {} +SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {} +#endif + } // namespace __tsan static ThreadSignalContext *SigCtx(ThreadState *thr) { @@ -866,6 +876,8 @@ // Used in thread-safe function static initialization. STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) { SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g); + OnPotentiallyBlockingRegionBegin(); + auto on_exit = at_scope_exit(&OnPotentiallyBlockingRegionEnd); for (;;) { u32 cmp = atomic_load(g, memory_order_acquire); if (cmp == 0) { Index: test/tsan/cxa_guard_acquire.cc =================================================================== --- test/tsan/cxa_guard_acquire.cc +++ test/tsan/cxa_guard_acquire.cc @@ -0,0 +1,25 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +#include + +namespace __tsan { + +void OnPotentiallyBlockingRegionBegin() { + printf("Enter __cxa_guard_acquire\n"); +} + +void OnPotentiallyBlockingRegionEnd() { printf("Exit __cxa_guard_acquire\n"); } + +} // namespace __tsan + +int main(int argc, char **argv) { + // CHECK: Enter main + printf("Enter main\n"); + // CHECK-NEXT: Enter __cxa_guard_acquire + // CHECK-NEXT: Exit __cxa_guard_acquire + static int s = argc; + (void)s; + // CHECK-NEXT: Exit main + printf("Exit main\n"); + return 0; +}