Index: compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -439,65 +439,61 @@ ExtractTagFromStack(stk, tag); } -static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2], - uptr addr_min, uptr addr_max) { - bool equal_stack = false; - RacyStacks hash; - bool equal_address = false; - RacyAddress ra0 = {addr_min, addr_max}; - { - ReadLock lock(&ctx->racy_mtx); - if (flags()->suppress_equal_stacks) { - hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); - hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); - for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { - if (hash == ctx->racy_stacks[i]) { - VPrintf(2, - "ThreadSanitizer: suppressing report as doubled (stack)\n"); - equal_stack = true; - break; - } - } - } - if (flags()->suppress_equal_addresses) { - for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { - RacyAddress ra2 = ctx->racy_addresses[i]; - uptr maxbeg = max(ra0.addr_min, ra2.addr_min); - uptr minend = min(ra0.addr_max, ra2.addr_max); - if (maxbeg < minend) { - VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n"); - equal_address = true; - break; - } - } +static bool FindRacyStacks(const RacyStacks &hash) { + for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) { + if (hash == ctx->racy_stacks[i]) { + VPrintf(2, "ThreadSanitizer: suppressing report as doubled (stack)\n"); + return true; } } - if (!equal_stack && !equal_address) + return false; +} + +static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) { + if (!flags()->suppress_equal_stacks) return false; - if (!equal_stack) { - Lock lock(&ctx->racy_mtx); - ctx->racy_stacks.PushBack(hash); - } - if (!equal_address) { - Lock lock(&ctx->racy_mtx); - ctx->racy_addresses.PushBack(ra0); + RacyStacks hash; + hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); + hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); + { + ReadLock lock(&ctx->racy_mtx); + if (FindRacyStacks(hash)) + return true; } - return true; + Lock lock(&ctx->racy_mtx); + if (FindRacyStacks(hash)) + return true; + ctx->racy_stacks.PushBack(hash); + return false; } -static void AddRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2], - uptr addr_min, uptr addr_max) { - Lock lock(&ctx->racy_mtx); - if (flags()->suppress_equal_stacks) { - RacyStacks hash; - hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr)); - hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr)); - ctx->racy_stacks.PushBack(hash); +static bool FindRacyAddress(const RacyAddress &ra0) { + for (uptr i = 0; i < ctx->racy_addresses.Size(); i++) { + RacyAddress ra2 = ctx->racy_addresses[i]; + uptr maxbeg = max(ra0.addr_min, ra2.addr_min); + uptr minend = min(ra0.addr_max, ra2.addr_max); + if (maxbeg < minend) { + VPrintf(2, "ThreadSanitizer: suppressing report as doubled (addr)\n"); + return true; + } } - if (flags()->suppress_equal_addresses) { - RacyAddress ra0 = {addr_min, addr_max}; - ctx->racy_addresses.PushBack(ra0); + return false; +} + +static bool HandleRacyAddress(ThreadState *thr, uptr addr_min, uptr addr_max) { + if (!flags()->suppress_equal_addresses) + return false; + RacyAddress ra0 = {addr_min, addr_max}; + { + ReadLock lock(&ctx->racy_mtx); + if (FindRacyAddress(ra0)) + return true; } + Lock lock(&ctx->racy_mtx); + if (FindRacyAddress(ra0)) + return true; + ctx->racy_addresses.PushBack(ra0); + return false; } bool OutputReport(ThreadState *thr, const ScopedReport &srep) { @@ -618,6 +614,8 @@ if (IsExpectedReport(addr_min, addr_max - addr_min)) return; } + if (HandleRacyAddress(thr, addr_min, addr_max)) + return; ReportType typ = ReportTypeRace; if (thr->is_vptr_access && freed) @@ -668,7 +666,7 @@ if (IsFiredSuppression(ctx, typ, traces[1])) return; - if (HandleRacyStacks(thr, traces, addr_min, addr_max)) + if (HandleRacyStacks(thr, traces)) return; // If any of the accesses has a tag, treat this as an "external" race. @@ -711,7 +709,6 @@ if (!OutputReport(thr, rep)) return; - AddRacyStacks(thr, traces, addr_min, addr_max); } void PrintCurrentStack(ThreadState *thr, uptr pc) { Index: compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h =================================================================== --- compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h +++ compiler-rt/lib/tsan/tests/rtl/tsan_test_util.h @@ -97,6 +97,7 @@ void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val, bool expect_race = false); + void Entry(void *pc); void Call(void(*pc)()); void Return(); Index: compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cpp =================================================================== --- compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cpp +++ compiler-rt/lib/tsan/tests/rtl/tsan_test_util_posix.cpp @@ -27,6 +27,8 @@ #include #include +#define CALLERPC (__builtin_return_address(0)) + using namespace __tsan; static __thread bool expect_report; @@ -327,7 +329,7 @@ } void *ScopedThread::Impl::ScopedThreadCallback(void *arg) { - __tsan_func_entry(__builtin_return_address(0)); + __tsan_func_entry(CALLERPC); Impl *impl = (Impl*)arg; for (;;) { Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire); @@ -392,10 +394,12 @@ void ScopedThread::Access(void *addr, bool is_write, int size, bool expect_race) { + Entry(CALLERPC); Event event(is_write ? Event::WRITE : Event::READ, addr, size); if (expect_race) event.ExpectReport(ReportTypeRace); impl_->send(&event); + Return(); } void ScopedThread::VptrUpdate(const MemLoc &vptr, @@ -407,6 +411,11 @@ impl_->send(&event); } +void ScopedThread::Entry(void *pc) { + Event event(Event::CALL, (void *)((uintptr_t)pc)); + impl_->send(&event); +} + void ScopedThread::Call(void(*pc)()) { Event event(Event::CALL, (void*)((uintptr_t)pc)); impl_->send(&event);