[compiler-rt] r204042 - [sanitizer] make the deadlock detector print 2*N stack traces on lock-order-inversion with N locks (i.e. print stack traces for both lock acquisitions in every edge in the graph). More improvements to follow

Kostya Serebryany kcc at google.com
Mon Mar 17 07:41:36 PDT 2014


Author: kcc
Date: Mon Mar 17 09:41:36 2014
New Revision: 204042

URL: http://llvm.org/viewvc/llvm-project?rev=204042&view=rev
Log:
[sanitizer] make the deadlock detector print 2*N stack traces on lock-order-inversion with N locks (i.e. print stack traces for both lock acquisitions in every edge in the graph). More improvements to follow

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/tsan/rtl/tsan_rtl_mutex.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=204042&r1=204041&r2=204042&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h Mon Mar 17 09:41:36 2014
@@ -231,20 +231,24 @@ class DeadlockDetector {
                                      added_edges, ARRAY_SIZE(added_edges));
     for (uptr i = 0; i < n_added_edges; i++) {
       if (n_edges_ < ARRAY_SIZE(edges_))
-        edges_[n_edges_++] = Edge((u16)added_edges[i], (u16)cur_idx, stk);
+        edges_[n_edges_++] = Edge((u16)added_edges[i], (u16)cur_idx, stk,
+                                  dtls->findLockContext(added_edges[i]));
       // Printf("Edge [%zd]: %u %zd=>%zd\n", i, stk, added_edges[i], cur_idx);
     }
     return n_added_edges;
   }
 
-  u32 findEdge(uptr from_node, uptr to_node) {
+  bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to) {
     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)
-        return edges_[i].stk;
+      if (edges_[i].from == from_idx && edges_[i].to == to_idx) {
+        *stk_from = edges_[i].stk_from;
+        *stk_to = edges_[i].stk_to;
+        return true;
+      }
     }
-    return 0;
+    return false;
   }
 
   // Test-only function. Handles the before/after lock events,
@@ -367,9 +371,11 @@ class DeadlockDetector {
   struct Edge {
     u16 from;
     u16 to;
-    u32 stk;
+    u32 stk_from;
+    u32 stk_to;
     // FIXME: replace with initializer list once the tests are built as c++11.
-    Edge(u16 f, u16 t, u32 s) : from(f), to(t), stk(s) {}
+    Edge(u16 f, u16 t, u32 sf, u32 st)
+        : from(f), to(t), stk_from(sf), stk_to(st) {}
     Edge() {}
   };
 

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=204042&r1=204041&r2=204042&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc Mon Mar 17 09:41:36 2014
@@ -106,9 +106,12 @@ void DD::MutexBeforeLock(DDCallback *cb,
   if (dd.isHeld(&lt->dd, m->id))
     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());
     uptr path[10];
     uptr len = dd.findPathToLock(&lt->dd, m->id, path, ARRAY_SIZE(path));
     CHECK_GT(len, 0U);  // Hm.. cycle of 10 locks? I'd like to see that.
+    CHECK_EQ(m->id, path[0]);
     lt->report_pending = true;
     DDReport *rep = &lt->rep;
     rep->n = len;
@@ -118,22 +121,25 @@ void DD::MutexBeforeLock(DDCallback *cb,
       DDMutex *m0 = (DDMutex*)dd.getData(from);
       DDMutex *m1 = (DDMutex*)dd.getData(to);
 
-      u32 stk = dd.findEdge(from, to);
-      // Printf("Edge: %zd=>%zd: %u\n", from, to, stk);
+      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
       rep->loop[i].mtx_ctx0 = m0->ctx;
       rep->loop[i].mtx_ctx1 = m1->ctx;
-      rep->loop[i].stk = stk;
+      rep->loop[i].stk[0] = stk_from;
+      rep->loop[i].stk[1] = stk_to;
     }
   }
 }
 
 void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
   DDLogicalThread *lt = cb->lt;
+  u32 stk = cb->Unwind();  // FIXME: if this is hot, do this under a flag.
   // Printf("T%p MutexLock:   %zx\n", lt, m->id);
-  if (dd.onFirstLock(&lt->dd, m->id))
+  if (dd.onFirstLock(&lt->dd, m->id, stk))
     return;
-  if (dd.onLockFast(&lt->dd, m->id))
+  if (dd.onLockFast(&lt->dd, m->id, stk))
     return;
 
   SpinMutexLock lk(&mtx);
@@ -142,7 +148,7 @@ void DD::MutexAfterLock(DDCallback *cb,
     CHECK(!dd.isHeld(&lt->dd, m->id));
   if (!trylock)
     dd.addEdges(&lt->dd, m->id, cb->Unwind());
-  dd.onLockAfter(&lt->dd, m->id);
+  dd.onLockAfter(&lt->dd, m->id, stk);
 }
 
 void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {

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=204042&r1=204041&r2=204042&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 Mon Mar 17 09:41:36 2014
@@ -47,13 +47,13 @@ struct DDMutex {
 };
 
 struct DDReport {
-  enum { kMaxLoopSize = 16 };
+  enum { kMaxLoopSize = 8 };
   int n;  // number of entries in loop
   struct {
     u64 thr_ctx;   // user thread context
     u64 mtx_ctx0;  // user mutex context, start of the edge
     u64 mtx_ctx1;  // user mutex context, end of the edge
-    u32 stk;       // stack id for the edge
+    u32 stk[2];  // stack ids for the edge
   } loop[kMaxLoopSize];
 };
 

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=204042&r1=204041&r2=204042&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Mon Mar 17 09:41:36 2014
@@ -427,17 +427,17 @@ void ReportDeadlock(ThreadState *thr, up
   ScopedReport rep(ReportTypeDeadlock);
   for (int i = 0; i < r->n; i++)
     rep.AddMutex(r->loop[i].mtx_ctx0);
-  StackTrace stacks[DDReport::kMaxLoopSize];
+  StackTrace stacks[2 * DDReport::kMaxLoopSize];
   for (int i = 0; i < r->n; i++) {
-    if (!r->loop[i].stk) continue;
     uptr size;
-    const uptr *trace = StackDepotGet(r->loop[i].stk, &size);
-    stacks[i].Init(const_cast<uptr *>(trace), size);
-    rep.AddStack(&stacks[i]);
+    for (int j = 0; j < 2; j++) {
+      u32 stk = r->loop[i].stk[j];
+      if (!stk) continue;
+      const uptr *trace = StackDepotGet(stk, &size);
+      stacks[i].Init(const_cast<uptr *>(trace), size);
+      rep.AddStack(&stacks[i]);
+    }
   }
-  StackTrace trace;
-  trace.ObtainCurrent(thr, pc);
-  rep.AddStack(&trace);
   OutputReport(ctx, rep);
 #endif  // TSAN_GO
 }

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=204042&r1=204041&r2=204042&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc (original)
+++ compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc Mon Mar 17 09:41:36 2014
@@ -420,6 +420,10 @@ class LockTest {
     // CHECK: LockTest::Acquire1
     // CHECK-NEXT: LockTest::Acquire_0_then_1
     // CHECK: LockTest::Acquire0
+    // CHECK-NEXT: LockTest::Acquire_0_then_1
+    // CHECK: LockTest::Acquire0
+    // CHECK-NEXT: LockTest::Acquire_1_then_0
+    // CHECK: LockTest::Acquire1
     // CHECK-NEXT: LockTest::Acquire_1_then_0
     Init(5);
     Acquire_0_then_1();





More information about the llvm-commits mailing list