[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(<->dd, m->id)) {
// Actually add this edge now so that we have all the stack traces.
- dd.addEdges(<->dd, m->id, cb->Unwind());
+ dd.addEdges(<->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(<->dd, m->id));
if (!trylock)
- dd.addEdges(<->dd, m->id, cb->Unwind());
+ dd.addEdges(<->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
dd.onLockAfter(<->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