diff options
Diffstat (limited to 'lib/tsan/rtl/tsan_rtl.cc')
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cc | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc index b3320aad8038..b76f3e05dde6 100644 --- a/lib/tsan/rtl/tsan_rtl.cc +++ b/lib/tsan/rtl/tsan_rtl.cc @@ -67,8 +67,17 @@ 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)); - MapThreadTrace(GetThreadTraceHeader(tid), sizeof(Trace)); - new(ThreadTrace(tid)) Trace(); + const uptr hdr = GetThreadTraceHeader(tid); + MapThreadTrace(hdr, sizeof(Trace)); + new((void*)hdr) Trace(); + // We are going to use only a small part of the trace with the default + // value of history_size. However, the constructor writes to the whole trace. + // Unmap the unused part. + uptr hdr_end = hdr + sizeof(Trace); + hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts()); + hdr_end = RoundUp(hdr_end, GetPageSizeCached()); + if (hdr_end < hdr + sizeof(Trace)) + UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end); void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); return new(mem) ThreadContext(tid); } @@ -117,6 +126,7 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch, { } +#ifndef SANITIZER_GO static void MemoryProfiler(Context *ctx, fd_t fd, int i) { uptr n_threads; uptr n_running_threads; @@ -127,13 +137,11 @@ static void MemoryProfiler(Context *ctx, fd_t fd, int i) { } static void BackgroundThread(void *arg) { -#ifndef SANITIZER_GO // This is a non-initialized non-user thread, nothing to see here. // We don't use ScopedIgnoreInterceptors, because we want ignores to be // enabled even when the thread function exits (e.g. during pthread thread // shutdown code). cur_thread()->ignore_interceptors++; -#endif const u64 kMs2Ns = 1000 * 1000; fd_t mprof_fd = kInvalidFd; @@ -191,7 +199,6 @@ static void BackgroundThread(void *arg) { if (mprof_fd != kInvalidFd) MemoryProfiler(ctx, mprof_fd, i); -#ifndef SANITIZER_GO // Flush symbolizer cache if requested. if (flags()->flush_symbolizer_ms > 0) { u64 last = atomic_load(&ctx->last_symbolize_time_ns, @@ -203,7 +210,6 @@ static void BackgroundThread(void *arg) { atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed); } } -#endif } } @@ -211,13 +217,14 @@ static void StartBackgroundThread() { ctx->background_thread = internal_start_thread(&BackgroundThread, 0); } -#ifndef SANITIZER_GO +#ifndef __mips__ static void StopBackgroundThread() { atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); internal_join_thread(ctx->background_thread); ctx->background_thread = 0; } #endif +#endif void DontNeedShadowFor(uptr addr, uptr size) { uptr shadow_beg = MemToShadow(addr); @@ -282,11 +289,11 @@ static void CheckShadowMapping() { if (p < beg || p >= end) continue; const uptr s = MemToShadow(p); - VPrintf(3, " checking pointer %p -> %p\n", p, s); + const uptr m = (uptr)MemToMeta(p); + VPrintf(3, " checking pointer %p: shadow=%p meta=%p\n", p, s, m); CHECK(IsAppMem(p)); CHECK(IsShadowMem(s)); CHECK_EQ(p & ~(kShadowCell - 1), ShadowToMem(s)); - const uptr m = (uptr)MemToMeta(p); CHECK(IsMetaMem(m)); } } @@ -325,11 +332,14 @@ void Initialize(ThreadState *thr) { #ifndef SANITIZER_GO InitializeLibIgnore(); Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer); -#endif + // On MIPS, TSan initialization is run before + // __pthread_initialize_minimal_internal() is finished, so we can not spawn + // new threads. +#ifndef __mips__ StartBackgroundThread(); -#ifndef SANITIZER_GO SetSandboxingCallback(StopBackgroundThread); #endif +#endif if (common_flags()->detect_deadlocks) ctx->dd = DDetector::Create(flags()); @@ -394,8 +404,11 @@ int Finalize(ThreadState *thr) { failed = OnFinalize(failed); +#if TSAN_COLLECT_STATS StatAggregate(ctx->stat, thr->stat); StatOutput(ctx->stat); +#endif + return failed ? flags()->exitcode : 0; } @@ -419,7 +432,7 @@ void ForkChildAfter(ThreadState *thr, uptr pc) { VPrintf(1, "ThreadSanitizer: forked new process with pid %d," " parent had %d threads\n", (int)internal_getpid(), (int)nthread); if (nthread == 1) { - internal_start_thread(&BackgroundThread, 0); + StartBackgroundThread(); } else { // We've just forked a multi-threaded process. We cannot reasonably function // after that (some mutexes may be locked before fork). So just enable @@ -826,7 +839,7 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size, } } else { // The region is big, reset only beginning and end. - const uptr kPageSize = 4096; + const uptr kPageSize = GetPageSizeCached(); u64 *begin = (u64*)MemToShadow(addr); u64 *end = begin + size / kShadowCell * kShadowCnt; u64 *p = begin; |