diff options
Diffstat (limited to 'compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc')
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index e93a7a34ee4..35e97873a3b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -143,26 +143,44 @@ void ThreadContext::OnFinished() { thr = 0; } -static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *unused) { +#ifndef TSAN_GO +struct ThreadLeak { + ThreadContext *tctx; + int count; +}; + +static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) { + Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg; ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base); - if (tctx->detached) + if (tctx->detached || tctx->status != ThreadStatusFinished) return; - if (tctx->status != ThreadStatusCreated - && tctx->status != ThreadStatusRunning - && tctx->status != ThreadStatusFinished) - return; - ScopedReport rep(ReportTypeThreadLeak); - rep.AddThread(tctx); - OutputReport(CTX(), rep); + for (uptr i = 0; i < leaks.Size(); i++) { + if (leaks[i].tctx->creation_stack_id == tctx->creation_stack_id) { + leaks[i].count++; + return; + } + } + ThreadLeak leak = {tctx, 1}; + leaks.PushBack(leak); } +#endif void ThreadFinalize(ThreadState *thr) { CHECK_GT(thr->in_rtl, 0); +#ifndef TSAN_GO if (!flags()->report_thread_leaks) return; ThreadRegistryLock l(CTX()->thread_registry); + Vector<ThreadLeak> leaks(MBlockScopedBuf); CTX()->thread_registry->RunCallbackForEachThreadLocked( - MaybeReportThreadLeak, 0); + MaybeReportThreadLeak, &leaks); + for (uptr i = 0; i < leaks.Size(); i++) { + ScopedReport rep(ReportTypeThreadLeak); + rep.AddThread(leaks[i].tctx); + rep.SetCount(leaks[i].count); + OutputReport(CTX(), rep); + } +#endif } int ThreadCount(ThreadState *thr) { |