summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc11
-rw-r--r--compiler-rt/test/tsan/deadlock_detector_stress_test.cc20
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
}
OpenPOWER on IntegriCloud