diff options
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 4 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 19 | ||||
-rw-r--r-- | compiler-rt/test/tsan/deadlock_detector_stress_test.cc | 44 |
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 } |