diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2012-08-16 15:08:49 +0000 | 
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2012-08-16 15:08:49 +0000 | 
| commit | 3482ec3bc8bd457bca29299ae1aa1ed16312f757 (patch) | |
| tree | 3470c39366355fdbd89edbd633ccfbcb0e642212 /compiler-rt | |
| parent | 19ae9f3b2ecf650d817fed2778f44de3f852a780 (diff) | |
| download | bcm5719-llvm-3482ec3bc8bd457bca29299ae1aa1ed16312f757.tar.gz bcm5719-llvm-3482ec3bc8bd457bca29299ae1aa1ed16312f757.zip | |
tsan: better diagnostics for destroy of a locked mutex + a test
llvm-svn: 162022
Diffstat (limited to 'compiler-rt')
| -rw-r--r-- | compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc | 29 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_report.cc | 5 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.h | 7 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 8 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_sync.cc | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_sync.h | 1 | 
7 files changed, 50 insertions, 3 deletions
| diff --git a/compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc b/compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc new file mode 100644 index 00000000000..f6ab874c2a2 --- /dev/null +++ b/compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc @@ -0,0 +1,29 @@ +#include <pthread.h> +#include <unistd.h> + +void *Thread(void *p) { +  pthread_mutex_lock((pthread_mutex_t*)p); +  return 0; +} + +int main() { +  pthread_mutex_t m; +  pthread_mutex_init(&m, 0); +  pthread_t t; +  pthread_create(&t, 0, Thread, &m); +  usleep(1000*1000); +  pthread_mutex_destroy(&m); +  pthread_join(t, 0); +  return 0; +} + +// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex +// CHECK:     #0 pthread_mutex_destroy +// CHECK:     #1 main +// CHECK:   and: +// CHECK:     #0 pthread_mutex_lock +// CHECK:     #1 Thread +// CHECK:   Mutex {{.*}} created at: +// CHECK:     #0 pthread_mutex_init +// CHECK:     #1 main + diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index c841a9827f4..7fc2e16f259 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -109,8 +109,11 @@ void PrintReport(const ReportDesc *rep) {    TsanPrintf("==================\n");    PrintHeader(rep->typ); -  for (uptr i = 0; i < rep->stacks.Size(); i++) +  for (uptr i = 0; i < rep->stacks.Size(); i++) { +    if (i) +      TsanPrintf("  and:\n");      PrintStack(rep->stacks[i]); +  }    for (uptr i = 0; i < rep->mops.Size(); i++)      PrintMop(rep->mops[i], i == 0); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index 336b656b7ce..8568f0af7da 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -83,6 +83,10 @@ class FastState {        : x_(x) {    } +  u64 raw() const { +    return x_; +  } +    u64 tid() const {      u64 res = x_ >> kTidShift;      return res; @@ -143,7 +147,6 @@ class Shadow : public FastState {    }    bool IsZero() const { return x_ == 0; } -  u64 raw() const { return x_; }    static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {      u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift; @@ -409,6 +412,8 @@ class ScopedReport {    void operator = (const ScopedReport&);  }; +void RestoreStack(int tid, const u64 epoch, StackTrace *stk); +  void StatAggregate(u64 *dst, u64 *src);  void StatOutput(u64 *stat);  void ALWAYS_INLINE INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index 44c400b8d15..258d203f50b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -47,6 +47,12 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {        s->is_broken = true;        ScopedReport rep(ReportTypeMutexDestroyLocked);        rep.AddMutex(s); +      StackTrace trace; +      trace.ObtainCurrent(thr, pc); +      rep.AddStack(&trace); +      FastState last(s->last_lock); +      RestoreStack(last.tid(), last.epoch(), &trace); +      rep.AddStack(&trace);        rep.AddLocation(s->addr, 1);        OutputReport(rep);      } @@ -64,6 +70,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {    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 { @@ -128,6 +135,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {      TsanPrintf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");    thr->clock.set(thr->tid, thr->fast_state.epoch());    thr->clock.acquire(&s->clock); +  s->last_lock = thr->fast_state.raw();    StatInc(thr, StatSyncAcquire);    s->mtx.ReadUnlock();  } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index f66e17e4815..6d1d49b080c 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -188,7 +188,7 @@ const ReportDesc *ScopedReport::GetReport() const {    return rep_;  } -static void RestoreStack(int tid, const u64 epoch, StackTrace *stk) { +void RestoreStack(int tid, const u64 epoch, StackTrace *stk) {    ThreadContext *tctx = CTX()->threads[tid];    if (tctx == 0)      return; diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc index 2004c8eb2cd..1f798b29756 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc @@ -21,6 +21,7 @@ SyncVar::SyncVar(uptr addr)    : mtx(MutexTypeSyncVar, StatMtxSyncVar)    , addr(addr)    , owner_tid(kInvalidTid) +  , last_lock()    , recursion()    , is_rw()    , is_recursive() diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.h b/compiler-rt/lib/tsan/rtl/tsan_sync.h index c96713096b3..89de81d54d8 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_sync.h +++ b/compiler-rt/lib/tsan/rtl/tsan_sync.h @@ -60,6 +60,7 @@ struct SyncVar {    SyncClock read_clock;  // Used for rw mutexes only.    StackTrace creation_stack;    int owner_tid;  // Set only by exclusive owners. +  u64 last_lock;    int recursion;    bool is_rw;    bool is_recursive; | 

