aboutsummaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_mutex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl/tsan_mutex.cc')
-rw-r--r--lib/tsan/rtl/tsan_mutex.cc65
1 files changed, 40 insertions, 25 deletions
diff --git a/lib/tsan/rtl/tsan_mutex.cc b/lib/tsan/rtl/tsan_mutex.cc
index 1a70f8fe4430..335ca2211d13 100644
--- a/lib/tsan/rtl/tsan_mutex.cc
+++ b/lib/tsan/rtl/tsan_mutex.cc
@@ -25,22 +25,28 @@ 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
const MutexType MutexTypeLeaf = (MutexType)-1;
static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
- /*0 MutexTypeInvalid*/ {},
- /*1 MutexTypeTrace*/ {MutexTypeLeaf},
- /*2 MutexTypeThreads*/ {MutexTypeReport},
- /*3 MutexTypeReport*/ {},
- /*4 MutexTypeSyncVar*/ {},
- /*5 MutexTypeSyncTab*/ {MutexTypeSyncVar},
- /*6 MutexTypeSlab*/ {MutexTypeLeaf},
- /*7 MutexTypeAnnotations*/ {},
- /*8 MutexTypeAtExit*/ {MutexTypeSyncTab},
+ /*0 MutexTypeInvalid*/ {},
+ /*1 MutexTypeTrace*/ {MutexTypeLeaf},
+ /*2 MutexTypeThreads*/ {MutexTypeReport},
+ /*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeMBlock,
+ MutexTypeJavaMBlock},
+ /*4 MutexTypeSyncVar*/ {},
+ /*5 MutexTypeSyncTab*/ {MutexTypeSyncVar},
+ /*6 MutexTypeSlab*/ {MutexTypeLeaf},
+ /*7 MutexTypeAnnotations*/ {},
+ /*8 MutexTypeAtExit*/ {MutexTypeSyncTab},
+ /*9 MutexTypeMBlock*/ {MutexTypeSyncVar},
+ /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar},
};
static bool CanLockAdj[MutexTypeCount][MutexTypeCount];
+#endif
void InitializeMutex() {
+#if TSAN_DEBUG && !TSAN_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;
@@ -48,7 +54,7 @@ void InitializeMutex() {
bool leaf[N] = {};
for (int i = 1; i < N; i++) {
for (int j = 0; j < N; j++) {
- int z = CanLockTab[i][j];
+ MutexType z = CanLockTab[i][j];
if (z == MutexTypeInvalid)
continue;
if (z == MutexTypeLeaf) {
@@ -56,8 +62,8 @@ void InitializeMutex() {
leaf[i] = true;
continue;
}
- CHECK(!CanLockAdj[i][z]);
- CanLockAdj[i][z] = true;
+ CHECK(!CanLockAdj[i][(int)z]);
+ CanLockAdj[i][(int)z] = true;
cnt[i]++;
}
}
@@ -92,36 +98,40 @@ void InitializeMutex() {
}
}
#if 0
- TsanPrintf("Can lock graph:\n");
+ Printf("Can lock graph:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- TsanPrintf("%d ", CanLockAdj[i][j]);
+ Printf("%d ", CanLockAdj[i][j]);
}
- TsanPrintf("\n");
+ Printf("\n");
}
- TsanPrintf("Can lock graph closure:\n");
+ Printf("Can lock graph closure:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
- TsanPrintf("%d ", CanLockAdj2[i][j]);
+ Printf("%d ", CanLockAdj2[i][j]);
}
- TsanPrintf("\n");
+ Printf("\n");
}
#endif
// Verify that the graph is acyclic.
for (int i = 0; i < N; i++) {
if (CanLockAdj2[i][i]) {
- TsanPrintf("Mutex %d participates in a cycle\n", i);
+ Printf("Mutex %d participates in a cycle\n", i);
Die();
}
}
+#endif
}
DeadlockDetector::DeadlockDetector() {
// Rely on zero initialization because some mutexes can be locked before ctor.
}
+#if TSAN_DEBUG && !TSAN_GO
void DeadlockDetector::Lock(MutexType t) {
- // TsanPrintf("LOCK %d @%zu\n", t, seq_ + 1);
+ // Printf("LOCK %d @%zu\n", t, seq_ + 1);
+ CHECK_GT(t, MutexTypeInvalid);
+ CHECK_LT(t, MutexTypeCount);
u64 max_seq = 0;
u64 max_idx = MutexTypeInvalid;
for (int i = 0; i != MutexTypeCount; i++) {
@@ -136,20 +146,21 @@ void DeadlockDetector::Lock(MutexType t) {
locked_[t] = ++seq_;
if (max_idx == MutexTypeInvalid)
return;
- // TsanPrintf(" last %d @%zu\n", max_idx, max_seq);
+ // Printf(" last %d @%zu\n", max_idx, max_seq);
if (!CanLockAdj[max_idx][t]) {
- TsanPrintf("ThreadSanitizer: internal deadlock detected\n");
- TsanPrintf("ThreadSanitizer: can't lock %d while under %zu\n",
+ Printf("ThreadSanitizer: internal deadlock detected\n");
+ Printf("ThreadSanitizer: can't lock %d while under %zu\n",
t, (uptr)max_idx);
- Die();
+ CHECK(0);
}
}
void DeadlockDetector::Unlock(MutexType t) {
- // TsanPrintf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
+ // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
CHECK(locked_[t]);
locked_[t] = 0;
}
+#endif
const uptr kUnlocked = 0;
const uptr kWriteLock = 1;
@@ -256,4 +267,8 @@ void Mutex::ReadUnlock() {
#endif
}
+void Mutex::CheckLocked() {
+ CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0);
+}
+
} // namespace __tsan