summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-19 12:25:48 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-19 12:25:48 +0000
commitce85e03620f64ce7e4cd0598f2e93090f52a9e99 (patch)
tree16b43363033c32c949b7b187e5d6cbe23219e1b0
parent8e1c769ed84f4d5cf23904dee1abeec6f125f1ac (diff)
downloadcompiler-rt-ce85e03620f64ce7e4cd0598f2e93090f52a9e99.tar.gz
compiler-rt-ce85e03620f64ce7e4cd0598f2e93090f52a9e99.tar.bz2
compiler-rt-ce85e03620f64ce7e4cd0598f2e93090f52a9e99.tar.xz
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
-rw-r--r--lib/sanitizer_common/sanitizer_thread_registry.cc51
-rw-r--r--lib/sanitizer_common/sanitizer_thread_registry.h8
-rw-r--r--lib/tsan/rtl/tsan_rtl.h2
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc7
4 files changed, 42 insertions, 26 deletions
diff --git a/lib/sanitizer_common/sanitizer_thread_registry.cc b/lib/sanitizer_common/sanitizer_thread_registry.cc
index 3d246fee..5b3dacc5 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
diff --git a/lib/sanitizer_common/sanitizer_thread_registry.h b/lib/sanitizer_common/sanitizer_thread_registry.h
index e2ee8f82..66eb4ca1 100644
--- a/lib/sanitizer_common/sanitizer_thread_registry.h
+++ b/lib/sanitizer_common/sanitizer_thread_registry.h
@@ -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;
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 053f24aa..19929def 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -487,7 +487,7 @@ class ThreadContext : public ThreadContextBase {
void OnFinished();
void OnStarted(void *arg);
void OnCreated(void *arg);
- void OnReset(void *arg);
+ void OnReset();
};
struct RacyStacks {
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index bcb5498c..476b670b 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -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 {