diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-03-18 13:13:47 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-03-18 13:13:47 +0000 |
commit | b4a5f1c12ad45b35ebbceffc00bbc4ee788af90f (patch) | |
tree | 5263834472ee2f9258917d6696a8e85ebe8b511e | |
parent | bdac124f2d8fb16f88c8e5f1abf525aa673088ee (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.cc | 3 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_deadlock_detector2.cc | 27 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_deadlock_detector_interface.h | 6 | ||||
-rw-r--r-- | lib/tsan/dd/dd_rtl.cc | 31 | ||||
-rw-r--r-- | lib/tsan/dd/dd_rtl.h | 8 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_flags.cc | 6 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_flags.h | 3 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cc | 2 |
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 = <->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 = <->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", |