Index: lib/tsan/rtl/tsan_rtl.h
===================================================================
--- lib/tsan/rtl/tsan_rtl.h
+++ lib/tsan/rtl/tsan_rtl.h
@@ -839,7 +839,8 @@
 
 extern "C" void __tsan_trace_switch();
 void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
-                                        EventType typ, u64 addr) {
+                                        EventType typ, u64 addr,
+                                        bool hacky_call = true) {
   if (!kCollectHistory)
     return;
   DCHECK_GE((int)typ, 0);
@@ -849,10 +850,12 @@
   u64 pos = fs.GetTracePos();
   if (UNLIKELY((pos % kTracePartSize) == 0)) {
 #if !SANITIZER_GO
-    HACKY_CALL(__tsan_trace_switch);
-#else
-    TraceSwitch(thr);
+    if (hacky_call) {
+      DCHECK_EQ(thr, cur_thread());
+      HACKY_CALL(__tsan_trace_switch);
+    } else
 #endif
+      TraceSwitch(thr);
   }
   Event *trace = (Event*)GetThreadTrace(fs.tid());
   Event *evp = &trace[pos];
Index: lib/tsan/rtl/tsan_rtl.cc
===================================================================
--- lib/tsan/rtl/tsan_rtl.cc
+++ lib/tsan/rtl/tsan_rtl.cc
@@ -619,6 +619,7 @@
   thr->racy_state[1] = old.raw();
   thr->racy_shadow_addr = shadow_mem;
 #if !SANITIZER_GO
+  DCHECK_EQ(thr, cur_thread());
   HACKY_CALL(__tsan_report_race);
 #else
   ReportRace(thr);
Index: lib/tsan/rtl/tsan_rtl_thread.cc
===================================================================
--- lib/tsan/rtl/tsan_rtl_thread.cc
+++ lib/tsan/rtl/tsan_rtl_thread.cc
@@ -59,7 +59,7 @@
     return;
   args->thr->fast_state.IncrementEpoch();
   // Can't increment epoch w/o writing to the trace as well.
-  TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
+  TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0, false);
   ReleaseImpl(args->thr, 0, &sync);
   creation_stack_id = CurrentStackId(args->thr, args->pc);
   if (reuse_count == 0)
@@ -112,7 +112,7 @@
   thr->fast_state.SetHistorySize(flags()->history_size);
   // Commit switch to the new part of the trace.
   // TraceAddEvent will reset stack0/mset0 in the new part for us.
-  TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+  TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0, false);
 
   thr->fast_synch_epoch = epoch0;
   AcquireImpl(thr, 0, &sync);
@@ -135,7 +135,7 @@
   if (!detached) {
     thr->fast_state.IncrementEpoch();
     // Can't increment epoch w/o writing to the trace as well.
-    TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+    TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0, false);
     ReleaseImpl(thr, 0, &sync);
   }
   epoch1 = thr->fast_state.epoch();
@@ -246,7 +246,8 @@
   uptr tls_addr = 0;
   uptr tls_size = 0;
 #if !SANITIZER_GO
-  GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
+  if (os_id)
+    GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
 
   if (tid) {
     if (stk_addr && stk_size)