diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp @@ -125,6 +125,16 @@ RawInternalFree(addr, cache); } +void InternalAllocatorLock() NO_THREAD_SAFETY_ANALYSIS { + internal_allocator_cache_mu.Lock(); + internal_allocator()->ForceLock(); +} + +void InternalAllocatorUnlock() NO_THREAD_SAFETY_ANALYSIS { + internal_allocator()->ForceUnlock(); + internal_allocator_cache_mu.Unlock(); +} + // LowLevelAllocator constexpr uptr kLowLevelAllocatorDefaultAlignment = 8; static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h @@ -48,6 +48,8 @@ void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache = nullptr); void InternalFree(void *p, InternalAllocatorCache *cache = nullptr); +void InternalAllocatorLock(); +void InternalAllocatorUnlock(); InternalAllocator *internal_allocator(); } // namespace __sanitizer diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.h b/compiler-rt/lib/tsan/rtl/tsan_mman.h --- a/compiler-rt/lib/tsan/rtl/tsan_mman.h +++ b/compiler-rt/lib/tsan/rtl/tsan_mman.h @@ -24,6 +24,8 @@ void AllocatorProcStart(Processor *proc); void AllocatorProcFinish(Processor *proc); void AllocatorPrintStats(); +void AllocatorLock(); +void AllocatorUnlock(); // For user allocations. void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz, diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp @@ -110,6 +110,16 @@ gp->mtx.Unlock(); } +void AllocatorLock() NO_THREAD_SAFETY_ANALYSIS { + global_proc()->mtx.Lock(); + InternalAllocatorLock(); +} + +void AllocatorUnlock() NO_THREAD_SAFETY_ANALYSIS { + InternalAllocatorUnlock(); + global_proc()->mtx.Unlock(); +} + static constexpr uptr kMaxAllowedMallocSize = 1ull << 40; static uptr max_user_defined_malloc_size; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -494,6 +494,7 @@ ctx->thread_registry.Lock(); ctx->report_mtx.Lock(); ScopedErrorReportLock::Lock(); + AllocatorLock(); // Suppress all reports in the pthread_atfork callbacks. // Reports will deadlock on the report_mtx. // We could ignore sync operations as well, @@ -512,6 +513,7 @@ void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + AllocatorUnlock(); ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry.Unlock(); @@ -521,6 +523,7 @@ bool start_thread) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + AllocatorUnlock(); ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry.Unlock(); @@ -755,7 +758,7 @@ {MutexInvalid, "Invalid", {}}, {MutexThreadRegistry, "ThreadRegistry", {}}, {MutexTypeTrace, "Trace", {MutexLeaf}}, - {MutexTypeReport, "Report", {MutexTypeSyncVar}}, + {MutexTypeReport, "Report", {MutexTypeSyncVar, MutexTypeGlobalProc}}, {MutexTypeSyncVar, "SyncVar", {}}, {MutexTypeAnnotations, "Annotations", {}}, {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}},