summaryrefslogtreecommitdiff
path: root/lib/tsan
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2012-12-04 12:19:53 +0000
committerDmitry Vyukov <dvyukov@google.com>2012-12-04 12:19:53 +0000
commit0415ac00935795a70d87ae662ccad58ea0704537 (patch)
tree7d487c30b84708c14c6c39dba29989054f7f7eb7 /lib/tsan
parent43811a14504f1ff473b40c194a3e9054e2ea46a4 (diff)
tsan: fix trace handling when trace is reused between threads
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@169259 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r--lib/tsan/rtl/tsan_defs.h8
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc6
-rw-r--r--lib/tsan/rtl/tsan_rtl.h1
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc8
5 files changed, 21 insertions, 6 deletions
diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h
index 6d8e9cfc3..3a530041d 100644
--- a/lib/tsan/rtl/tsan_defs.h
+++ b/lib/tsan/rtl/tsan_defs.h
@@ -128,11 +128,17 @@ T max(T a, T b) {
}
template<typename T>
-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<typename T>
+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/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index b29fe6027..904558809 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/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/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index ce438556d..8366ef012 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/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/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index 3ca056227..dd967b9ab 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/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<uptr> stack(1024); // FIXME: de-hardcode 1024
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 4a0882c3b..75568def8 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/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);