[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(<->dd, m->id))
return; // FIXME: allow this only for recursive locks.
if (dd.onLockBefore(<->dd, m->id)) {
+ // Actually add this edge now so that we have all the stack traces.
+ dd.addEdges(<->dd, m->id, cb->Unwind());
uptr path[10];
uptr len = dd.findPathToLock(<->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 = <->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(<->dd, m->id))
+ if (dd.onFirstLock(<->dd, m->id, stk))
return;
- if (dd.onLockFast(<->dd, m->id))
+ if (dd.onLockFast(<->dd, m->id, stk))
return;
SpinMutexLock lk(&mtx);
@@ -142,7 +148,7 @@ void DD::MutexAfterLock(DDCallback *cb,
CHECK(!dd.isHeld(<->dd, m->id));
if (!trylock)
dd.addEdges(<->dd, m->id, cb->Unwind());
- dd.onLockAfter(<->dd, m->id);
+ dd.onLockAfter(<->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