[compiler-rt] r202492 - [sanitizer] speedup deadlock detector for the case when we acquire the first lock in a thread

Kostya Serebryany kcc at google.com
Fri Feb 28 03:56:15 PST 2014


Author: kcc
Date: Fri Feb 28 05:56:14 2014
New Revision: 202492

URL: http://llvm.org/viewvc/llvm-project?rev=202492&view=rev
Log:
[sanitizer] speedup deadlock detector for the case when we acquire the first lock in a thread

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/tests/sanitizer_deadlock_detector_test.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=202492&r1=202491&r2=202492&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector.h Fri Feb 28 05:56:14 2014
@@ -42,6 +42,8 @@ class DeadlockDetectorTLS {
     epoch_ = 0;
   }
 
+  bool empty() const { return bv_.empty(); }
+
   void ensureCurrentEpoch(uptr current_epoch) {
     if (epoch_ == current_epoch) return;
     bv_.clear();
@@ -157,6 +159,18 @@ class DeadlockDetector {
     return false;
   }
 
+  // Returns true iff dtls is empty (no locks are currently held) and we can
+  // add the node to the currently held locks w/o chanding the global state.
+  // This operation is thread-safe as it only touches the dtls.
+  bool onFirstLock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
+    if (!dtls->empty()) return false;
+    if (dtls->getEpoch() && dtls->getEpoch() == nodeToEpoch(node)) {
+      dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node));
+      return true;
+    }
+    return false;
+  }
+
   // Finds a path between the lock 'cur_node' (which is currently held in dtls)
   // and some other currently held lock, returns the length of the path
   // or 0 on failure.
@@ -173,8 +187,8 @@ class DeadlockDetector {
     return res;
   }
 
-  // Handle the unlock event. This operation is thread-safe
-  // as it only touches the dtls.
+  // Handle the unlock event.
+  // This operation is thread-safe as it only touches the dtls.
   void onUnlock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
     if (dtls->getEpoch() == nodeToEpoch(node))
       dtls->removeLock(nodeToIndexUnchecked(node));

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=202492&r1=202491&r2=202492&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_deadlock_detector1.cc Fri Feb 28 05:56:14 2014
@@ -95,6 +95,8 @@ void DDetectorImpl::MutexEnsureID(DDLogi
 
 DDReport *DDetectorImpl::MutexLock(DDPhysicalThread *pt, DDLogicalThread *lt,
     DDMutex *m, bool writelock, bool trylock) {
+  if (dd.onFirstLock(&lt->dd, m->id))
+    return 0;
   SpinMutexLock lk(&mtx);
   MutexEnsureID(lt, m);
   CHECK(!dd.isHeld(&lt->dd, m->id));

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=202492&r1=202491&r2=202492&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 Feb 28 05:56:14 2014
@@ -338,3 +338,41 @@ TEST(DeadlockDetector, TryLockTest) {
   RunTryLockTest<BV1>();
   RunTryLockTest<BV2>();
 }
+
+template <class BV>
+void RunOnFirstLockTest() {
+  ScopedDD<BV> sdd;
+  DeadlockDetector<BV> &d = *sdd.dp;
+  DeadlockDetectorTLS<BV> &dtls = sdd.dtls;
+
+  uptr l0 = d.newNode(0);
+  uptr l1 = d.newNode(0);
+  EXPECT_FALSE(d.onFirstLock(&dtls, l0));  // dtls has old epoch.
+  d.onLock(&dtls, l0);
+  d.onUnlock(&dtls, l0);
+
+  EXPECT_TRUE(d.onFirstLock(&dtls, l0));  // Ok, same ecpoch, first lock.
+  EXPECT_FALSE(d.onFirstLock(&dtls, l1));  // Second lock.
+  d.onLock(&dtls, l1);
+  d.onUnlock(&dtls, l1);
+  d.onUnlock(&dtls, l0);
+
+  EXPECT_TRUE(d.onFirstLock(&dtls, l0));  // Ok
+  d.onUnlock(&dtls, l0);
+
+  vector<uptr> locks1;
+  for (uptr i = 0; i < d.size(); i++)
+    locks1.push_back(d.newNode(i));
+
+  EXPECT_TRUE(d.onFirstLock(&dtls, l0));  // Epoch has changed, but not in dtls.
+
+  uptr l3 = d.newNode(0);
+  d.onLock(&dtls, l3);
+  d.onUnlock(&dtls, l3);
+
+  EXPECT_FALSE(d.onFirstLock(&dtls, l0));  // Epoch has changed in dtls.
+}
+
+TEST(DeadlockDetector, onFirstLockTest) {
+  RunOnFirstLockTest<BV2>();
+}

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=202492&r1=202491&r2=202492&view=diff
==============================================================================
--- compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc (original)
+++ compiler-rt/trunk/test/tsan/deadlock_detector_stress_test.cc Fri Feb 28 05:56:14 2014
@@ -403,7 +403,7 @@ class LockTest {
   void Test15() {
     if (test_number > 0 && test_number != 15) return;
     if (!LockType::supports_read_lock()) return;
-    fprintf(stderr, "Starting Test15: 4 threads read lock/unlock 4 shared mutexes, all under another shared mutex\n");
+    fprintf(stderr, "Starting Test15: recursive rlock\n");
     // DISABLEDCHECK-RD: Starting Test15
     Init(5);
     RL(0); RL(0); RU(0); RU(0);  // Recusrive reader lock.
@@ -499,4 +499,3 @@ int main(int argc, char **argv) {
   fprintf(stderr, "ALL-DONE\n");
   // CHECK: ALL-DONE
 }
-





More information about the llvm-commits mailing list