Index: lib/asan/asan_thread.cc =================================================================== --- lib/asan/asan_thread.cc +++ lib/asan/asan_thread.cc @@ -433,6 +433,14 @@ __asan::asanThreadRegistry().Unlock(); } +void LockThreadRegistryRead() { + __asan::asanThreadRegistry().ReadLock(); +} + +void UnlockThreadRegistryRead() { + __asan::asanThreadRegistry().ReadUnlock(); +} + void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); } Index: lib/lsan/lsan_common.h =================================================================== --- lib/lsan/lsan_common.h +++ lib/lsan/lsan_common.h @@ -161,6 +161,8 @@ // Wrappers for ThreadRegistry access. void LockThreadRegistry(); void UnlockThreadRegistry(); +void LockThreadRegistryRead(); +void UnlockThreadRegistryRead(); bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, uptr *tls_begin, uptr *tls_end, uptr *cache_begin, uptr *cache_end, DTLS **dtls); Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -439,11 +439,11 @@ EnsureMainThreadIDIsCorrect(); CheckForLeaksParam param; param.success = false; - LockThreadRegistry(); + LockThreadRegistryRead(); LockAllocator(); DoStopTheWorld(CheckForLeaksCallback, ¶m); UnlockAllocator(); - UnlockThreadRegistry(); + UnlockThreadRegistryRead(); if (!param.success) { Report("LeakSanitizer has encountered a fatal error.\n"); Index: lib/lsan/lsan_thread.cc =================================================================== --- lib/lsan/lsan_thread.cc +++ lib/lsan/lsan_thread.cc @@ -164,4 +164,12 @@ thread_registry->Unlock(); } +void LockThreadRegistryRead() { + thread_registry->ReadLock(); +} + +void UnlockThreadRegistryRead() { + thread_registry->ReadUnlock(); +} + } // namespace __lsan Index: lib/sanitizer_common/sanitizer_thread_registry.h =================================================================== --- lib/sanitizer_common/sanitizer_thread_registry.h +++ lib/sanitizer_common/sanitizer_thread_registry.h @@ -87,6 +87,8 @@ void Lock() { mtx_.Lock(); } void CheckLocked() { mtx_.CheckLocked(); } void Unlock() { mtx_.Unlock(); } + void ReadLock() { mtx_.ReadLock(); } + void ReadUnlock() { mtx_.ReadUnlock(); } // Should be guarded by ThreadRegistryLock. ThreadContextBase *GetThreadLocked(u32 tid) { @@ -124,7 +126,7 @@ const u32 thread_quarantine_size_; const u32 max_reuse_; - BlockingMutex mtx_; + RWMutex mtx_; u32 n_contexts_; // Number of created thread contexts, // at most max_threads_. Index: lib/sanitizer_common/sanitizer_thread_registry.cc =================================================================== --- lib/sanitizer_common/sanitizer_thread_registry.cc +++ lib/sanitizer_common/sanitizer_thread_registry.cc @@ -108,20 +108,20 @@ void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, uptr *alive) { - BlockingMutexLock l(&mtx_); + RWMutexReadLock l(&mtx_); if (total) *total = n_contexts_; if (running) *running = running_threads_; if (alive) *alive = alive_threads_; } uptr ThreadRegistry::GetMaxAliveThreads() { - BlockingMutexLock l(&mtx_); + RWMutexReadLock l(&mtx_); return max_alive_threads_; } u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); u32 tid = kUnknownTid; ThreadContextBase *tctx = QuarantinePop(); if (tctx) { @@ -167,7 +167,7 @@ } u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); for (u32 tid = 0; tid < n_contexts_; tid++) { ThreadContextBase *tctx = threads_[tid]; if (tctx != 0 && cb(tctx, arg)) @@ -199,7 +199,7 @@ } void ThreadRegistry::SetThreadName(u32 tid, const char *name) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); CHECK_LT(tid, n_contexts_); ThreadContextBase *tctx = threads_[tid]; CHECK_NE(tctx, 0); @@ -208,7 +208,7 @@ } void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); for (u32 tid = 0; tid < n_contexts_; tid++) { ThreadContextBase *tctx = threads_[tid]; if (tctx != 0 && tctx->user_id == user_id && @@ -220,7 +220,7 @@ } void ThreadRegistry::DetachThread(u32 tid, void *arg) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); CHECK_LT(tid, n_contexts_); ThreadContextBase *tctx = threads_[tid]; CHECK_NE(tctx, 0); @@ -238,7 +238,7 @@ } void ThreadRegistry::JoinThread(u32 tid, void *arg) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); CHECK_LT(tid, n_contexts_); ThreadContextBase *tctx = threads_[tid]; CHECK_NE(tctx, 0); @@ -251,7 +251,7 @@ } void ThreadRegistry::FinishThread(u32 tid) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); CHECK_GT(alive_threads_, 0); alive_threads_--; CHECK_GT(running_threads_, 0); @@ -269,7 +269,7 @@ void ThreadRegistry::StartThread(u32 tid, uptr os_id, bool workerthread, void *arg) { - BlockingMutexLock l(&mtx_); + RWMutexLock l(&mtx_); running_threads_++; CHECK_LT(tid, n_contexts_); ThreadContextBase *tctx = threads_[tid]; Index: lib/tsan/rtl/tsan_rtl.cc =================================================================== --- lib/tsan/rtl/tsan_rtl.cc +++ lib/tsan/rtl/tsan_rtl.cc @@ -455,18 +455,18 @@ #if !SANITIZER_GO void ForkBefore(ThreadState *thr, uptr pc) { - ctx->thread_registry->Lock(); + ctx->thread_registry->ReadLock(); ctx->report_mtx.Lock(); } void ForkParentAfter(ThreadState *thr, uptr pc) { ctx->report_mtx.Unlock(); - ctx->thread_registry->Unlock(); + ctx->thread_registry->ReadUnlock(); } void ForkChildAfter(ThreadState *thr, uptr pc) { ctx->report_mtx.Unlock(); - ctx->thread_registry->Unlock(); + ctx->thread_registry->ReadUnlock(); uptr nthread = 0; ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);