summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc19
-rw-r--r--compiler-rt/test/tsan/deadlock_detector_stress_test.cc44
3 files changed, 43 insertions, 24 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index ad8dd7155ae..c87ad2d90bd 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -1047,7 +1047,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
int res = REAL(pthread_rwlock_tryrdlock)(m);
if (res == 0) {
- MutexReadLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
}
return res;
}
@@ -1074,7 +1074,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
int res = REAL(pthread_rwlock_trywrlock)(m);
if (res == 0) {
- MutexLock(thr, pc, (uptr)m);
+ MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
}
return res;
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
index b82768413b1..6a3100975e5 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -29,6 +29,15 @@ static void EnsureDeadlockDetectorID(Context *ctx, ThreadState *thr,
ctx->dd.ensureCurrentEpoch(&thr->deadlock_detector_tls);
}
+static void DDUnlock(Context *ctx, ThreadState *thr,
+ SyncVar *s) {
+ if (!common_flags()->detect_deadlocks) return;
+ Lock lk(&ctx->dd_mtx);
+ EnsureDeadlockDetectorID(ctx, thr, s);
+ // Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
+ ctx->dd.onUnlock(&thr->deadlock_detector_tls, s->deadlock_detector_id);
+}
+
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init) {
Context *ctx = CTX();
@@ -186,13 +195,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
}
}
thr->mset.Del(s->GetId(), true);
- if (common_flags()->detect_deadlocks) {
- Lock lk(&ctx->dd_mtx);
- EnsureDeadlockDetectorID(ctx, thr, s);
- // Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
- ctx->dd.onUnlock(&thr->deadlock_detector_tls,
- s->deadlock_detector_id);
- }
+ DDUnlock(ctx, thr, s);
s->mtx.Unlock();
return rec;
}
@@ -230,6 +233,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
PrintCurrentStack(thr, pc);
}
ReleaseImpl(thr, pc, &s->read_clock);
+ DDUnlock(CTX(), thr, s);
s->mtx.Unlock();
thr->mset.Del(s->GetId(), false);
}
@@ -267,6 +271,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
PrintCurrentStack(thr, pc);
}
thr->mset.Del(s->GetId(), write);
+ DDUnlock(CTX(), thr, s);
s->mtx.Unlock();
}
diff --git a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc
index da9451f21da..a4d4505a689 100644
--- a/compiler-rt/test/tsan/deadlock_detector_stress_test.cc
+++ b/compiler-rt/test/tsan/deadlock_detector_stress_test.cc
@@ -1,4 +1,8 @@
-// RUN: %clangxx_tsan %s -o %t
+// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex
+// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock
+// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
#include <pthread.h>
#undef NDEBUG
@@ -37,8 +41,22 @@ class PthreadSpinLock {
char padding_[64 - sizeof(pthread_spinlock_t)];
};
+class PthreadRWLock {
+ public:
+ PthreadRWLock() { assert(0 == pthread_rwlock_init(&mu_, 0)); }
+ ~PthreadRWLock() {
+ assert(0 == pthread_rwlock_destroy(&mu_));
+ (void)padding_;
+ }
+ void lock() { assert(0 == pthread_rwlock_wrlock(&mu_)); }
+ void unlock() { assert(0 == pthread_rwlock_unlock(&mu_)); }
+ bool try_lock() { return 0 == pthread_rwlock_trywrlock(&mu_); }
+
+ private:
+ pthread_rwlock_t mu_;
+ char padding_[64 - sizeof(pthread_rwlock_t)];
+};
-template <class LockType>
class LockTest {
public:
LockTest(size_t n) : n_(n), locks_(new LockType[n]) { }
@@ -184,7 +202,9 @@ class LockTest {
void CreateAndDestroyManyLocks() {
LockType create_many_locks_but_never_acquire[kDeadlockGraphSize];
+ (void)create_many_locks_but_never_acquire;
}
+
void CreateLockUnlockAndDestroyManyLocks() {
LockType many_locks[kDeadlockGraphSize];
for (size_t i = 0; i < kDeadlockGraphSize; i++) {
@@ -222,20 +242,14 @@ class LockTest {
LockType *locks_;
};
-template <class LockType>
-void RunAllTests() {
- { LockTest<LockType> t(5); t.Test1(); }
- { LockTest<LockType> t(5); t.Test2(); }
- { LockTest<LockType> t(5); t.Test3(); }
- { LockTest<LockType> t(5); t.Test4(); }
- { LockTest<LockType> t(5); t.Test5(); }
- { LockTest<LockType> t(5); t.Test6(); }
- { LockTest<LockType> t(10); t.Test7(); }
-}
-
int main () {
- RunAllTests<PthreadMutex>();
- RunAllTests<PthreadSpinLock>();
+ { LockTest t(5); t.Test1(); }
+ { LockTest t(5); t.Test2(); }
+ { LockTest t(5); t.Test3(); }
+ { LockTest t(5); t.Test4(); }
+ { LockTest t(5); t.Test5(); }
+ { LockTest t(5); t.Test6(); }
+ { LockTest t(10); t.Test7(); }
fprintf(stderr, "DONE\n");
// CHECK: DONE
}
OpenPOWER on IntegriCloud