tsan: more precise handling of finalizers
authorDmitry Vyukov <dvyukov@google.com>
Wed, 7 Nov 2012 15:08:20 +0000 (15:08 +0000)
committerDmitry Vyukov <dvyukov@google.com>
Wed, 7 Nov 2012 15:08:20 +0000 (15:08 +0000)
llvm-svn: 167530

compiler-rt/lib/tsan/go/tsan_go.cc
compiler-rt/lib/tsan/rtl/tsan_clock.cc
compiler-rt/lib/tsan/rtl/tsan_clock.h
compiler-rt/lib/tsan/rtl/tsan_rtl.h
compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc

index a7e8d96..1496842 100644 (file)
@@ -192,7 +192,7 @@ void __tsan_release_merge(int goid, void *addr) {
 
 void __tsan_finalizer_goroutine(int goid) {
   ThreadState *thr = goroutines[goid];
-  ThreadFinalizerGoroutine(thr);
+  AcquireGlobal(thr, 0);
 }
 
 #ifdef _WIN32
index 89e788d..f8745ec 100644 (file)
@@ -58,7 +58,6 @@ namespace __tsan {
 
 ThreadClock::ThreadClock() {
   nclk_ = 0;
-  disabled_ = false;
   for (uptr i = 0; i < (uptr)kMaxTidInClock; i++)
     clk_[i] = 0;
 }
@@ -81,8 +80,6 @@ void ThreadClock::release(SyncClock *dst) const {
   DCHECK(nclk_ <= kMaxTid);
   DCHECK(dst->clk_.Size() <= kMaxTid);
 
-  if (disabled_)
-    return;
   if (dst->clk_.Size() < nclk_)
     dst->clk_.Resize(nclk_);
   for (uptr i = 0; i < nclk_; i++) {
@@ -95,8 +92,6 @@ void ThreadClock::ReleaseStore(SyncClock *dst) const {
   DCHECK(nclk_ <= kMaxTid);
   DCHECK(dst->clk_.Size() <= kMaxTid);
 
-  if (disabled_)
-    return;
   if (dst->clk_.Size() < nclk_)
     dst->clk_.Resize(nclk_);
   for (uptr i = 0; i < nclk_; i++)
@@ -110,14 +105,6 @@ void ThreadClock::acq_rel(SyncClock *dst) {
   release(dst);
 }
 
-void ThreadClock::Disable(unsigned tid) {
-  disabled_ = true;
-  u64 c0 = clk_[tid];
-  for (uptr i = 0; i < kMaxTidInClock; i++)
-    clk_[i] = (u64)-1;
-  clk_[tid] = c0;
-}
-
 SyncClock::SyncClock()
   : clk_(MBlockClock) {
 }
index 38a99db..0ee9374 100644 (file)
@@ -48,7 +48,7 @@ struct ThreadClock {
 
   void set(unsigned tid, u64 v) {
     DCHECK_LT(tid, kMaxTid);
-    DCHECK(v >= clk_[tid] || disabled_);
+    DCHECK_GE(v, clk_[tid]);
     clk_[tid] = v;
     if (nclk_ <= tid)
       nclk_ = tid + 1;
@@ -61,8 +61,6 @@ struct ThreadClock {
       nclk_ = tid + 1;
   }
 
-  void Disable(unsigned tid);
-
   uptr size() const {
     return nclk_;
   }
@@ -74,7 +72,6 @@ struct ThreadClock {
 
  private:
   uptr nclk_;
-  bool disabled_;
   u64 clk_[kMaxTidInClock];
 };
 
index 49388aa..489357c 100644 (file)
@@ -497,7 +497,6 @@ int ThreadTid(ThreadState *thr, uptr pc, uptr uid);
 void ThreadJoin(ThreadState *thr, uptr pc, int tid);
 void ThreadDetach(ThreadState *thr, uptr pc, int tid);
 void ThreadFinalize(ThreadState *thr);
-void ThreadFinalizerGoroutine(ThreadState *thr);
 
 void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
                  bool rw, bool recursive, bool linker_init);
@@ -509,6 +508,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
 void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
 
 void Acquire(ThreadState *thr, uptr pc, uptr addr);
+void AcquireGlobal(ThreadState *thr, uptr pc);
 void Release(ThreadState *thr, uptr pc, uptr addr);
 void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
 void AfterSleep(ThreadState *thr, uptr pc);
index a2e5681..0a75668 100644 (file)
@@ -231,6 +231,20 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
   s->mtx.ReadUnlock();
 }
 
+void AcquireGlobal(ThreadState *thr, uptr pc) {
+  Context *ctx = CTX();
+  Lock l(&ctx->thread_mtx);
+  for (unsigned i = 0; i < kMaxTid; i++) {
+    ThreadContext *tctx = ctx->threads[i];
+    if (tctx == 0)
+      continue;
+    if (tctx->status == ThreadStatusRunning)
+      thr->clock.set(i, tctx->thr->fast_state.epoch());
+    else
+      thr->clock.set(i, tctx->epoch1);
+  }
+}
+
 void Release(ThreadState *thr, uptr pc, uptr addr) {
   CHECK_GT(thr->in_rtl, 0);
   DPrintf("#%d: Release %zx\n", thr->tid, addr);
index 88061d7..13acda8 100644 (file)
@@ -303,10 +303,6 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
   }
 }
 
-void ThreadFinalizerGoroutine(ThreadState *thr) {
-  thr->clock.Disable(thr->tid);
-}
-
 void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
                        uptr size, bool is_write) {
   if (size == 0)