summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-03-18 13:13:47 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-03-18 13:13:47 +0000
commitb4a5f1c12ad45b35ebbceffc00bbc4ee788af90f (patch)
tree5263834472ee2f9258917d6696a8e85ebe8b511e
parentbdac124f2d8fb16f88c8e5f1abf525aa673088ee (diff)
tsan: deadlock detector: add deadlock detector flags
the first flags is to enable printing of the second stack per edge git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@204150 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/sanitizer_common/sanitizer_deadlock_detector1.cc3
-rw-r--r--lib/sanitizer_common/sanitizer_deadlock_detector2.cc27
-rw-r--r--lib/sanitizer_common/sanitizer_deadlock_detector_interface.h6
-rw-r--r--lib/tsan/dd/dd_rtl.cc31
-rw-r--r--lib/tsan/dd/dd_rtl.h8
-rw-r--r--lib/tsan/rtl/tsan_flags.cc6
-rw-r--r--lib/tsan/rtl/tsan_flags.h3
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc2
8 files changed, 63 insertions, 23 deletions
diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector1.cc b/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
index 368bd41be..0e920d8a6 100644
--- a/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
+++ b/lib/sanitizer_common/sanitizer_deadlock_detector1.cc
@@ -56,7 +56,8 @@ struct DD : public DDetector {
void MutexEnsureID(DDLogicalThread *lt, DDMutex *m);
};
-DDetector *DDetector::Create() {
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
return new(mem) DD();
}
diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector2.cc b/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
index 3e9052ee0..55038c527 100644
--- a/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
+++ b/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
@@ -82,7 +82,7 @@ struct Mutex {
};
struct DD : public DDetector {
- explicit DD();
+ explicit DD(const DDFlags *flags);
DDPhysicalThread* CreatePhysicalThread();
void DestroyPhysicalThread(DDPhysicalThread *pt);
@@ -105,21 +105,24 @@ struct DD : public DDetector {
Mutex *getMutex(u32 id);
u32 getMutexId(Mutex *m);
+ DDFlags flags;
+
+ Mutex* mutex[kL1Size];
+
SpinMutex mtx;
InternalMmapVector<u32> free_id;
-
int id_gen;
-
- Mutex* mutex[kL1Size];
};
-DDetector *DDetector::Create() {
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
- return new(mem) DD();
+ return new(mem) DD(flags);
}
-DD::DD()
- : free_id(1024) {
+DD::DD(const DDFlags *flags)
+ : flags(*flags)
+ , free_id(1024) {
id_gen = 0;
}
@@ -210,7 +213,8 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
ThreadMutex *tm = &lt->locked[lt->nlocked++];
tm->id = m->id;
- tm->stk = cb->Unwind();
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
if (lt->nlocked == 1) {
VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
cb->lt->ctx);
@@ -296,7 +300,8 @@ void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
m->id = allocateId(cb);
ThreadMutex *tm = &lt->locked[lt->nlocked++];
tm->id = m->id;
- tm->stk = cb->Unwind();
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
}
void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
@@ -407,7 +412,7 @@ void DD::Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath) {
rep->loop[i].thr_ctx = link->tid;
rep->loop[i].mtx_ctx0 = link0->id;
rep->loop[i].mtx_ctx1 = link->id;
- rep->loop[i].stk[0] = link->stk0;
+ rep->loop[i].stk[0] = flags.second_deadlock_stack ? link->stk0 : 0;
rep->loop[i].stk[1] = link->stk1;
}
pt->report_pending = true;
diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h b/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
index 9c5dc8f4b..feb28af9e 100644
--- a/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
+++ b/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
@@ -46,6 +46,10 @@ struct DDMutex {
u64 ctx;
};
+struct DDFlags {
+ bool second_deadlock_stack;
+};
+
struct DDReport {
enum { kMaxLoopSize = 8 };
int n; // number of entries in loop
@@ -65,7 +69,7 @@ struct DDCallback {
};
struct DDetector {
- static DDetector *Create();
+ static DDetector *Create(const DDFlags *flags);
virtual DDPhysicalThread* CreatePhysicalThread() { return 0; }
virtual void DestroyPhysicalThread(DDPhysicalThread *pt) {}
diff --git a/lib/tsan/dd/dd_rtl.cc b/lib/tsan/dd/dd_rtl.cc
index 38716d5c3..474684397 100644
--- a/lib/tsan/dd/dd_rtl.cc
+++ b/lib/tsan/dd/dd_rtl.cc
@@ -45,9 +45,11 @@ static void ReportDeadlock(Thread *thr, DDReport *rep) {
Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
PrintStackTrace(thr, rep->loop[i].stk[1]);
- Printf("Mutex %llu was acquired here:\n",
- rep->loop[i].mtx_ctx0);
- PrintStackTrace(thr, rep->loop[i].stk[0]);
+ if (rep->loop[i].stk[0]) {
+ Printf("Mutex %llu was acquired here:\n",
+ rep->loop[i].mtx_ctx0);
+ PrintStackTrace(thr, rep->loop[i].stk[0]);
+ }
}
Printf("==============================\n");
Die();
@@ -63,15 +65,32 @@ u32 Callback::Unwind() {
return CurrentStackTrace(thr, 3);
}
+void InitializeFlags(Flags *f, const char *env) {
+ internal_memset(f, 0, sizeof(*f));
+
+ // Default values.
+ f->second_deadlock_stack = false;
+
+ SetCommonFlagsDefaults(f);
+ // Override some common flags defaults.
+ f->allow_addr2line = true;
+
+ // Override from command line.
+ ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack");
+ ParseCommonFlagsFromString(f, env);
+
+ // Copy back to common flags.
+ *common_flags() = *f;
+}
+
void Initialize() {
static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
ctx = new(ctx_mem) Context();
InitializeInterceptors();
- ParseCommonFlagsFromString(flags(), GetEnv("DSAN_OPTIONS"));
- //common_flags()->allow_addr2line = true;
+ InitializeFlags(flags(), GetEnv("DSAN_OPTIONS"));
common_flags()->symbolize = true;
- ctx->dd = DDetector::Create();
+ ctx->dd = DDetector::Create(flags());
}
void ThreadInit(Thread *thr) {
diff --git a/lib/tsan/dd/dd_rtl.h b/lib/tsan/dd/dd_rtl.h
index 673f86a3c..45d456e66 100644
--- a/lib/tsan/dd/dd_rtl.h
+++ b/lib/tsan/dd/dd_rtl.h
@@ -18,6 +18,9 @@
namespace __dsan {
+struct Flags : CommonFlags, DDFlags {
+};
+
struct Mutex {
DDMutex dd;
};
@@ -44,8 +47,9 @@ struct Context {
MutexHashMap mutex_map;
};
-inline CommonFlags* flags() {
- return common_flags();
+inline Flags* flags() {
+ static Flags flags;
+ return &flags;
}
void Initialize();
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index d11bf7ab6..631a2fa5c 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -59,6 +59,9 @@ static void ParseFlags(Flags *f, const char *env) {
ParseFlag(env, &f->history_size, "history_size");
ParseFlag(env, &f->io_sync, "io_sync");
ParseFlag(env, &f->die_after_fork, "die_after_fork");
+
+ // DDFlags
+ ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack");
}
void InitializeFlags(Flags *f, const char *env) {
@@ -91,6 +94,9 @@ void InitializeFlags(Flags *f, const char *env) {
f->io_sync = 1;
f->die_after_fork = true;
+ // DDFlags
+ f->second_deadlock_stack = false;
+
SetCommonFlagsDefaults(f);
// Override some common flags defaults.
f->allow_addr2line = true;
diff --git a/lib/tsan/rtl/tsan_flags.h b/lib/tsan/rtl/tsan_flags.h
index 001905f17..2a765b135 100644
--- a/lib/tsan/rtl/tsan_flags.h
+++ b/lib/tsan/rtl/tsan_flags.h
@@ -15,10 +15,11 @@
#define TSAN_FLAGS_H
#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
namespace __tsan {
-struct Flags : CommonFlags {
+struct Flags : CommonFlags, DDFlags {
// Enable dynamic annotations, otherwise they are no-ops.
bool enable_annotations;
// Supress a race report if we've already output another race report
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index b4bf10c2b..ec6caa0a7 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -251,7 +251,7 @@ void Initialize(ThreadState *thr) {
#endif
internal_start_thread(&BackgroundThread, 0);
if (flags()->detect_deadlocks)
- ctx->dd = DDetector::Create();
+ ctx->dd = DDetector::Create(flags());
if (ctx->flags.verbosity)
Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",