[compiler-rt] r204127 - tsan: support up to 1<<20 mutexes in standalone deadlock detector

Dmitry Vyukov dvyukov at google.com
Tue Mar 18 01:31:12 PDT 2014


Author: dvyukov
Date: Tue Mar 18 03:31:11 2014
New Revision: 204127

URL: http://llvm.org/viewvc/llvm-project?rev=204127&view=rev
Log:
tsan: support up to 1<<20 mutexes in standalone deadlock detector


Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
    compiler-rt/trunk/lib/tsan/dd/dd_rtl.h

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc?rev=204127&r1=204126&r2=204127&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector2.cc Tue Mar 18 03:31:11 2014
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_common.h"
 #include "sanitizer_allocator_internal.h"
 #include "sanitizer_placement_new.h"
 #include "sanitizer_mutex.h"
@@ -20,11 +21,13 @@
 
 namespace __sanitizer {
 
-const int kMaxMutex = 1024;
 const int kMaxNesting = 64;
 const u32 kNoId = -1;
 const u32 kEndId = -2;
 const int kMaxLink = 8;
+const int kL1Size = 1024;
+const int kL2Size = 1024;
+const int kMaxMutex = kL1Size * kL2Size;
 
 struct Id {
   u32 id;
@@ -91,13 +94,16 @@ struct DD : public DDetector {
 
   void CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, DDMutex *mtx);
   void Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath);
+  u32 allocateId(DDCallback *cb);
+  Mutex *getMutex(u32 id);
+  u32 getMutexId(Mutex *m);
 
   SpinMutex mtx;
-  u32 free_id[kMaxMutex];
-  int nfree_id;
+  InternalMmapVector<u32> free_id;
+
   int id_gen;
 
-  Mutex mutex[kMaxMutex];
+  Mutex* mutex[kL1Size];
 };
 
 DDetector *DDetector::Create() {
@@ -105,8 +111,8 @@ DDetector *DDetector::Create() {
   return new(mem) DD();
 }
 
-DD::DD() {
-  nfree_id = 0;
+DD::DD()
+    : free_id(1024) {
   id_gen = 0;
 }
 
@@ -141,6 +147,41 @@ void DD::MutexInit(DDCallback *cb, DDMut
   atomic_store(&m->owner, 0, memory_order_relaxed);
 }
 
+Mutex *DD::getMutex(u32 id) {
+  return &mutex[id / kL2Size][id % kL2Size];
+}
+
+u32 DD::getMutexId(Mutex *m) {
+  for (int i = 0; i < kL1Size; i++) {
+    Mutex *tab = mutex[i];
+    if (tab == 0)
+      break;
+    if (m >= tab && m < tab + kL2Size)
+      return i * kL2Size + (m - tab);
+  }
+  return -1;
+}
+
+u32 DD::allocateId(DDCallback *cb) {
+  u32 id = -1;
+  SpinMutexLock l(&mtx);
+  if (free_id.size() > 0) {
+    id = free_id.back();
+    free_id.pop_back();
+  } else {
+    CHECK_LT(id_gen, kMaxMutex);
+    if ((id_gen % kL2Size) == 0) {
+      mutex[id_gen / kL2Size] = (Mutex*)MmapOrDie(kL2Size * sizeof(Mutex),
+          "deadlock detector (mutex table)");
+    }
+    id = id_gen++;
+  }
+  CHECK_LE(id, kMaxMutex);
+  VPrintf(3, "#%llu: DD::allocateId assign id %d\n",
+      cb->lt->ctx, id);
+  return id;
+}
+
 void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
   VPrintf(2, "#%llu: DD::MutexBeforeLock(%p, wlock=%d) nlocked=%d\n",
       cb->lt->ctx, m, wlock, cb->lt->nlocked);
@@ -156,17 +197,9 @@ void DD::MutexBeforeLock(DDCallback *cb,
 
   CHECK_LE(lt->nlocked, kMaxNesting);
 
-  if (m->id == kNoId) {
-    // FIXME(dvyukov): don't allocate id if lt->nlocked == 0
-    SpinMutexLock l(&mtx);
-    if (nfree_id > 0)
-      m->id = free_id[--nfree_id];
-    else
-      m->id = id_gen++;
-    CHECK_LE(id_gen, kMaxMutex);
-    VPrintf(3, "#%llu: DD::MutexBeforeLock assign id %d\n",
-        cb->lt->ctx, m->id);
-  }
+  // FIXME(dvyukov): don't allocate id if lt->nlocked == 0?
+  if (m->id == kNoId)
+    m->id = allocateId(cb);
 
   lt->locked[lt->nlocked++] = m->id;
   if (lt->nlocked == 1) {
@@ -176,10 +209,10 @@ void DD::MutexBeforeLock(DDCallback *cb,
   }
 
   bool added = false;
-  Mutex *mtx = &mutex[m->id];
+  Mutex *mtx = getMutex(m->id);
   for (int i = 0; i < lt->nlocked - 1; i++) {
     u32 id1 = lt->locked[i];
-    Mutex *mtx1 = &mutex[id1];
+    Mutex *mtx1 = getMutex(id1);
     SpinMutexLock l(&mtx1->mtx);
     if (mtx1->nlink == kMaxLink) {
       // FIXME(dvyukov): check stale links
@@ -195,7 +228,7 @@ void DD::MutexBeforeLock(DDCallback *cb,
           link->stk = cb->Unwind();
           added = true;
           VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
-              cb->lt->ctx, mtx1 - mutex, m->id);
+              cb->lt->ctx, getMutexId(mtx1), m->id);
         }
         break;
       }
@@ -209,7 +242,7 @@ void DD::MutexBeforeLock(DDCallback *cb,
       link->stk = cb->Unwind();
       added = true;
       VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
-          cb->lt->ctx, mtx1 - mutex, m->id);
+          cb->lt->ctx, getMutexId(mtx1), m->id);
     }
   }
 
@@ -247,17 +280,8 @@ void DD::MutexAfterLock(DDCallback *cb,
     return;
 
   CHECK_LE(lt->nlocked, kMaxNesting);
-  if (m->id == kNoId) {
-    // FIXME(dvyukov): don't allocate id if lt->nlocked == 0
-    SpinMutexLock l(&mtx);
-    if (nfree_id > 0)
-      m->id = free_id[--nfree_id];
-    else
-      m->id = id_gen++;
-    CHECK_LE(id_gen, kMaxMutex);
-    VPrintf(3, "#%llu: DD::MutexAfterLock assign id %d\n", cb->lt->ctx, m->id);
-  }
-
+  if (m->id == kNoId)
+    m->id = allocateId(cb);
   lt->locked[lt->nlocked++] = m->id;
 }
 
@@ -291,26 +315,24 @@ void DD::MutexDestroy(DDCallback *cb, DD
   if (m->id == kNoId)
     return;
   {
-    Mutex *mtx = &mutex[m->id];
+    Mutex *mtx = getMutex(m->id);
     SpinMutexLock l(&mtx->mtx);
     mtx->seq++;
     mtx->nlink = 0;
   }
   {
     SpinMutexLock l(&mtx);
-    free_id[nfree_id++] = m->id;
-    m->id = kNoId;
+    free_id.push_back(m->id);
   }
 }
 
 void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt,
     DDMutex *m) {
-  // Mutex *mtx = &mutex[m->id];
   internal_memset(pt->visited, 0, sizeof(pt->visited));
   int npath = 0;
   int npending = 0;
   {
-    Mutex *mtx = &mutex[m->id];
+    Mutex *mtx = getMutex(m->id);
     SpinMutexLock l(&mtx->mtx);
     for (int li = 0; li < mtx->nlink; li++)
       pt->pending[npending++] = mtx->link[li];
@@ -323,7 +345,7 @@ void DD::CycleCheck(DDPhysicalThread *pt
     }
     if (pt->visited[link.id])
       continue;
-    Mutex *mtx1 = &mutex[link.id];
+    Mutex *mtx1 = getMutex(link.id);
     SpinMutexLock l(&mtx1->mtx);
     if (mtx1->seq != link.seq)
       continue;
@@ -336,7 +358,7 @@ void DD::CycleCheck(DDPhysicalThread *pt
       return Report(pt, lt, npath);  // Bingo!
     for (int li = 0; li < mtx1->nlink; li++) {
       Link *link1 = &mtx1->link[li];
-      // Mutex *mtx2 = &mutex[link->id];
+      // Mutex *mtx2 = getMutex(link->id);
       // FIXME(dvyukov): fast seq check
       // FIXME(dvyukov): fast nlink != 0 check
       // FIXME(dvyukov): fast pending check?

Modified: compiler-rt/trunk/lib/tsan/dd/dd_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/dd/dd_rtl.h?rev=204127&r1=204126&r2=204127&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/dd/dd_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/dd/dd_rtl.h Tue Mar 18 03:31:11 2014
@@ -36,7 +36,7 @@ struct Callback : DDCallback {
   virtual u32 Unwind();
 };
 
-typedef AddrHashMap<Mutex, 1000003> MutexHashMap;
+typedef AddrHashMap<Mutex, 31051> MutexHashMap;
 
 struct Context {
   DDetector *dd;





More information about the llvm-commits mailing list