diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index a8d2feaa31c8..801478a00151 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -228,6 +228,16 @@ void InitializeLibIgnore() { 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 @@ TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { // 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) { diff --git a/compiler-rt/test/tsan/cxa_guard_acquire.cc b/compiler-rt/test/tsan/cxa_guard_acquire.cc new file mode 100644 index 000000000000..cdbe609003d4 --- /dev/null +++ b/compiler-rt/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; +}