summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_rtl_mutex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl/tsan_rtl_mutex.cc')
-rw-r--r--lib/tsan/rtl/tsan_rtl_mutex.cc108
1 files changed, 48 insertions, 60 deletions
diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc
index c33328126..fbbd5ee46 100644
--- a/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include <sanitizer_common/sanitizer_deadlock_detector.h>
+#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
#include "tsan_rtl.h"
#include "tsan_flags.h"
@@ -22,50 +22,7 @@
namespace __tsan {
-static void EnsureDeadlockDetectorID(Context *ctx, ThreadState *thr,
- SyncVar *s) {
- if (!ctx->dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
- s->deadlock_detector_id = ctx->dd.newNode(reinterpret_cast<uptr>(s));
- ctx->dd.ensureCurrentEpoch(&thr->deadlock_detector_tls);
-}
-
-static void DDUnlock(Context *ctx, ThreadState *thr, SyncVar *s) {
- if (!common_flags()->detect_deadlocks) return;
- if (s->recursion != 0) return;
- // Printf("T%d MutexUnlock: %zx; recursion %d\n", thr->tid,
- // s->deadlock_detector_id, s->recursion);
- ctx->dd.onUnlock(&thr->deadlock_detector_tls, s->deadlock_detector_id);
-}
-
-static void DDLock(Context *ctx, ThreadState *thr, SyncVar *s, uptr pc,
- bool try_lock) {
- if (!common_flags()->detect_deadlocks) return;
- if (s->recursion > 1) return;
- Lock lk(&ctx->dd_mtx);
- EnsureDeadlockDetectorID(ctx, thr, s);
- CHECK(!ctx->dd.isHeld(&thr->deadlock_detector_tls, s->deadlock_detector_id));
- // Printf("T%d MutexLock: %zx\n", thr->tid, s->deadlock_detector_id);
- bool has_deadlock = try_lock
- ? ctx->dd.onTryLock(&thr->deadlock_detector_tls,
- s->deadlock_detector_id)
- : ctx->dd.onLock(&thr->deadlock_detector_tls,
- s->deadlock_detector_id);
- if (has_deadlock) {
- uptr path[10];
- uptr len = ctx->dd.findPathToHeldLock(&thr->deadlock_detector_tls,
- s->deadlock_detector_id, path,
- ARRAY_SIZE(path));
- CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
- ThreadRegistryLock l(CTX()->thread_registry);
- ScopedReport rep(ReportTypeDeadlock);
- for (uptr i = 0; i < len; i++)
- rep.AddMutex(reinterpret_cast<SyncVar*>(ctx->dd.getData(path[i])));
- StackTrace trace;
- trace.ObtainCurrent(thr, pc);
- rep.AddStack(&trace);
- OutputReport(CTX(), rep);
- }
-}
+void ReportDeadlockReport(ThreadState *thr, uptr pc, DDReport *r);
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init) {
@@ -98,12 +55,8 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
SyncVar *s = ctx->synctab.GetAndRemove(thr, pc, addr);
if (s == 0)
return;
- if (common_flags()->detect_deadlocks) {
- Lock lk(&ctx->dd_mtx);
- if (ctx->dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
- ctx->dd.removeNode(s->deadlock_detector_id);
- s->deadlock_detector_id = 0;
- }
+ if (flags()->detect_deadlocks)
+ ctx->dd->MutexDestroy(thr->dd_pt, thr->dd_lt, &s->dd);
if (IsAppMem(addr)) {
CHECK(!thr->is_freeing);
thr->is_freeing = true;
@@ -158,8 +111,12 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
}
s->recursion += rec;
thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
- DDLock(ctx, thr, s, pc, try_lock);
+ DDReport *dd_rep = 0;
+ if (flags()->detect_deadlocks && s->recursion == 1)
+ dd_rep = ctx->dd->MutexLock(thr->dd_pt, thr->dd_lt, &s->dd, true, try_lock);
s->mtx.Unlock();
+ if (dd_rep)
+ ReportDeadlockReport(thr, pc, dd_rep);
}
int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
@@ -196,17 +153,22 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
}
}
thr->mset.Del(s->GetId(), true);
- DDUnlock(ctx, thr, s);
+ DDReport *dd_rep = 0;
+ if (flags()->detect_deadlocks && s->recursion == 0)
+ dd_rep = ctx->dd->MutexUnlock(thr->dd_pt, thr->dd_lt, &s->dd, true);
s->mtx.Unlock();
+ if (dd_rep)
+ ReportDeadlockReport(thr, pc, dd_rep);
return rec;
}
-void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool try_lock) {
+void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) {
+ Context *ctx = CTX();
DPrintf("#%d: MutexReadLock %zx\n", thr->tid, addr);
StatInc(thr, StatMutexReadLock);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, false);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
@@ -217,16 +179,21 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool try_lock) {
AcquireImpl(thr, pc, &s->clock);
s->last_lock = thr->fast_state.raw();
thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
- DDLock(CTX(), thr, s, pc, try_lock);
+ DDReport *dd_rep = 0;
+ if (flags()->detect_deadlocks && s->recursion == 0)
+ dd_rep = ctx->dd->MutexLock(thr->dd_pt, thr->dd_lt, &s->dd, false, trylock);
s->mtx.ReadUnlock();
+ if (dd_rep)
+ ReportDeadlockReport(thr, pc, dd_rep);
}
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
+ Context *ctx = CTX();
DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
StatInc(thr, StatMutexReadUnlock);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
@@ -235,16 +202,21 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
PrintCurrentStack(thr, pc);
}
ReleaseImpl(thr, pc, &s->read_clock);
- DDUnlock(CTX(), thr, s);
+ DDReport *dd_rep = 0;
+ if (flags()->detect_deadlocks && s->recursion == 0)
+ dd_rep = ctx->dd->MutexUnlock(thr->dd_pt, thr->dd_lt, &s->dd, false);
s->mtx.Unlock();
thr->mset.Del(s->GetId(), false);
+ if (dd_rep)
+ ReportDeadlockReport(thr, pc, dd_rep);
}
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
+ Context *ctx = CTX();
DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
bool write = true;
if (s->owner_tid == SyncVar::kInvalidTid) {
// Seems to be read unlock.
@@ -273,8 +245,12 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
PrintCurrentStack(thr, pc);
}
thr->mset.Del(s->GetId(), write);
- DDUnlock(CTX(), thr, s);
+ DDReport *dd_rep = 0;
+ if (flags()->detect_deadlocks && s->recursion == 0)
+ dd_rep = ctx->dd->MutexUnlock(thr->dd_pt, thr->dd_lt, &s->dd, write);
s->mtx.Unlock();
+ if (dd_rep)
+ ReportDeadlockReport(thr, pc, dd_rep);
}
void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
@@ -394,4 +370,16 @@ void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
StatInc(thr, StatSyncRelease);
}
+void ReportDeadlockReport(ThreadState *thr, uptr pc, DDReport *r) {
+ Context *ctx = CTX();
+ ThreadRegistryLock l(ctx->thread_registry);
+ ScopedReport rep(ReportTypeDeadlock);
+ for (int i = 0; i < r->n; i++)
+ rep.AddMutex(r->loop[i].mtx_ctx0);
+ StackTrace trace;
+ trace.ObtainCurrent(thr, pc);
+ rep.AddStack(&trace);
+ OutputReport(ctx, rep);
+}
+
} // namespace __tsan