[compiler-rt] r204149 - tsan: deadlock detector: print 2 stacks per deadlock edge

Dmitry Vyukov dvyukov at google.com
Tue Mar 18 05:53:05 PDT 2014


Author: dvyukov
Date: Tue Mar 18 07:53:05 2014
New Revision: 204149

URL: http://llvm.org/viewvc/llvm-project?rev=204149&view=rev
Log:
tsan: deadlock detector: print 2 stacks per deadlock edge


Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
    compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc?rev=204149&r1=204148&r2=204149&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc Tue Mar 18 07:53:05 2014
@@ -43,13 +43,15 @@ struct Link {
   u32 id;
   u32 seq;
   u32 tid;
-  u32 stk;
+  u32 stk0;
+  u32 stk1;
 
-  explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 stk = 0)
+  explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 s0 = 0, u32 s1 = 0)
       : id(id)
       , seq(seq)
       , tid(tid)
-      , stk(stk) {
+      , stk0(s0)
+      , stk1(s1) {
   }
 };
 
@@ -61,10 +63,15 @@ struct DDPhysicalThread {
   Link path[kMaxMutex];
 };
 
+struct ThreadMutex {
+  u32 id;
+  u32 stk;
+};
+
 struct DDLogicalThread {
-  u64 ctx;
-  u32 locked[kMaxNesting];
-  int nlocked;
+  u64         ctx;
+  ThreadMutex locked[kMaxNesting];
+  int         nlocked;
 };
 
 struct Mutex {
@@ -201,7 +208,9 @@ void DD::MutexBeforeLock(DDCallback *cb,
   if (m->id == kNoId)
     m->id = allocateId(cb);
 
-  lt->locked[lt->nlocked++] = m->id;
+  ThreadMutex *tm = &lt->locked[lt->nlocked++];
+  tm->id = m->id;
+  tm->stk = cb->Unwind();
   if (lt->nlocked == 1) {
     VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
         cb->lt->ctx);
@@ -211,7 +220,8 @@ void DD::MutexBeforeLock(DDCallback *cb,
   bool added = false;
   Mutex *mtx = getMutex(m->id);
   for (int i = 0; i < lt->nlocked - 1; i++) {
-    u32 id1 = lt->locked[i];
+    u32 id1 = lt->locked[i].id;
+    u32 stk1 = lt->locked[i].stk;
     Mutex *mtx1 = getMutex(id1);
     SpinMutexLock l(&mtx1->mtx);
     if (mtx1->nlink == kMaxLink) {
@@ -225,7 +235,8 @@ void DD::MutexBeforeLock(DDCallback *cb,
         if (link->seq != mtx->seq) {
           link->seq = mtx->seq;
           link->tid = lt->ctx;
-          link->stk = cb->Unwind();
+          link->stk0 = stk1;
+          link->stk1 = cb->Unwind();
           added = true;
           VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
               cb->lt->ctx, getMutexId(mtx1), m->id);
@@ -239,7 +250,8 @@ void DD::MutexBeforeLock(DDCallback *cb,
       link->id = m->id;
       link->seq = mtx->seq;
       link->tid = lt->ctx;
-      link->stk = cb->Unwind();
+      link->stk0 = stk1;
+      link->stk1 = cb->Unwind();
       added = true;
       VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
           cb->lt->ctx, getMutexId(mtx1), m->id);
@@ -282,7 +294,9 @@ void DD::MutexAfterLock(DDCallback *cb,
   CHECK_LE(lt->nlocked, kMaxNesting);
   if (m->id == kNoId)
     m->id = allocateId(cb);
-  lt->locked[lt->nlocked++] = m->id;
+  ThreadMutex *tm = &lt->locked[lt->nlocked++];
+  tm->id = m->id;
+  tm->stk = cb->Unwind();
 }
 
 void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
@@ -301,7 +315,7 @@ void DD::MutexBeforeUnlock(DDCallback *c
   CHECK_NE(m->id, kNoId);
   int last = lt->nlocked - 1;
   for (int i = last; i >= 0; i--) {
-    if (cb->lt->locked[i] == m->id) {
+    if (cb->lt->locked[i].id == m->id) {
       lt->locked[i] = lt->locked[last];
       lt->nlocked--;
       break;
@@ -312,14 +326,30 @@ void DD::MutexBeforeUnlock(DDCallback *c
 void DD::MutexDestroy(DDCallback *cb, DDMutex *m) {
   VPrintf(2, "#%llu: DD::MutexDestroy(%p)\n",
       cb->lt->ctx, m);
+  DDLogicalThread *lt = cb->lt;
+
   if (m->id == kNoId)
     return;
+
+  // Remove the mutex from lt->locked if there.
+  int last = lt->nlocked - 1;
+  for (int i = last; i >= 0; i--) {
+    if (lt->locked[i].id == m->id) {
+      lt->locked[i] = lt->locked[last];
+      lt->nlocked--;
+      break;
+    }
+  }
+
+  // Clear and invalidate the mutex descriptor.
   {
     Mutex *mtx = getMutex(m->id);
     SpinMutexLock l(&mtx->mtx);
     mtx->seq++;
     mtx->nlink = 0;
   }
+
+  // Return id to cache.
   {
     SpinMutexLock l(&mtx);
     free_id.push_back(m->id);
@@ -377,7 +407,8 @@ void DD::Report(DDPhysicalThread *pt, DD
     rep->loop[i].thr_ctx = link->tid;
     rep->loop[i].mtx_ctx0 = link0->id;
     rep->loop[i].mtx_ctx1 = link->id;
-    rep->loop[i].stk[1] = link->stk;
+    rep->loop[i].stk[0] = link->stk0;
+    rep->loop[i].stk[1] = link->stk1;
   }
   pt->report_pending = true;
 }

Modified: compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc?rev=204149&r1=204148&r2=204149&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/dd/dd_rtl.cc Tue Mar 18 07:53:05 2014
@@ -45,8 +45,12 @@ static void ReportDeadlock(Thread *thr,
     Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
       rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
     PrintStackTrace(thr, rep->loop[i].stk[1]);
+    Printf("Mutex %llu was acquired here:\n",
+      rep->loop[i].mtx_ctx0);
+    PrintStackTrace(thr, rep->loop[i].stk[0]);
   }
   Printf("==============================\n");
+  Die();
 }
 
 Callback::Callback(Thread *thr)





More information about the llvm-commits mailing list