[compiler-rt] r201675 - [tsan] when printing a mutex, also print its address. Properly print the deadlock report.

Kostya Serebryany kcc at google.com
Wed Feb 19 06:17:26 PST 2014


Author: kcc
Date: Wed Feb 19 08:17:25 2014
New Revision: 201675

URL: http://llvm.org/viewvc/llvm-project?rev=201675&view=rev
Log:
[tsan] when printing a mutex, also print its address. Properly print the deadlock report.

Modified:
    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_mutex.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
    compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc
    compiler-rt/trunk/test/tsan/mutex_cycle2.c
    compiler-rt/trunk/test/tsan/mutexset1.cc
    compiler-rt/trunk/test/tsan/mutexset2.cc
    compiler-rt/trunk/test/tsan/mutexset3.cc
    compiler-rt/trunk/test/tsan/mutexset4.cc
    compiler-rt/trunk/test/tsan/mutexset5.cc
    compiler-rt/trunk/test/tsan/mutexset6.cc
    compiler-rt/trunk/test/tsan/mutexset8.cc

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=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Wed Feb 19 08:17:25 2014
@@ -77,6 +77,8 @@ static const char *ReportTypeString(Repo
     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 ReportLo
     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
     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");

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=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Wed Feb 19 08:17:25 2014
@@ -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;
 };

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=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Wed Feb 19 08:17:25 2014
@@ -26,7 +26,7 @@ static __sanitizer::DeadlockDetector<DDB
 
 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
     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();

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=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Wed Feb 19 08:17:25 2014
@@ -278,6 +278,7 @@ void ScopedReport::AddMutex(const SyncVa
   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;
 }

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=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc (original)
+++ compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc Wed Feb 19 08:17:25 2014
@@ -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:

Modified: compiler-rt/trunk/test/tsan/mutex_cycle2.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutex_cycle2.c?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutex_cycle2.c (original)
+++ compiler-rt/trunk/test/tsan/mutex_cycle2.c Wed Feb 19 08:17:25 2014
@@ -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() {

Modified: compiler-rt/trunk/test/tsan/mutexset1.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset1.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset1.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset1.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset2.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset2.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset2.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset3.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset3.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset3.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset3.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset4.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset4.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset4.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset4.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset5.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset5.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset5.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset5.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset6.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset6.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset6.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset6.cc Wed Feb 19 08:17:25 2014
@@ -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);

Modified: compiler-rt/trunk/test/tsan/mutexset8.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutexset8.cc?rev=201675&r1=201674&r2=201675&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/mutexset8.cc (original)
+++ compiler-rt/trunk/test/tsan/mutexset8.cc Wed Feb 19 08:17:25 2014
@@ -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;





More information about the llvm-commits mailing list