[compiler-rt] r204461 - [sanitizer] print threads in deadlock report

Kostya Serebryany kcc at google.com
Fri Mar 21 06:00:18 PDT 2014


Author: kcc
Date: Fri Mar 21 08:00:18 2014
New Revision: 204461

URL: http://llvm.org/viewvc/llvm-project?rev=204461&view=rev
Log:
[sanitizer] print threads in deadlock report

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
    compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h Fri Mar 21 08:00:18 2014
@@ -231,7 +231,8 @@ class DeadlockDetector {
   // returns the number of added edges, and puts the sources of added edges
   // into added_edges[].
   // Should be called before onLockAfter.
-  uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+  uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk,
+                int unique_tid) {
     ensureCurrentEpoch(dtls);
     uptr cur_idx = nodeToIndex(cur_node);
     uptr added_edges[40];
@@ -240,19 +241,23 @@ class DeadlockDetector {
     for (uptr i = 0; i < n_added_edges; i++) {
       if (n_edges_ < ARRAY_SIZE(edges_))
         edges_[n_edges_++] = {(u16)added_edges[i], (u16)cur_idx,
-                              dtls->findLockContext(added_edges[i]), stk};
-      // Printf("E%zd: %u %zd=>%zd\n", n_edges_, stk, added_edges[i], cur_idx);
+                              dtls->findLockContext(added_edges[i]), stk,
+                              unique_tid};
+      // Printf("Edge%zd: %u %zd=>%zd in T%d\n",
+      //        n_edges_, stk, added_edges[i], cur_idx, unique_tid);
     }
     return n_added_edges;
   }
 
-  bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to) {
+  bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to,
+                int *unique_tid) {
     uptr from_idx = nodeToIndex(from_node);
     uptr to_idx = nodeToIndex(to_node);
     for (uptr i = 0; i < n_edges_; i++) {
       if (edges_[i].from == from_idx && edges_[i].to == to_idx) {
         *stk_from = edges_[i].stk_from;
         *stk_to = edges_[i].stk_to;
+        *unique_tid = edges_[i].unique_tid;
         return true;
       }
     }
@@ -264,7 +269,7 @@ class DeadlockDetector {
   bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
     ensureCurrentEpoch(dtls);
     bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
-    addEdges(dtls, cur_node, stk);
+    addEdges(dtls, cur_node, stk, 0);
     onLockAfter(dtls, cur_node, stk);
     return is_reachable;
   }
@@ -381,6 +386,7 @@ class DeadlockDetector {
     u16 to;
     u32 stk_from;
     u32 stk_to;
+    int unique_tid;
   };
 
   uptr current_epoch_;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc Fri Mar 21 08:00:18 2014
@@ -111,7 +111,7 @@ void DD::MutexBeforeLock(DDCallback *cb,
     return;  // FIXME: allow this only for recursive locks.
   if (dd.onLockBefore(&lt->dd, m->id)) {
     // Actually add this edge now so that we have all the stack traces.
-    dd.addEdges(&lt->dd, m->id, cb->Unwind());
+    dd.addEdges(&lt->dd, m->id, cb->Unwind(), cb->UniqueTid());
     ReportDeadlock(cb, m);
   }
 }
@@ -131,10 +131,12 @@ void DD::ReportDeadlock(DDCallback *cb,
     DDMutex *m0 = (DDMutex*)dd.getData(from);
     DDMutex *m1 = (DDMutex*)dd.getData(to);
 
-    u32 stk_from = 0, stk_to = 0;
-    dd.findEdge(from, to, &stk_from, &stk_to);
-    // Printf("Edge: %zd=>%zd: %u/%u\n", from, to, stk_from, stk_to);
-    rep->loop[i].thr_ctx = 0;  // don't know
+    u32 stk_from = -1U, stk_to = -1U;
+    int unique_tid = 0;
+    dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid);
+    // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to,
+    //    unique_tid);
+    rep->loop[i].thr_ctx = unique_tid;
     rep->loop[i].mtx_ctx0 = m0->ctx;
     rep->loop[i].mtx_ctx1 = m1->ctx;
     rep->loop[i].stk[0] = stk_to;
@@ -158,7 +160,7 @@ void DD::MutexAfterLock(DDCallback *cb,
   if (wlock)  // Only a recursive rlock may be held.
     CHECK(!dd.isHeld(&lt->dd, m->id));
   if (!trylock)
-    dd.addEdges(&lt->dd, m->id, cb->Unwind());
+    dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
   dd.onLockAfter(&lt->dd, m->id, stk);
 }
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h Fri Mar 21 08:00:18 2014
@@ -66,6 +66,7 @@ struct DDCallback {
   DDLogicalThread  *lt;
 
   virtual u32 Unwind() { return 0; }
+  virtual int UniqueTid() { return 0; }
 };
 
 struct DDetector {

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc Fri Mar 21 08:00:18 2014
@@ -452,6 +452,7 @@ void RunRemoveEdgesTest() {
   DeadlockDetectorTLS<BV> &dtls = sdd.dtls;
   vector<uptr> node(BV::kSize);
   u32 stk_from = 0, stk_to = 0;
+  int unique_tid = 0;
   for (size_t i = 0; i < BV::kSize; i++)
     node[i] = d.newNode(0);
 
@@ -459,7 +460,8 @@ void RunRemoveEdgesTest() {
     EXPECT_FALSE(d.onLock(&dtls, node[i], i + 1));
   for (size_t i = 0; i < BV::kSize; i++) {
     for (uptr j = i + 1; j < BV::kSize; j++) {
-      EXPECT_TRUE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
+      EXPECT_TRUE(
+          d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid));
       EXPECT_EQ(stk_from, i + 1);
       EXPECT_EQ(stk_to, j + 1);
     }
@@ -475,9 +477,11 @@ void RunRemoveEdgesTest() {
   for (size_t i = 0; i < BV::kSize; i++) {
     for (uptr j = i + 1; j < BV::kSize; j++) {
       if ((i % 2) || (j % 2))
-        EXPECT_FALSE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
+        EXPECT_FALSE(
+            d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid));
       else
-        EXPECT_TRUE(d.findEdge(node[i], node[j], &stk_from, &stk_to));
+        EXPECT_TRUE(
+            d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid));
     }
   }
 }

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Fri Mar 21 08:00:18 2014
@@ -40,6 +40,7 @@ ReportDesc::ReportDesc()
     , locs(MBlockReportLoc)
     , mutexes(MBlockReportMutex)
     , threads(MBlockReportThread)
+    , unique_tids(MBlockReportThread)
     , sleep()
     , count() {
 }
@@ -162,8 +163,8 @@ static void PrintMutexShort(const Report
   Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.EndMutex(), after);
 }
 
-static void PrintMutexShortWitAddress(const ReportMutex *rm,
-                                      const char *after) {
+static void PrintMutexShortWithAddress(const ReportMutex *rm,
+                                       const char *after) {
   Decorator d;
   Printf("%sM%zd (%p)%s%s", d.Mutex(), rm->id, rm->addr, d.EndMutex(), after);
 }
@@ -237,9 +238,10 @@ void PrintReport(const ReportDesc *rep)
   Printf("%s", d.EndWarning());
 
   if (rep->typ == ReportTypeDeadlock) {
+    char thrbuf[kThreadBufSize];
     Printf("  Cycle in lock order graph: ");
     for (uptr i = 0; i < rep->mutexes.Size(); i++)
-      PrintMutexShortWitAddress(rep->mutexes[i], " => ");
+      PrintMutexShortWithAddress(rep->mutexes[i], " => ");
     PrintMutexShort(rep->mutexes[0], "\n\n");
     CHECK_GT(rep->mutexes.Size(), 0U);
     CHECK_EQ(rep->mutexes.Size() * (flags()->second_deadlock_stack ? 2 : 1),
@@ -248,7 +250,10 @@ void PrintReport(const ReportDesc *rep)
       Printf("  Mutex ");
       PrintMutexShort(rep->mutexes[(i + 1) % rep->mutexes.Size()],
                       " acquired here while holding mutex ");
-      PrintMutexShort(rep->mutexes[i], ":\n");
+      PrintMutexShort(rep->mutexes[i], " in ");
+      Printf("%s", d.ThreadDescription());
+      Printf("%s:\n", thread_name(thrbuf, rep->unique_tids[i]));
+      Printf("%s", d.EndThreadDescription());
       if (flags()->second_deadlock_stack) {
         PrintStack(rep->stacks[2*i]);
         Printf("  Mutex ");

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.h?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Fri Mar 21 08:00:18 2014
@@ -103,6 +103,7 @@ class ReportDesc {
   Vector<ReportLocation*> locs;
   Vector<ReportMutex*> mutexes;
   Vector<ReportThread*> threads;
+  Vector<int> unique_tids;
   ReportStack *sleep;
   int count;
 

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=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Fri Mar 21 08:00:18 2014
@@ -575,6 +575,8 @@ class ScopedReport {
   void AddMemoryAccess(uptr addr, Shadow s, const StackTrace *stack,
                        const MutexSet *mset);
   void AddThread(const ThreadContext *tctx);
+  void AddThread(int unique_tid);
+  void AddUniqueTid(int unique_tid);
   void AddMutex(const SyncVar *s);
   u64 AddMutex(u64 id);
   void AddLocation(uptr addr, uptr size);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Fri Mar 21 08:00:18 2014
@@ -39,6 +39,9 @@ struct Callback : DDCallback {
   virtual u32 Unwind() {
     return CurrentStackId(thr, pc);
   }
+  virtual int UniqueTid() {
+    return thr->unique_id;
+  }
 };
 
 void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {
@@ -411,8 +414,11 @@ void ReportDeadlock(ThreadState *thr, up
     return;
   ThreadRegistryLock l(ctx->thread_registry);
   ScopedReport rep(ReportTypeDeadlock);
-  for (int i = 0; i < r->n; i++)
+  for (int i = 0; i < r->n; i++) {
     rep.AddMutex(r->loop[i].mtx_ctx0);
+    rep.AddUniqueTid((int)r->loop[i].thr_ctx);
+    rep.AddThread((int)r->loop[i].thr_ctx);
+  }
   StackTrace stacks[2 * DDReport::kMaxLoopSize];
   uptr dummy_pc = 0x42;
   for (int i = 0; i < r->n; i++) {

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Fri Mar 21 08:00:18 2014
@@ -186,6 +186,10 @@ void ScopedReport::AddMemoryAccess(uptr
   }
 }
 
+void ScopedReport::AddUniqueTid(int unique_tid) {
+  rep_->unique_tids.PushBack(unique_tid);
+}
+
 void ScopedReport::AddThread(const ThreadContext *tctx) {
   for (uptr i = 0; i < rep_->threads.Size(); i++) {
     if ((u32)rep_->threads[i]->id == tctx->tid)
@@ -247,6 +251,12 @@ ThreadContext *IsThreadStackOrTls(uptr a
 }
 #endif
 
+void ScopedReport::AddThread(int unique_tid) {
+#ifndef TSAN_GO
+  AddThread(FindThreadByUidLocked(unique_tid));
+#endif
+}
+
 void ScopedReport::AddMutex(const SyncVar *s) {
   for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
     if (rep_->mutexes[i]->id == s->uid)

Modified: compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc?rev=204461&r1=204460&r2=204461&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc (original)
+++ compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc Fri Mar 21 08:00:18 2014
@@ -222,6 +222,11 @@ class LockTest {
     Init(5);
     RunThreads(&LockTest::Lock_0_1, &LockTest::Lock_1_0);
     // CHECK: WARNING: ThreadSanitizer: lock-order-inversion
+    // CHECK: Cycle in lock order graph: [[M1:M[0-9]+]] ({{.*}}) => [[M2:M[0-9]+]] ({{.*}}) => [[M1]]
+    // CHECK: Mutex [[M2]] acquired here while holding mutex [[M1]] in thread [[T1:T[0-9]+]]
+    // CHECK: Mutex [[M1]] acquired here while holding mutex [[M2]] in thread [[T2:T[0-9]+]]
+    // CHECK: Thread [[T1]] {{.*}} created by main thread
+    // CHECK: Thread [[T2]] {{.*}} created by main thread
     // CHECK-NOT: WARNING: ThreadSanitizer:
   }
 





More information about the llvm-commits mailing list