tsan: move trace header into 0x600000000000 range
authorDmitry Vyukov <dvyukov@google.com>
Wed, 20 Mar 2013 10:31:53 +0000 (10:31 +0000)
committerDmitry Vyukov <dvyukov@google.com>
Wed, 20 Mar 2013 10:31:53 +0000 (10:31 +0000)
eliminat thread "dead info" altogether

llvm-svn: 177512

compiler-rt/lib/tsan/rtl/tsan_platform.h
compiler-rt/lib/tsan/rtl/tsan_rtl.cc
compiler-rt/lib/tsan/rtl/tsan_rtl.h
compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc

index 2a07599..15b4d10 100644 (file)
@@ -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;
 }
index 37f65eb..6efb287 100644 (file)
@@ -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"
index 19929de..2b9aaf4 100644 (file)
@@ -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,
index 2df4234..b343ff3 100644 (file)
@@ -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];
index 476b670..3be9b83 100644 (file)
@@ -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