[compiler-rt] r177394 - tsan: flush dead thread info earlier (when another thread is finished rather than new thread is created)

Dmitry Vyukov dvyukov at google.com
Tue Mar 19 05:25:48 PDT 2013


Author: dvyukov
Date: Tue Mar 19 07:25:48 2013
New Revision: 177394

URL: http://llvm.org/viewvc/llvm-project?rev=177394&view=rev
Log:
tsan: flush dead thread info earlier (when another thread is finished rather than new thread is created)


Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc?rev=177394&r1=177393&r2=177394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc Tue Mar 19 07:25:48 2013
@@ -77,11 +77,11 @@ void ThreadContextBase::SetCreated(uptr
   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(ThreadCon
   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 us
                                  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 ti
   }
   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,
     return;
   }
   tctx->SetJoined(arg);
-  dead_threads_.push_back(tctx);
+  QuarantinePush(tctx);
 }
 
 void ThreadRegistry::FinishThread(u32 tid) {
@@ -239,7 +233,7 @@ void ThreadRegistry::FinishThread(u32 ti
   tctx->SetFinished();
   if (tctx->detached) {
     tctx->SetDead();
-    dead_threads_.push_back(tctx);
+    QuarantinePush(tctx);
   }
 }
 
@@ -253,4 +247,23 @@ void ThreadRegistry::StartThread(u32 tid
   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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h?rev=177394&r1=177393&r2=177394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h Tue Mar 19 07:25:48 2013
@@ -60,7 +60,7 @@ class ThreadContextBase {
   void SetStarted(uptr _os_id, void *arg);
   void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
                   u32 _parent_tid, void *arg);
-  void Reset(void *arg);
+  void Reset();
 
   // The following methods may be overriden by subclasses.
   // Some of them take opaque arg that may be optionally be used
@@ -70,7 +70,7 @@ class ThreadContextBase {
   virtual void OnFinished() {}
   virtual void OnStarted(void *arg) {}
   virtual void OnCreated(void *arg) {}
-  virtual void OnReset(void *arg) {}
+  virtual void OnReset() {}
 };
 
 typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
@@ -133,6 +133,10 @@ class ThreadRegistry {
 
   ThreadContextBase **threads_;  // Array of thread contexts is leaked.
   IntrusiveList<ThreadContextBase> dead_threads_;
+  IntrusiveList<ThreadContextBase> invalid_threads_;
+
+  void QuarantinePush(ThreadContextBase *tctx);
+  ThreadContextBase *QuarantinePop();
 };
 
 typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=177394&r1=177393&r2=177394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Tue Mar 19 07:25:48 2013
@@ -487,7 +487,7 @@ class ThreadContext : public ThreadConte
   void OnFinished();
   void OnStarted(void *arg);
   void OnCreated(void *arg);
-  void OnReset(void *arg);
+  void OnReset();
 };
 
 struct RacyStacks {

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=177394&r1=177393&r2=177394&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Tue Mar 19 07:25:48 2013
@@ -73,11 +73,10 @@ void ThreadContext::OnCreated(void *arg)
     StatInc(args->thr, StatThreadMaxTid);
 }
 
-void ThreadContext::OnReset(void *arg) {
-  OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
-  StatInc(args->thr, StatThreadReuse);
+void ThreadContext::OnReset() {
   sync.Reset();
-  DestroyAndFree(dead_info);
+  if (dead_info)
+    DestroyAndFree(dead_info);
 }
 
 struct OnStartedArgs {





More information about the llvm-commits mailing list