diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 08:58:23 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-04-25 08:58:23 +0000 |
commit | af11ce221730ad4056c5d541819e95b795fba103 (patch) | |
tree | 04fe68b5bc60f8c7221fc942f564c1f52a7a5100 /lib/tsan | |
parent | 2a10d45fc5321f31c5a0cb8ccf8e17c5d2a67ed2 (diff) |
tsan: better reports for "read lock of a write locked mutex"
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@207209 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r-- | lib/tsan/rtl/tsan_report.cc | 2 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_report.h | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 60 |
3 files changed, 30 insertions, 33 deletions
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index 98a7d0f4d..a835cee7d 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/lib/tsan/rtl/tsan_report.cc @@ -78,6 +78,8 @@ static const char *ReportTypeString(ReportType typ) { return "double lock of a mutex"; if (typ == ReportTypeMutexBadUnlock) return "unlock of an unlocked mutex (or by a wrong thread)"; + if (typ == ReportTypeMutexBadReadLock) + return "read lock of a write locked mutex"; if (typ == ReportTypeMutexBadReadUnlock) return "read unlock of a write locked mutex"; if (typ == ReportTypeSignalUnsafe) diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h index 7c14eff18..3817bcdfc 100644 --- a/lib/tsan/rtl/tsan_report.h +++ b/lib/tsan/rtl/tsan_report.h @@ -26,6 +26,7 @@ enum ReportType { ReportTypeMutexDestroyLocked, ReportTypeMutexDoubleLock, ReportTypeMutexBadUnlock, + ReportTypeMutexBadReadLock, ReportTypeMutexBadReadUnlock, ReportTypeSignalUnsafe, ReportTypeErrnoInSignal, diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc index ae6e4f798..5cb06a870 100644 --- a/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -50,6 +50,18 @@ void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) { s->dd.ctx = s->GetId(); } +static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ, + uptr addr, u64 mid) { + ThreadRegistryLock l(ctx->thread_registry); + ScopedReport rep(typ); + rep.AddMutex(mid); + StackTrace trace; + trace.ObtainCurrent(thr, pc); + rep.AddStack(&trace); + rep.AddLocation(addr, 1); + OutputReport(ctx, rep); +} + void MutexCreate(ThreadState *thr, uptr pc, uptr addr, bool rw, bool recursive, bool linker_init) { DPrintf("#%d: MutexCreate %zx\n", thr->tid, addr); @@ -146,16 +158,8 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) { u64 mid = s->GetId(); s->mtx.Unlock(); // Can't touch s after this point. - if (report_double_lock) { - ThreadRegistryLock l(ctx->thread_registry); - ScopedReport rep(ReportTypeMutexDoubleLock); - rep.AddMutex(mid); - StackTrace trace; - trace.ObtainCurrent(thr, pc); - rep.AddStack(&trace); - rep.AddLocation(addr, 1); - OutputReport(ctx, rep); - } + if (report_double_lock) + ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr, mid); if (flags()->detect_deadlocks) { Callback cb(thr, pc); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); @@ -195,16 +199,8 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) { u64 mid = s->GetId(); s->mtx.Unlock(); // Can't touch s after this point. - if (report_bad_unlock) { - ThreadRegistryLock l(ctx->thread_registry); - ScopedReport rep(ReportTypeMutexBadUnlock); - rep.AddMutex(mid); - StackTrace trace; - trace.ObtainCurrent(thr, pc); - rep.AddStack(&trace); - rep.AddLocation(addr, 1); - OutputReport(ctx, rep); - } + if (report_bad_unlock) + ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr, mid); if (flags()->detect_deadlocks) { Callback cb(thr, pc); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); @@ -220,10 +216,12 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) { SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, false); thr->fast_state.IncrementEpoch(); TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId()); + bool report_bad_lock = false; if (s->owner_tid != SyncVar::kInvalidTid) { - Printf("ThreadSanitizer WARNING: read lock of a write locked mutex %p\n", - addr); - PrintCurrentStack(thr, pc); + if (flags()->report_mutex_bugs && !s->is_broken) { + s->is_broken = true; + report_bad_lock = true; + } } AcquireImpl(thr, pc, &s->clock); s->last_lock = thr->fast_state.raw(); @@ -234,7 +232,11 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool trylock) { ctx->dd->MutexBeforeLock(&cb, &s->dd, false); ctx->dd->MutexAfterLock(&cb, &s->dd, false, trylock); } + u64 mid = s->GetId(); s->mtx.ReadUnlock(); + // Can't touch s after this point. + if (report_bad_lock) + ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr, mid); if (flags()->detect_deadlocks) { Callback cb(thr, pc); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); @@ -265,16 +267,8 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) { s->mtx.Unlock(); // Can't touch s after this point. thr->mset.Del(mid, false); - if (report_bad_unlock) { - ThreadRegistryLock l(ctx->thread_registry); - ScopedReport rep(ReportTypeMutexBadReadUnlock); - rep.AddMutex(mid); - StackTrace trace; - trace.ObtainCurrent(thr, pc); - rep.AddStack(&trace); - rep.AddLocation(addr, 1); - OutputReport(ctx, rep); - } + if (report_bad_unlock) + ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr, mid); if (flags()->detect_deadlocks) { Callback cb(thr, pc); ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb)); |