From 90c9cbfed4e5cad132d2631cb025fbdce2757727 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 5 Oct 2012 15:51:32 +0000 Subject: [PATCH] tsan: cache pc's that cause suppressions (this way we do not need to symbolize the reports) llvm-svn: 165317 --- compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 7 +++-- compiler-rt/lib/tsan/rtl/tsan_mman.cc | 7 +++-- compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 3 +- compiler-rt/lib/tsan/rtl/tsan_rtl.h | 12 ++++++- compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc | 2 +- compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 45 ++++++++++++++++++--------- compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 2 +- compiler-rt/lib/tsan/rtl/tsan_suppressions.cc | 10 +++--- compiler-rt/lib/tsan/rtl/tsan_suppressions.h | 2 +- 9 files changed, 62 insertions(+), 28 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 387cfba..4e09d8e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1324,6 +1324,7 @@ static void process_pending_signals(ThreadState *thr) { SignalContext *sctx = SigCtx(thr); if (sctx == 0 || sctx->pending_signal_count == 0 || thr->in_signal_handler) return; + Context *ctx = CTX(); thr->in_signal_handler = true; sctx->pending_signal_count = 0; // These are too big for stack. @@ -1351,8 +1352,10 @@ static void process_pending_signals(ThreadState *thr) { (uptr)sigactions[sig].sa_handler; stack.Init(&pc, 1); ScopedReport rep(ReportTypeErrnoInSignal); - rep.AddStack(&stack); - OutputReport(rep, rep.GetReport()->stacks[0]); + if (!IsFiredSuppression(ctx, rep, stack)) { + rep.AddStack(&stack); + OutputReport(ctx, rep, rep.GetReport()->stacks[0]); + } } errno = saved_errno; } diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.cc b/compiler-rt/lib/tsan/rtl/tsan_mman.cc index 6b33480..fcc3000 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_mman.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_mman.cc @@ -45,11 +45,14 @@ void AlloctorThreadFinish(ThreadState *thr) { static void SignalUnsafeCall(ThreadState *thr, uptr pc) { if (!thr->in_signal_handler || !flags()->report_signal_unsafe) return; + Context *ctx = CTX(); StackTrace stack; stack.ObtainCurrent(thr, pc); ScopedReport rep(ReportTypeSignalUnsafe); - rep.AddStack(&stack); - OutputReport(rep, rep.GetReport()->stacks[0]); + if (!IsFiredSuppression(ctx, rep, stack)) { + rep.AddStack(&stack); + OutputReport(ctx, rep, rep.GetReport()->stacks[0]); + } } void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 1bbb367..c776193 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -49,7 +49,8 @@ Context::Context() , nmissed_expected() , thread_mtx(MutexTypeThreads, StatMtxThreads) , racy_stacks(MBlockRacyStacks) - , racy_addresses(MBlockRacyAddresses) { + , racy_addresses(MBlockRacyAddresses) + , fired_suppressions(MBlockRacyAddresses) { } // The objects are allocated in TLS, so one may rely on zero-initialization. diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index d2487ef..c4632c7 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -362,6 +362,11 @@ struct RacyAddress { uptr addr_max; }; +struct FiredSuppression { + ReportType type; + uptr pc; +}; + struct Context { Context(); @@ -385,6 +390,7 @@ struct Context { Vector racy_stacks; Vector racy_addresses; + Vector fired_suppressions; Flags flags; @@ -439,8 +445,12 @@ void InitializeInterceptors(); void InitializeDynamicAnnotations(); void ReportRace(ThreadState *thr); -bool OutputReport(const ScopedReport &srep, +bool OutputReport(Context *ctx, + const ScopedReport &srep, const ReportStack *suppress_stack = 0); +bool IsFiredSuppression(Context *ctx, + const ScopedReport &srep, + const StackTrace &trace); bool IsExpectedReport(uptr addr, uptr size); #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc index 3175f91..73320a0 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -64,7 +64,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { RestoreStack(last.tid(), last.epoch(), &trace); rep.AddStack(&trace); rep.AddLocation(s->addr, 1); - OutputReport(rep); + OutputReport(ctx, rep); } DestroyAndFree(s); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index d179410..34eb450 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -354,17 +354,36 @@ static void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2], } } -bool OutputReport(const ScopedReport &srep, const ReportStack *suppress_stack) { +bool OutputReport(Context *ctx, + const ScopedReport &srep, + const ReportStack *suppress_stack) { const ReportDesc *rep = srep.GetReport(); - bool suppressed = IsSuppressed(rep->typ, suppress_stack); - suppressed = OnReport(rep, suppressed); - if (suppressed) + const uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack); + if (suppress_pc != 0) { + FiredSuppression supp = {srep.GetReport()->typ, suppress_pc}; + ctx->fired_suppressions.PushBack(supp); + } + if (OnReport(rep, suppress_pc != 0)) return false; PrintReport(rep); CTX()->nreported++; return true; } +bool IsFiredSuppression(Context *ctx, + const ScopedReport &srep, + const StackTrace &trace) { + for (uptr k = 0; k < ctx->fired_suppressions.Size(); k++) { + if (ctx->fired_suppressions[k].type != srep.GetReport()->typ) + continue; + for (uptr j = 0; j < trace.Size(); j++) { + if (trace.Get(j) == ctx->fired_suppressions[k].pc) + return true; + } + } + return false; +} + void ReportRace(ThreadState *thr) { ScopedInRtl in_rtl; @@ -395,15 +414,13 @@ void ReportRace(ThreadState *thr) { ScopedReport rep(freed ? ReportTypeUseAfterFree : ReportTypeRace); const uptr kMop = 2; StackTrace traces[kMop]; - for (uptr i = 0; i < kMop; i++) { - Shadow s(thr->racy_state[i]); - RestoreStack(s.tid(), s.epoch(), &traces[i]); - } - // Failure to restore stack of the current thread - // was observed on free() interceptor called from pthread. - // Just get the current shadow stack instead. - if (traces[0].IsEmpty()) - traces[0].ObtainCurrent(thr, 0); + const uptr toppc = thr->trace.events[thr->fast_state.epoch() % kTraceSize] + & ((1ull << 61) - 1); + traces[0].ObtainCurrent(thr, toppc); + if (IsFiredSuppression(ctx, rep, traces[0])) + return; + Shadow s2(thr->racy_state[1]); + RestoreStack(s2.tid(), s2.epoch(), &traces[1]); if (HandleRacyStacks(thr, traces, addr_min, addr_max)) return; @@ -431,7 +448,7 @@ void ReportRace(ThreadState *thr) { } #endif - if (!OutputReport(rep, rep.GetReport()->mops[0]->stack)) + if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack)) return; AddRacyStacks(thr, traces, addr_min, addr_max); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index ee287cb..c52dd82 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -35,7 +35,7 @@ static void MaybeReportThreadLeak(ThreadContext *tctx) { return; ScopedReport rep(ReportTypeThreadLeak); rep.AddThread(tctx); - OutputReport(rep); + OutputReport(CTX(), rep); } void ThreadFinalize(ThreadState *thr) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc index ef7b691..acb95e5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc @@ -134,9 +134,9 @@ void InitializeSuppressions() { g_suppressions = SuppressionParse(supp); } -bool IsSuppressed(ReportType typ, const ReportStack *stack) { +uptr IsSuppressed(ReportType typ, const ReportStack *stack) { if (g_suppressions == 0 || stack == 0) - return false; + return 0; SuppressionType stype; if (typ == ReportTypeRace) stype = SuppressionRace; @@ -147,17 +147,17 @@ bool IsSuppressed(ReportType typ, const ReportStack *stack) { else if (typ == ReportTypeSignalUnsafe) stype = SuppressionSignal; else - return false; + return 0; for (const ReportStack *frame = stack; frame; frame = frame->next) { for (Suppression *supp = g_suppressions; supp; supp = supp->next) { if (stype == supp->type && (SuppressionMatch(supp->templ, frame->func) || SuppressionMatch(supp->templ, frame->file))) { DPrintf("ThreadSanitizer: matched suppression '%s'\n", supp->templ); - return true; + return frame->pc; } } } - return false; + return 0; } } // namespace __tsan diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h index e576ff4..61a4cca 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h @@ -19,7 +19,7 @@ namespace __tsan { void InitializeSuppressions(); void FinalizeSuppressions(); -bool IsSuppressed(ReportType typ, const ReportStack *stack); +uptr IsSuppressed(ReportType typ, const ReportStack *stack); // Exposed for testing. enum SuppressionType { -- 2.7.4