summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-04-25 07:42:55 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-04-25 07:42:55 +0000
commitc845decce1eaf0047b29bf44fef758ccd873be2d (patch)
tree613602abd1533386dd36c7fbcfb710ccfd844571 /compiler-rt
parent3212b18bbf8458cc9eabbb8938ffcef68af7473c (diff)
downloadbcm5719-llvm-c845decce1eaf0047b29bf44fef758ccd873be2d.tar.gz
bcm5719-llvm-c845decce1eaf0047b29bf44fef758ccd873be2d.zip
tsan: better reports for "double lock of a mutex"
+ fixes crashes due to races on symbolizer, see: https://code.google.com/p/thread-sanitizer/issues/detail?id=55 llvm-svn: 207204
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.h2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc19
-rw-r--r--compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc4
6 files changed, 27 insertions, 3 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
index 2dd9a0c7fe9..143120010a1 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
@@ -41,6 +41,7 @@ static void ParseFlags(Flags *f, const char *env) {
ParseFlag(env, &f->report_bugs, "report_bugs", "");
ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks", "");
ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked", "");
+ ParseFlag(env, &f->report_mutex_bugs, "report_mutex_bugs", "");
ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe", "");
ParseFlag(env, &f->report_atomic_races, "report_atomic_races", "");
ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics", "");
@@ -75,6 +76,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->report_bugs = true;
f->report_thread_leaks = true;
f->report_destroy_locked = true;
+ f->report_mutex_bugs = true;
f->report_signal_unsafe = true;
f->report_atomic_races = true;
f->force_seq_cst_atomics = false;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.h b/compiler-rt/lib/tsan/rtl/tsan_flags.h
index 2a765b135f6..cd489d66843 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.h
@@ -37,6 +37,8 @@ struct Flags : CommonFlags, DDFlags {
bool report_thread_leaks;
// Report destruction of a locked mutex?
bool report_destroy_locked;
+ // Report incorrect usages of mutexes and mutex annotations?
+ bool report_mutex_bugs;
// Report violations of async signal-safety
// (e.g. malloc() call from a signal handler).
bool report_signal_unsafe;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc
index 8beccd29f50..b0ad670da3e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc
@@ -74,6 +74,8 @@ static const char *ReportTypeString(ReportType typ) {
return "thread leak";
if (typ == ReportTypeMutexDestroyLocked)
return "destroy of a locked mutex";
+ if (typ == ReportTypeMutexDoubleLock)
+ return "double lock of a mutex";
if (typ == ReportTypeSignalUnsafe)
return "signal-unsafe call inside of a signal";
if (typ == ReportTypeErrnoInSignal)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h
index b37d00bec37..aaa562b5def 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.h
@@ -24,6 +24,7 @@ enum ReportType {
ReportTypeUseAfterFree,
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
+ ReportTypeMutexDoubleLock,
ReportTypeSignalUnsafe,
ReportTypeErrnoInSignal,
ReportTypeDeadlock
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
index e26e142368f..83e76968b32 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -117,15 +117,16 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
+ bool report_double_lock = false;
if (s->owner_tid == SyncVar::kInvalidTid) {
CHECK_EQ(s->recursion, 0);
s->owner_tid = thr->tid;
s->last_lock = thr->fast_state.raw();
} else if (s->owner_tid == thr->tid) {
CHECK_GT(s->recursion, 0);
- } else {
- Printf("ThreadSanitizer WARNING: double lock of mutex %p\n", addr);
- PrintCurrentStack(thr, pc);
+ } else if (flags()->report_mutex_bugs && !s->is_broken) {
+ s->is_broken = true;
+ report_double_lock = true;
}
if (s->recursion == 0) {
StatInc(thr, StatMutexLock);
@@ -142,7 +143,19 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec, bool try_lock) {
ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
ctx->dd->MutexAfterLock(&cb, &s->dd, true, 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 (flags()->detect_deadlocks) {
Callback cb(thr, pc);
ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc b/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc
index 33ddaaae2dd..3227d27ec92 100644
--- a/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc
+++ b/compiler-rt/lib/tsan/tests/unit/tsan_flags_test.cc
@@ -42,6 +42,7 @@ static const char *options1 =
" report_bugs=0"
" report_thread_leaks=0"
" report_destroy_locked=0"
+ " report_mutex_bugs=0"
" report_signal_unsafe=0"
" report_atomic_races=0"
" force_seq_cst_atomics=0"
@@ -86,6 +87,7 @@ static const char *options2 =
" report_bugs=true"
" report_thread_leaks=true"
" report_destroy_locked=true"
+ " report_mutex_bugs=true"
" report_signal_unsafe=true"
" report_atomic_races=true"
" force_seq_cst_atomics=true"
@@ -130,6 +132,7 @@ void VerifyOptions1(Flags *f) {
EXPECT_EQ(f->report_bugs, 0);
EXPECT_EQ(f->report_thread_leaks, 0);
EXPECT_EQ(f->report_destroy_locked, 0);
+ EXPECT_EQ(f->report_mutex_bugs, 0);
EXPECT_EQ(f->report_signal_unsafe, 0);
EXPECT_EQ(f->report_atomic_races, 0);
EXPECT_EQ(f->force_seq_cst_atomics, 0);
@@ -174,6 +177,7 @@ void VerifyOptions2(Flags *f) {
EXPECT_EQ(f->report_bugs, true);
EXPECT_EQ(f->report_thread_leaks, true);
EXPECT_EQ(f->report_destroy_locked, true);
+ EXPECT_EQ(f->report_mutex_bugs, true);
EXPECT_EQ(f->report_signal_unsafe, true);
EXPECT_EQ(f->report_atomic_races, true);
EXPECT_EQ(f->force_seq_cst_atomics, true);
OpenPOWER on IntegriCloud