summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-04-25 08:21:30 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-04-25 08:21:30 +0000
commit2a10d45fc5321f31c5a0cb8ccf8e17c5d2a67ed2 (patch)
tree97dcc561ac3314b58491159cb504fb816ea363db /lib/tsan/rtl
parent087f9f66700726d1f4e6a70cdac3b9202c857f9f (diff)
tsan: improve "read unlock of a write locked mutex" report
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@207208 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/rtl')
-rw-r--r--lib/tsan/rtl/tsan_report.cc2
-rw-r--r--lib/tsan/rtl/tsan_report.h1
-rw-r--r--lib/tsan/rtl/tsan_rtl_mutex.cc22
3 files changed, 21 insertions, 4 deletions
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 6875c4cad..98a7d0f4d 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 == ReportTypeMutexBadReadUnlock)
+ return "read unlock of a write locked mutex";
if (typ == ReportTypeSignalUnsafe)
return "signal-unsafe call inside of a signal";
if (typ == ReportTypeErrnoInSignal)
diff --git a/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h
index 5b643351b..7c14eff18 100644
--- a/lib/tsan/rtl/tsan_report.h
+++ b/lib/tsan/rtl/tsan_report.h
@@ -26,6 +26,7 @@ enum ReportType {
ReportTypeMutexDestroyLocked,
ReportTypeMutexDoubleLock,
ReportTypeMutexBadUnlock,
+ ReportTypeMutexBadReadUnlock,
ReportTypeSignalUnsafe,
ReportTypeErrnoInSignal,
ReportTypeDeadlock
diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc
index 4f6a2d09b..ae6e4f798 100644
--- a/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -249,18 +249,32 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
+ bool report_bad_unlock = false;
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read unlock 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_unlock = true;
+ }
}
ReleaseImpl(thr, pc, &s->read_clock);
if (flags()->detect_deadlocks && s->recursion == 0) {
Callback cb(thr, pc);
ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
}
+ u64 mid = s->GetId();
s->mtx.Unlock();
- thr->mset.Del(s->GetId(), false);
+ // 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 (flags()->detect_deadlocks) {
Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));