From 55b47cad335c7e4e0da93ee4794a4d2a908ebe9d Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 4 Dec 2012 12:19:53 +0000 Subject: [PATCH] tsan: fix trace handling when trace is reused between threads llvm-svn: 169259 --- compiler-rt/lib/tsan/rtl/tsan_defs.h | 8 +++++++- compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 6 +++++- compiler-rt/lib/tsan/rtl/tsan_rtl.h | 1 + compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 4 ++-- compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 8 ++++++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h index 6d8e9cf..3a53004 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -128,11 +128,17 @@ T max(T a, T b) { } template -T RoundUp(T p, int align) { +T RoundUp(T p, u64 align) { DCHECK_EQ(align & (align - 1), 0); return (T)(((u64)p + align - 1) & ~(align - 1)); } +template +T RoundDown(T p, u64 align) { + DCHECK_EQ(align & (align - 1), 0); + return (T)((u64)p & ~(align - 1)); +} + struct MD5Hash { u64 hash[2]; bool operator==(const MD5Hash &other) const; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index b29fe60..9045588 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -286,7 +286,7 @@ void TraceSwitch(ThreadState *thr) { thr->nomalloc++; ScopedInRtl in_rtl; Lock l(&thr->trace.mtx); - unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % kTraceParts; + unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); TraceHeader *hdr = &thr->trace.headers[trace]; hdr->epoch0 = thr->fast_state.epoch(); hdr->stack0.ObtainCurrent(thr, 0); @@ -303,6 +303,10 @@ uptr TraceSize() { return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1)); } +uptr TraceParts() { + return TraceSize() / kTracePartSize; +} + #ifndef TSAN_GO extern "C" void __tsan_trace_switch() { TraceSwitch(cur_thread()); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index ce43855..8366ef0 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -568,6 +568,7 @@ void AfterSleep(ThreadState *thr, uptr pc); void TraceSwitch(ThreadState *thr); uptr TraceTopPC(ThreadState *thr); uptr TraceSize(); +uptr TraceParts(); extern "C" void __tsan_trace_switch(); void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, FastState fs, diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index 3ca0562..dd967b9 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -265,12 +265,12 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk) { return; } Lock l(&trace->mtx); - const int partidx = (epoch / (TraceSize() / kTraceParts)) % kTraceParts; + const int partidx = (epoch / kTracePartSize) % TraceParts(); TraceHeader* hdr = &trace->headers[partidx]; if (epoch < hdr->epoch0) return; const u64 eend = epoch % TraceSize(); - const u64 ebegin = eend / kTracePartSize * kTracePartSize; + const u64 ebegin = RoundDown(eend, kTracePartSize); DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n", tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx); InternalScopedBuffer stack(1024); // FIXME: de-hardcode 1024 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index 4a0882c..75568de 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -187,7 +187,9 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) { CHECK_EQ(tctx->status, ThreadStatusCreated); tctx->status = ThreadStatusRunning; tctx->os_id = os_id; - tctx->epoch0 = tctx->epoch1 + 1; + // RoundUp so that one trace part does not contain events + // from different threads. + tctx->epoch0 = RoundUp(tctx->epoch1 + 1, kTracePartSize); tctx->epoch1 = (u64)-1; new(thr) ThreadState(CTX(), tid, tctx->unique_id, tctx->epoch0, stk_addr, stk_size, @@ -205,6 +207,8 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) { thr->clock.set(tid, tctx->epoch0); thr->clock.acquire(&tctx->sync); thr->fast_state.SetHistorySize(flags()->history_size); + const uptr trace = (tctx->epoch0 / kTracePartSize) % TraceParts(); + thr->trace.headers[trace].epoch0 = tctx->epoch0; StatInc(thr, StatSyncAcquire); DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx " "tls_addr=%zx tls_size=%zx\n", @@ -250,7 +254,7 @@ void ThreadFinish(ThreadState *thr) { // Save from info about the thread. tctx->dead_info = new(internal_alloc(MBlockDeadInfo, sizeof(ThreadDeadInfo))) ThreadDeadInfo(); - for (int i = 0; i < kTraceParts; i++) { + for (uptr i = 0; i < TraceParts(); i++) { tctx->dead_info->trace.headers[i].epoch0 = thr->trace.headers[i].epoch0; tctx->dead_info->trace.headers[i].stack0.CopyFrom( thr->trace.headers[i].stack0); -- 2.7.4