From 1b4699359868ef38a938995e42326ac64095820e Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 4 Dec 2012 15:46:05 +0000 Subject: [PATCH] tsan: output thread names llvm-svn: 169279 --- compiler-rt/lib/tsan/lit_tests/thread_name.cc | 34 ++++++++++++++++++++++++++ compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc | 3 ++- compiler-rt/lib/tsan/rtl/tsan_report.cc | 1 + compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 3 ++- compiler-rt/lib/tsan/rtl/tsan_rtl.h | 2 ++ compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 4 +-- compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 20 +++++++++++++++ 7 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 compiler-rt/lib/tsan/lit_tests/thread_name.cc diff --git a/compiler-rt/lib/tsan/lit_tests/thread_name.cc b/compiler-rt/lib/tsan/lit_tests/thread_name.cc new file mode 100644 index 0000000..76ca993 --- /dev/null +++ b/compiler-rt/lib/tsan/lit_tests/thread_name.cc @@ -0,0 +1,34 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s +#include +#include +#include + +extern "C" void AnnotateThreadName(const char *f, int l, const char *name); + +int Global; + +void *Thread1(void *x) { + usleep(100*1000); + AnnotateThreadName(__FILE__, __LINE__, "Thread1"); + Global++; + return NULL; +} + +void *Thread2(void *x) { + AnnotateThreadName(__FILE__, __LINE__, "Thread2"); + Global--; + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: Thread 1 'Thread1' +// CHECK: Thread 2 'Thread2' + diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc index b0b9f60..51ebbf2 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cc @@ -338,7 +338,7 @@ void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) { void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) { SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd); - IgnoreCtl(cur_thread(), true, false); + IgnoreCtl(thr, true, false); } void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange( @@ -354,6 +354,7 @@ void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange( void INTERFACE_ATTRIBUTE AnnotateThreadName( char *f, int l, char *name) { SCOPED_ANNOTATION(AnnotateThreadName); + ThreadSetName(thr, name); } void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc index 67ae5a9..3324320 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc @@ -26,6 +26,7 @@ ReportDesc::ReportDesc() } ReportDesc::~ReportDesc() { + // FIXME(dvyukov): it must be leaking a lot of memory. } #ifndef TSAN_GO diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 9045588..17e7bd5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -84,7 +84,8 @@ ThreadContext::ThreadContext(int tid) , epoch0() , epoch1() , dead_info() - , dead_next() { + , dead_next() + , name() { } static void WriteMemoryProfile(char *buf, uptr buf_size, int num) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index af8951b..c1b28fc 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -373,6 +373,7 @@ struct ThreadContext { StackTrace creation_stack; ThreadDeadInfo *dead_info; ThreadContext *dead_next; // In dead thread list. + char *name; // As annotated by user. explicit ThreadContext(int tid); }; @@ -529,6 +530,7 @@ int ThreadTid(ThreadState *thr, uptr pc, uptr uid); void ThreadJoin(ThreadState *thr, uptr pc, int tid); void ThreadDetach(ThreadState *thr, uptr pc, int tid); void ThreadFinalize(ThreadState *thr); +void ThreadSetName(ThreadState *thr, const char *name); int ThreadCount(ThreadState *thr); void ProcessPendingSignals(ThreadState *thr); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index dd967b9..488019f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -125,8 +125,7 @@ ScopedReport::ScopedReport(ReportType typ) { ScopedReport::~ScopedReport() { ctx_->report_mtx.Unlock(); - rep_->~ReportDesc(); - internal_free(rep_); + DestroyAndFree(rep_); } void ScopedReport::AddStack(const StackTrace *stack) { @@ -158,6 +157,7 @@ void ScopedReport::AddThread(const ThreadContext *tctx) { rt->id = tctx->tid; rt->pid = tctx->os_id; rt->running = (tctx->status == ThreadStatusRunning); + rt->name = tctx->name ? internal_strdup(tctx->name) : 0; rt->stack = SymbolizeStack(tctx->creation_stack); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index 75568de..7d80066 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -98,6 +98,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { ThreadContext *tctx = 0; if (ctx->dead_list_size > kThreadQuarantineSize || ctx->thread_seq >= kMaxTid) { + // Reusing old thread descriptor and tid. if (ctx->dead_list_size == 0) { Printf("ThreadSanitizer: %d thread limit exceeded. Dying.\n", kMaxTid); @@ -117,7 +118,12 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) { tctx->sync.Reset(); tid = tctx->tid; DestroyAndFree(tctx->dead_info); + if (tctx->name) { + internal_free(tctx->name); + tctx->name = 0; + } } else { + // Allocating new thread descriptor and tid. StatInc(thr, StatThreadMaxTid); tid = ctx->thread_seq++; void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); @@ -324,6 +330,20 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) { } } +void ThreadSetName(ThreadState *thr, const char *name) { + Context *ctx = CTX(); + Lock l(&ctx->thread_mtx); + ThreadContext *tctx = ctx->threads[thr->tid]; + CHECK_NE(tctx, 0); + CHECK_EQ(tctx->status, ThreadStatusRunning); + if (tctx->name) { + internal_free(tctx->name); + tctx->name = 0; + } + if (name) + tctx->name = internal_strdup(name); +} + void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, bool is_write) { if (size == 0) -- 2.7.4