diff options
author | Kostya Serebryany <kcc@google.com> | 2014-02-19 14:17:25 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2014-02-19 14:17:25 +0000 |
commit | b51f8d4990950c046a7b07d4125ccde57758a130 (patch) | |
tree | 72c1b4d67c2f659a04c5874cf463e1c845d4a943 /compiler-rt | |
parent | 8067448dfe175e196af25ec345a7c3394923ff5c (diff) | |
download | bcm5719-llvm-b51f8d4990950c046a7b07d4125ccde57758a130.tar.gz bcm5719-llvm-b51f8d4990950c046a7b07d4125ccde57758a130.zip |
[tsan] when printing a mutex, also print its address. Properly print the deadlock report.
llvm-svn: 201675
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_report.cc | 17 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_report.h | 4 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 16 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 2 | ||||
-rw-r--r-- | compiler-rt/test/tsan/deadlock_detector_stress_test.cc | 20 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutex_cycle2.c | 2 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset1.cc | 2 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset2.cc | 2 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset3.cc | 4 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset4.cc | 4 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset5.cc | 4 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset6.cc | 6 | ||||
-rw-r--r-- | compiler-rt/test/tsan/mutexset8.cc | 2 |
13 files changed, 54 insertions, 31 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index 66307ae09dc..5281c7ae973 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -77,6 +77,8 @@ static const char *ReportTypeString(ReportType typ) { return "signal-unsafe call inside of a signal"; if (typ == ReportTypeErrnoInSignal) return "signal handler spoils errno"; + if (typ == ReportTypeDeadlock) + return "lock-order-inversion (potential deadlock)"; return ""; } @@ -155,6 +157,11 @@ static void PrintLocation(const ReportLocation *loc) { PrintStack(loc->stack); } +static void PrintMutexShort(const ReportMutex *rm, const char *after) { + Decorator d; + Printf("%sM%zd%s%s", d.Mutex(), rm->id, d.EndMutex(), after); +} + static void PrintMutex(const ReportMutex *rm) { Decorator d; if (rm->destroyed) { @@ -163,7 +170,7 @@ static void PrintMutex(const ReportMutex *rm) { Printf("%s", d.EndMutex()); } else { Printf("%s", d.Mutex()); - Printf(" Mutex M%llu created at:\n", rm->id); + Printf(" Mutex M%llu (%p) created at:\n", rm->id, rm->addr); Printf("%s", d.EndMutex()); PrintStack(rm->stack); } @@ -223,6 +230,14 @@ void PrintReport(const ReportDesc *rep) { (int)internal_getpid()); Printf("%s", d.EndWarning()); + if (rep->typ == ReportTypeDeadlock) { + Printf(" path: "); + CHECK_GT(rep->mutexes.Size(), 0U); + for (uptr i = 0; i < rep->mutexes.Size(); i++) + PrintMutexShort(rep->mutexes[i], " => "); + PrintMutexShort(rep->mutexes[0], "\n"); + } + for (uptr i = 0; i < rep->stacks.Size(); i++) { if (i) Printf(" and:\n"); diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h index b2ce0dd66a2..185751400b5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.h +++ b/compiler-rt/lib/tsan/rtl/tsan_report.h @@ -25,7 +25,8 @@ enum ReportType { ReportTypeThreadLeak, ReportTypeMutexDestroyLocked, ReportTypeSignalUnsafe, - ReportTypeErrnoInSignal + ReportTypeErrnoInSignal, + ReportTypeDeadlock }; struct ReportStack { @@ -89,6 +90,7 @@ struct ReportThread { struct ReportMutex { u64 id; + uptr addr; bool destroyed; ReportStack *stack; }; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index 7af5ce656f6..364f4b57c88 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -26,7 +26,7 @@ static __sanitizer::DeadlockDetector<DDBV> g_dd; static void EnsureDeadlockDetectorID(ThreadState *thr, SyncVar *s) { if (!g_dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id)) - s->deadlock_detector_id = g_dd.newNode(reinterpret_cast<uptr>(s->addr)); + s->deadlock_detector_id = g_dd.newNode(reinterpret_cast<uptr>(s)); } void MutexCreate(ThreadState *thr, uptr pc, uptr addr, @@ -128,17 +128,19 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) { bool has_deadlock = g_dd.onLock(&thr->deadlock_detector_tls, s->deadlock_detector_id); if (has_deadlock) { - Printf("ThreadSanitizer: lock-order-inversion (potential deadlock)\n"); uptr path[10]; uptr len = g_dd.findPathToHeldLock(&thr->deadlock_detector_tls, s->deadlock_detector_id, path, ARRAY_SIZE(path)); CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that. - Printf(" path: "); - for (uptr i = 0; i < len; i++) { - Printf("%p => ", g_dd.getData(path[i])); - } - Printf("%p\n", g_dd.getData(path[0])); + ThreadRegistryLock l(CTX()->thread_registry); + ScopedReport rep(ReportTypeDeadlock); + for (uptr i = 0; i < len; i++) + rep.AddMutex(reinterpret_cast<SyncVar*>(g_dd.getData(path[i]))); + StackTrace trace; + trace.ObtainCurrent(thr, pc); + rep.AddStack(&trace); + OutputReport(CTX(), rep); } } s->mtx.Unlock(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index b1741298b0e..9d88a687a68 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -278,6 +278,7 @@ void ScopedReport::AddMutex(const SyncVar *s) { ReportMutex *rm = new(mem) ReportMutex(); rep_->mutexes.PushBack(rm); rm->id = s->uid; + rm->addr = s->addr; rm->destroyed = false; rm->stack = 0; #ifndef TSAN_GO @@ -294,6 +295,7 @@ void ScopedReport::AddMutex(u64 id) { ReportMutex *rm = new(mem) ReportMutex(); rep_->mutexes.PushBack(rm); rm->id = id; + rm->addr = 0; rm->destroyed = true; rm->stack = 0; } diff --git a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc index f36935ffd00..30ce88d12b8 100644 --- a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc +++ b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan %s -o %t -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %t 2>&1 | FileCheck %s +// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s #include <pthread.h> #undef NDEBUG #include <assert.h> @@ -46,9 +46,11 @@ class LockTest { // CHECK: Expecting lock inversion: [[A1:0x[a-f0-9]*]] [[A2:0x[a-f0-9]*]] L(0); L(1); U(0); U(1); L(1); L(0); U(0); U(1); - // CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) - // CHECK-NEXT: path: [[A1]] => [[A2]] => [[A1]] - // CHECK-NOT: ThreadSanitizer: + // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) + // CHECK: path: [[M1:M[0-9]+]] => [[M2:M[0-9]+]] => [[M1]] + // CHECK: Mutex [[M1]] ([[A1]]) created at: + // CHECK: Mutex [[M2]] ([[A2]]) created at: + // CHECK-NOT: WARNING: ThreadSanitizer: } // Simple lock order inversion with 3 locks. @@ -57,8 +59,8 @@ class LockTest { // CHECK: Starting Test2 L(0); L(1); L(2); U(2); U(0); U(1); L(2); L(0); U(0); U(2); - // CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) - // CHECK-NOT: ThreadSanitizer: + // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) + // CHECK-NOT: WARNING: ThreadSanitizer: } // Lock order inversion with lots of new locks created (but not used) @@ -72,8 +74,8 @@ class LockTest { CreateAndDestroyManyLocks(); U(2); L(1); L(0); U(0); U(1); - // CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) - // CHECK-NOT: ThreadSanitizer: + // CHECK: WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) + // CHECK-NOT: WARNING: ThreadSanitizer: } // lock l0=>l1; then create and use lots of locks; then lock l1=>l0. @@ -86,7 +88,7 @@ class LockTest { CreateLockUnlockAndDestroyManyLocks(); U(2); L(1); L(0); U(0); U(1); - // CHECK-NOT: ThreadSanitizer: + // CHECK-NOT: WARNING: ThreadSanitizer: } private: diff --git a/compiler-rt/test/tsan/mutex_cycle2.c b/compiler-rt/test/tsan/mutex_cycle2.c index cd1006d4760..32bb067567f 100644 --- a/compiler-rt/test/tsan/mutex_cycle2.c +++ b/compiler-rt/test/tsan/mutex_cycle2.c @@ -1,5 +1,5 @@ // RUN: %clangxx_tsan %s -o %t -// RUN: TSAN_OPTIONS=detect_deadlocks=1 %t 2>&1 | FileCheck %s +// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s #include <pthread.h> int main() { diff --git a/compiler-rt/test/tsan/mutexset1.cc b/compiler-rt/test/tsan/mutexset1.cc index ca87a7ba047..acba2f33e02 100644 --- a/compiler-rt/test/tsan/mutexset1.cc +++ b/compiler-rt/test/tsan/mutexset1.cc @@ -24,7 +24,7 @@ int main() { // CHECK: Write of size 4 at {{.*}} by thread T1 // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Previous write of size 4 at {{.*}} by thread T2: - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset1.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); diff --git a/compiler-rt/test/tsan/mutexset2.cc b/compiler-rt/test/tsan/mutexset2.cc index 9ccf952b005..4bc25b736cd 100644 --- a/compiler-rt/test/tsan/mutexset2.cc +++ b/compiler-rt/test/tsan/mutexset2.cc @@ -24,7 +24,7 @@ int main() { // CHECK: Write of size 4 at {{.*}} by thread T2: // CHECK: Previous write of size 4 at {{.*}} by thread T1 // CHECK: (mutexes: write [[M1:M[0-9]+]]): - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset2.cc:[[@LINE+1]] pthread_mutex_init(&mtx, 0); diff --git a/compiler-rt/test/tsan/mutexset3.cc b/compiler-rt/test/tsan/mutexset3.cc index 272ddafb3c4..57393bbf43c 100644 --- a/compiler-rt/test/tsan/mutexset3.cc +++ b/compiler-rt/test/tsan/mutexset3.cc @@ -27,10 +27,10 @@ int main() { // CHECK: Write of size 4 at {{.*}} by thread T1 // CHECK: (mutexes: write [[M1:M[0-9]+]], write [[M2:M[0-9]+]]): // CHECK: Previous write of size 4 at {{.*}} by thread T2: - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+4]] - // CHECK: Mutex [[M2]] created at: + // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset3.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); diff --git a/compiler-rt/test/tsan/mutexset4.cc b/compiler-rt/test/tsan/mutexset4.cc index be751fa92bf..26c95cac720 100644 --- a/compiler-rt/test/tsan/mutexset4.cc +++ b/compiler-rt/test/tsan/mutexset4.cc @@ -27,10 +27,10 @@ int main() { // CHECK: Write of size 4 at {{.*}} by thread T2: // CHECK: Previous write of size 4 at {{.*}} by thread T1 // CHECK: (mutexes: write [[M1:M[0-9]+]], write [[M2:M[0-9]+]]): - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+4]] - // CHECK: Mutex [[M2]] created at: + // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset4.cc:[[@LINE+2]] pthread_mutex_init(&mtx1, 0); diff --git a/compiler-rt/test/tsan/mutexset5.cc b/compiler-rt/test/tsan/mutexset5.cc index e013edb4656..45ae8bb5e4f 100644 --- a/compiler-rt/test/tsan/mutexset5.cc +++ b/compiler-rt/test/tsan/mutexset5.cc @@ -28,10 +28,10 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Previous write of size 4 at {{.*}} by thread T2 // CHECK: (mutexes: write [[M2:M[0-9]+]]): - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+4]] - // CHECK: Mutex [[M2]] created at: + // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset5.cc:[[@LINE+5]] pthread_mutex_init(&mtx1, 0); diff --git a/compiler-rt/test/tsan/mutexset6.cc b/compiler-rt/test/tsan/mutexset6.cc index f5e6e66becf..c8392d89931 100644 --- a/compiler-rt/test/tsan/mutexset6.cc +++ b/compiler-rt/test/tsan/mutexset6.cc @@ -33,11 +33,11 @@ int main() { // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Previous write of size 4 at {{.*}} by thread T2 // CHECK: (mutexes: write [[M2:M[0-9]+]], read [[M3:M[0-9]+]]): - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+5]] - // CHECK: Mutex [[M2]] created at: + // CHECK: Mutex [[M2]] (0x{{.*}}) created at: // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+4]] - // CHECK: Mutex [[M3]] created at: + // CHECK: Mutex [[M3]] (0x{{.*}}) created at: // CHECK: #1 main {{.*}}/mutexset6.cc:[[@LINE+3]] pthread_mutex_init(&mtx1, 0); pthread_spin_init(&mtx2, 0); diff --git a/compiler-rt/test/tsan/mutexset8.cc b/compiler-rt/test/tsan/mutexset8.cc index 8822b050e93..afc064c5e09 100644 --- a/compiler-rt/test/tsan/mutexset8.cc +++ b/compiler-rt/test/tsan/mutexset8.cc @@ -24,7 +24,7 @@ int main() { // CHECK: Write of size 4 at {{.*}} by thread T1 // CHECK: (mutexes: write [[M1:M[0-9]+]]): // CHECK: Previous write of size 4 at {{.*}} by thread T2: - // CHECK: Mutex [[M1]] created at: + // CHECK: Mutex [[M1]] (0x{{.*}}) created at: // CHECK: #0 pthread_mutex_init // CHECK: #1 main {{.*}}/mutexset8.cc mtx = new pthread_mutex_t; |