diff options
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; |

