diff options
Diffstat (limited to 'lib/tsan/rtl/tsan_rtl_mutex.cc')
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 108 |
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 |