[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(<->dd, m->id))
+ return 0;
SpinMutexLock lk(&mtx);
MutexEnsureID(lt, m);
CHECK(!dd.isHeld(<->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