From ce85e03620f64ce7e4cd0598f2e93090f52a9e99 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 19 Mar 2013 12:25:48 +0000 Subject: tsan: flush dead thread info earlier (when another thread is finished rather than new thread is created) git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177394 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_thread_registry.cc | 51 ++++++++++++++--------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'lib/sanitizer_common/sanitizer_thread_registry.cc') diff --git a/lib/sanitizer_common/sanitizer_thread_registry.cc b/lib/sanitizer_common/sanitizer_thread_registry.cc index 3d246feee..5b3dacc56 100644 --- a/lib/sanitizer_common/sanitizer_thread_registry.cc +++ b/lib/sanitizer_common/sanitizer_thread_registry.cc @@ -77,11 +77,11 @@ void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id, OnCreated(arg); } -void ThreadContextBase::Reset(void *arg) { +void ThreadContextBase::Reset() { status = ThreadStatusInvalid; reuse_count++; SetName(0); - OnReset(arg); + OnReset(); } // ThreadRegistry implementation. @@ -102,6 +102,7 @@ ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads, threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]), "ThreadRegistry"); dead_threads_.clear(); + invalid_threads_.clear(); } void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running, @@ -121,25 +122,18 @@ u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg) { BlockingMutexLock l(&mtx_); u32 tid = kUnknownTid; - ThreadContextBase *tctx = 0; - if (dead_threads_.size() > thread_quarantine_size_ || - n_contexts_ >= max_threads_) { - // Reusing old thread descriptor and tid. - if (dead_threads_.size() == 0) { - Report("%s: Thread limit (%u threads) exceeded. Dying.\n", - SanitizerToolName, max_threads_); - Die(); - } - tctx = dead_threads_.front(); - dead_threads_.pop_front(); - CHECK_EQ(ThreadStatusDead, tctx->status); - tctx->Reset(arg); + ThreadContextBase *tctx = QuarantinePop(); + if (tctx) { tid = tctx->tid; - } else { + } else if (n_contexts_ < max_threads_) { // Allocate new thread context and tid. tid = n_contexts_++; tctx = context_factory_(tid); threads_[tid] = tctx; + } else { + Report("%s: Thread limit (%u threads) exceeded. Dying.\n", + SanitizerToolName, max_threads_); + Die(); } CHECK_NE(tctx, 0); CHECK_NE(tid, kUnknownTid); @@ -207,7 +201,7 @@ void ThreadRegistry::DetachThread(u32 tid) { } if (tctx->status == ThreadStatusFinished) { tctx->SetDead(); - dead_threads_.push_back(tctx); + QuarantinePush(tctx); } else { tctx->detached = true; } @@ -223,7 +217,7 @@ void ThreadRegistry::JoinThread(u32 tid, void *arg) { return; } tctx->SetJoined(arg); - dead_threads_.push_back(tctx); + QuarantinePush(tctx); } void ThreadRegistry::FinishThread(u32 tid) { @@ -239,7 +233,7 @@ void ThreadRegistry::FinishThread(u32 tid) { tctx->SetFinished(); if (tctx->detached) { tctx->SetDead(); - dead_threads_.push_back(tctx); + QuarantinePush(tctx); } } @@ -253,4 +247,23 @@ void ThreadRegistry::StartThread(u32 tid, uptr os_id, void *arg) { tctx->SetStarted(os_id, arg); } +void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) { + dead_threads_.push_back(tctx); + if (dead_threads_.size() <= thread_quarantine_size_) + return; + tctx = dead_threads_.front(); + dead_threads_.pop_front(); + CHECK_EQ(tctx->status, ThreadStatusDead); + tctx->Reset(); + invalid_threads_.push_back(tctx); +} + +ThreadContextBase *ThreadRegistry::QuarantinePop() { + if (invalid_threads_.size() == 0) + return 0; + ThreadContextBase *tctx = invalid_threads_.front(); + invalid_threads_.pop_front(); + return tctx; +} + } // namespace __sanitizer -- cgit v1.2.3