diff options
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 11 | ||||
-rw-r--r-- | compiler-rt/test/tsan/deadlock_detector_stress_test.cc | 20 |
2 files changed, 24 insertions, 7 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index bb471b02c94..5d54a42141a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -45,10 +45,6 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, s->is_rw = rw; s->is_recursive = recursive; s->is_linker_init = linker_init; - if (common_flags()->detect_deadlocks) { - EnsureDeadlockDetectorID(thr, s); - Printf("MutexCreate: %zx\n", s->deadlock_detector_id); - } s->mtx.Unlock(); } @@ -66,8 +62,9 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { if (s == 0) return; if (common_flags()->detect_deadlocks) { - EnsureDeadlockDetectorID(thr, s); - Printf("MutexDestroy: %zx\n", s->deadlock_detector_id); + if (s->deadlock_detector_id) + g_deadlock_detector.removeNode(s->deadlock_detector_id); + s->deadlock_detector_id = 0; } if (IsAppMem(addr)) { CHECK(!thr->is_freeing); @@ -169,7 +166,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) { thr->mset.Del(s->GetId(), true); if (common_flags()->detect_deadlocks) { EnsureDeadlockDetectorID(thr, s); - Printf("MutexUnlock: %zx\n", s->deadlock_detector_id); + // Printf("MutexUnlock: %zx\n", s->deadlock_detector_id); g_deadlock_detector.onUnlock(&thr->deadlock_detector_tls, s->deadlock_detector_id); } diff --git a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc index cb83f56da2f..b62df4df555 100644 --- a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc +++ b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc @@ -33,6 +33,7 @@ class LockTest { locks_[i].unlock(); } + // Simple lock order onversion. void Test1() { fprintf(stderr, "Starting Test1\n"); // CHECK: Starting Test1 @@ -42,6 +43,7 @@ class LockTest { // CHECK-NOT: ThreadSanitizer: } + // Simple lock order inversion with 3 locks. void Test2() { fprintf(stderr, "Starting Test2\n"); // CHECK: Starting Test2 @@ -51,7 +53,24 @@ class LockTest { // CHECK-NOT: ThreadSanitizer: } + // Lock order inversion with lots of new locks created (but not used) + // between. Since the new locks are not used we should still detect the + // deadlock. + void Test3() { + fprintf(stderr, "Starting Test3\n"); + // CHECK: Starting Test3 + L(0); L(1); U(0); U(1); + CreateAndDestroyManyLocks(); + L(1); L(0); U(0); U(1); + // CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock) + // CHECK-NOT: ThreadSanitizer: + } + private: + void CreateAndDestroyManyLocks() { + PaddedLock create_many_locks_but_never_acquire[kDeadlockGraphSize]; + } + static const size_t kDeadlockGraphSize = 4096; size_t n_; PaddedLock *locks_; }; @@ -59,6 +78,7 @@ class LockTest { int main() { { LockTest t(5); t.Test1(); } { LockTest t(5); t.Test2(); } + { LockTest t(5); t.Test3(); } fprintf(stderr, "DONE\n"); // CHECK: DONE } |