diff options
Diffstat (limited to 'lib/tsan/rtl/tsan_mutex.cc')
-rw-r--r-- | lib/tsan/rtl/tsan_mutex.cc | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/lib/tsan/rtl/tsan_mutex.cc b/lib/tsan/rtl/tsan_mutex.cc index a92fd90fd9c1..9ea9bae21b50 100644 --- a/lib/tsan/rtl/tsan_mutex.cc +++ b/lib/tsan/rtl/tsan_mutex.cc @@ -25,28 +25,29 @@ namespace __tsan { // then Report mutex can be locked while under Threads mutex. // The leaf mutexes can be locked under any other mutexes. // Recursive locking is not supported. -#if TSAN_DEBUG && !TSAN_GO +#if TSAN_DEBUG && !SANITIZER_GO const MutexType MutexTypeLeaf = (MutexType)-1; static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = { /*0 MutexTypeInvalid*/ {}, /*1 MutexTypeTrace*/ {MutexTypeLeaf}, /*2 MutexTypeThreads*/ {MutexTypeReport}, - /*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeSyncVar, + /*3 MutexTypeReport*/ {MutexTypeSyncVar, MutexTypeMBlock, MutexTypeJavaMBlock}, - /*4 MutexTypeSyncVar*/ {}, - /*5 MutexTypeSyncTab*/ {MutexTypeSyncVar}, + /*4 MutexTypeSyncVar*/ {MutexTypeDDetector}, + /*5 MutexTypeSyncTab*/ {}, // unused /*6 MutexTypeSlab*/ {MutexTypeLeaf}, /*7 MutexTypeAnnotations*/ {}, - /*8 MutexTypeAtExit*/ {MutexTypeSyncTab}, + /*8 MutexTypeAtExit*/ {MutexTypeSyncVar}, /*9 MutexTypeMBlock*/ {MutexTypeSyncVar}, /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar}, + /*11 MutexTypeDDetector*/ {}, }; static bool CanLockAdj[MutexTypeCount][MutexTypeCount]; #endif void InitializeMutex() { -#if TSAN_DEBUG && !TSAN_GO +#if TSAN_DEBUG && !SANITIZER_GO // Build the "can lock" adjacency matrix. // If [i][j]==true, then one can lock mutex j while under mutex i. const int N = MutexTypeCount; @@ -123,12 +124,12 @@ void InitializeMutex() { #endif } -DeadlockDetector::DeadlockDetector() { +InternalDeadlockDetector::InternalDeadlockDetector() { // Rely on zero initialization because some mutexes can be locked before ctor. } -#if TSAN_DEBUG && !TSAN_GO -void DeadlockDetector::Lock(MutexType t) { +#if TSAN_DEBUG && !SANITIZER_GO +void InternalDeadlockDetector::Lock(MutexType t) { // Printf("LOCK %d @%zu\n", t, seq_ + 1); CHECK_GT(t, MutexTypeInvalid); CHECK_LT(t, MutexTypeCount); @@ -155,13 +156,25 @@ void DeadlockDetector::Lock(MutexType t) { } } -void DeadlockDetector::Unlock(MutexType t) { +void InternalDeadlockDetector::Unlock(MutexType t) { // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]); CHECK(locked_[t]); locked_[t] = 0; } + +void InternalDeadlockDetector::CheckNoLocks() { + for (int i = 0; i != MutexTypeCount; i++) { + CHECK_EQ(locked_[i], 0); + } +} #endif +void CheckNoLocks(ThreadState *thr) { +#if TSAN_DEBUG && !SANITIZER_GO + thr->internal_deadlock_detector.CheckNoLocks(); +#endif +} + const uptr kUnlocked = 0; const uptr kWriteLock = 1; const uptr kReadLock = 2; @@ -209,8 +222,8 @@ Mutex::~Mutex() { } void Mutex::Lock() { -#if TSAN_DEBUG && !TSAN_GO - cur_thread()->deadlock_detector.Lock(type_); +#if TSAN_DEBUG && !SANITIZER_GO + cur_thread()->internal_deadlock_detector.Lock(type_); #endif uptr cmp = kUnlocked; if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock, @@ -221,7 +234,7 @@ void Mutex::Lock() { cmp = kUnlocked; if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock, memory_order_acquire)) { -#if TSAN_COLLECT_STATS +#if TSAN_COLLECT_STATS && !SANITIZER_GO StatInc(cur_thread(), stat_type_, backoff.Contention()); #endif return; @@ -234,14 +247,14 @@ void Mutex::Unlock() { uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release); (void)prev; DCHECK_NE(prev & kWriteLock, 0); -#if TSAN_DEBUG && !TSAN_GO - cur_thread()->deadlock_detector.Unlock(type_); +#if TSAN_DEBUG && !SANITIZER_GO + cur_thread()->internal_deadlock_detector.Unlock(type_); #endif } void Mutex::ReadLock() { -#if TSAN_DEBUG && !TSAN_GO - cur_thread()->deadlock_detector.Lock(type_); +#if TSAN_DEBUG && !SANITIZER_GO + cur_thread()->internal_deadlock_detector.Lock(type_); #endif uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire); if ((prev & kWriteLock) == 0) @@ -249,7 +262,7 @@ void Mutex::ReadLock() { for (Backoff backoff; backoff.Do();) { prev = atomic_load(&state_, memory_order_acquire); if ((prev & kWriteLock) == 0) { -#if TSAN_COLLECT_STATS +#if TSAN_COLLECT_STATS && !SANITIZER_GO StatInc(cur_thread(), stat_type_, backoff.Contention()); #endif return; @@ -262,8 +275,8 @@ void Mutex::ReadUnlock() { (void)prev; DCHECK_EQ(prev & kWriteLock, 0); DCHECK_GT(prev & ~kWriteLock, 0); -#if TSAN_DEBUG && !TSAN_GO - cur_thread()->deadlock_detector.Unlock(type_); +#if TSAN_DEBUG && !SANITIZER_GO + cur_thread()->internal_deadlock_detector.Unlock(type_); #endif } |