From 79915de6af800b892c11d6bf96259052150b3359 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 20 Mar 2013 10:31:53 +0000 Subject: [PATCH] tsan: move trace header into 0x600000000000 range eliminat thread "dead info" altogether llvm-svn: 177512 --- compiler-rt/lib/tsan/rtl/tsan_platform.h | 8 +++++++- compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 23 +++++++++++++++++++---- compiler-rt/lib/tsan/rtl/tsan_rtl.h | 10 +++------- compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 15 ++++----------- compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 19 ++++++------------- 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 2a07599..15b4d10 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -138,7 +138,13 @@ void WriteMemoryProfile(char *buf, uptr buf_size); const char *InitializePlatform(); void FinalizePlatform(); uptr ALWAYS_INLINE INLINE GetThreadTrace(int tid) { - uptr p = kTraceMemBegin + (uptr)tid * kTraceSize * sizeof(Event); + uptr p = kTraceMemBegin + (uptr)(tid * 2) * kTraceSize * sizeof(Event); + DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); + return p; +} + +uptr ALWAYS_INLINE INLINE GetThreadTraceHeader(int tid) { + uptr p = kTraceMemBegin + (uptr)(tid * 2 + 1) * kTraceSize * sizeof(Event); DCHECK_LT(p, kTraceMemBegin + kTraceMemSize); return p; } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 37f65eb..6efb287 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -52,7 +52,9 @@ static char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadContextBase *CreateThreadContext(u32 tid) { // Map thread trace when context is created. MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event)); - void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext"); + MapThreadTrace(GetThreadTraceHeader(tid), sizeof(Trace)); + new(ThreadTrace(tid)) Trace(); + void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); return new(mem) ThreadContext(tid); } @@ -285,15 +287,20 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) { void TraceSwitch(ThreadState *thr) { thr->nomalloc++; ScopedInRtl in_rtl; - Lock l(&thr->trace.mtx); + Trace *thr_trace = ThreadTrace(thr->tid); + Lock l(&thr_trace->mtx); unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); - TraceHeader *hdr = &thr->trace.headers[trace]; + TraceHeader *hdr = &thr_trace->headers[trace]; hdr->epoch0 = thr->fast_state.epoch(); hdr->stack0.ObtainCurrent(thr, 0); hdr->mset0 = thr->mset; thr->nomalloc--; } +Trace *ThreadTrace(int tid) { + return (Trace*)GetThreadTraceHeader(tid); +} + uptr TraceTopPC(ThreadState *thr) { Event *events = (Event*)GetThreadTrace(thr->tid); uptr pc = events[thr->fast_state.GetTracePos()]; @@ -377,7 +384,15 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, // 'candidates' with 'same' or 'replace', but I think // it's just not worth it (performance- and complexity-wise). - Shadow old(0); + Shadow old(LoadShadow(shadow_mem)); +Printf("MOP %p -> %p %llu\n", addr, shadow_mem, old.raw()); + if (old.raw() == kShadowRodata) { + // Access to .rodata section, no races here. + // Measurements show that it can be 10-20% of all memory accesses. + StatInc(thr, StatMopRodata); + return; + } + if (kShadowCnt == 1) { int idx = 0; #include "tsan_update_shadow_word_inl.h" diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index 19929de..2b9aaf4 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -137,6 +137,8 @@ Allocator *allocator(); void TsanCheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); +const u64 kShadowRodata = (u64)-1; // .rodata shadow marker + // FastState (from most significant bit): // ignore : 1 // tid : kTidBits @@ -404,7 +406,6 @@ struct ThreadState { uptr *shadow_stack_pos; u64 *racy_shadow_addr; u64 racy_state[2]; - Trace trace; #ifndef TSAN_GO // C/C++ uses embed shadow stack of fixed size. uptr shadow_stack[kShadowStackSize]; @@ -458,11 +459,6 @@ INLINE ThreadState *cur_thread() { } #endif -// An info about a thread that is hold for some time after its termination. -struct ThreadDeadInfo { - Trace trace; -}; - class ThreadContext : public ThreadContextBase { public: explicit ThreadContext(int tid); @@ -479,7 +475,6 @@ class ThreadContext : public ThreadContextBase { // the event is from a dead thread that shared tid with this thread. u64 epoch0; u64 epoch1; - ThreadDeadInfo *dead_info; // Override superclass callbacks. void OnDead(); @@ -719,6 +714,7 @@ void TraceSwitch(ThreadState *thr); uptr TraceTopPC(ThreadState *thr); uptr TraceSize(); uptr TraceParts(); +Trace *ThreadTrace(int tid); 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 2df4234..b343ff3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -379,18 +379,11 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset) { ctx->thread_registry->GetThreadLocked(tid)); if (tctx == 0) return; - Trace* trace = 0; - if (tctx->status == ThreadStatusRunning) { - CHECK(tctx->thr); - trace = &tctx->thr->trace; - } else if (tctx->status == ThreadStatusFinished - || tctx->status == ThreadStatusDead) { - if (tctx->dead_info == 0) - return; - trace = &tctx->dead_info->trace; - } else { + if (tctx->status != ThreadStatusRunning + && tctx->status != ThreadStatusFinished + && tctx->status != ThreadStatusDead) return; - } + Trace* trace = ThreadTrace(tctx->tid); Lock l(&trace->mtx); const int partidx = (epoch / kTracePartSize) % TraceParts(); TraceHeader* hdr = &trace->headers[partidx]; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index 476b670..3be9b83 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -27,8 +27,7 @@ ThreadContext::ThreadContext(int tid) , thr() , sync() , epoch0() - , epoch1() - , dead_info() { + , epoch1() { } #ifndef TSAN_GO @@ -75,8 +74,8 @@ void ThreadContext::OnCreated(void *arg) { void ThreadContext::OnReset() { sync.Reset(); - if (dead_info) - DestroyAndFree(dead_info); + FlushUnneededShadowMemory(GetThreadTrace(tid), TraceSize() * sizeof(Event)); + //!!! FlushUnneededShadowMemory(GetThreadTraceHeader(tid), sizeof(Trace)); } struct OnStartedArgs { @@ -113,8 +112,10 @@ void ThreadContext::OnStarted(void *arg) { thr->clock.acquire(&sync); thr->fast_state.SetHistorySize(flags()->history_size); const uptr trace = (epoch0 / kTracePartSize) % TraceParts(); - thr->trace.headers[trace].epoch0 = epoch0; + Trace *thr_trace = ThreadTrace(thr->tid); + thr_trace->headers[trace].epoch0 = epoch0; StatInc(thr, StatSyncAcquire); + sync.Reset(); DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx " "tls_addr=%zx tls_size=%zx\n", tid, (uptr)epoch0, args->stk_addr, args->stk_size, @@ -132,14 +133,6 @@ void ThreadContext::OnFinished() { thr->clock.release(&sync); StatInc(thr, StatSyncRelease); } - // Save from info about the thread. - dead_info = new(internal_alloc(MBlockDeadInfo, sizeof(ThreadDeadInfo))) - ThreadDeadInfo(); - for (uptr i = 0; i < TraceParts(); i++) { - dead_info->trace.headers[i].epoch0 = thr->trace.headers[i].epoch0; - dead_info->trace.headers[i].stack0.CopyFrom( - thr->trace.headers[i].stack0); - } epoch1 = thr->fast_state.epoch(); #ifndef TSAN_GO -- 2.7.4