[compiler-rt] r177634 - [ASan] Switch ASan to generic ThreadRegistry from sanitizer_common. Delete ASan-specific AsanThreadRegistry.

Alexey Samsonov samsonov at google.com
Thu Mar 21 04:23:41 PDT 2013


Author: samsonov
Date: Thu Mar 21 06:23:41 2013
New Revision: 177634

URL: http://llvm.org/viewvc/llvm-project?rev=177634&view=rev
Log:
[ASan] Switch ASan to generic ThreadRegistry from sanitizer_common. Delete ASan-specific AsanThreadRegistry.

Removed:
    compiler-rt/trunk/lib/asan/asan_thread_registry.cc
    compiler-rt/trunk/lib/asan/asan_thread_registry.h
Modified:
    compiler-rt/trunk/lib/asan/CMakeLists.txt
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/asan_fake_stack.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_linux.cc
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
    compiler-rt/trunk/lib/asan/asan_posix.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/asan_stats.cc
    compiler-rt/trunk/lib/asan/asan_stats.h
    compiler-rt/trunk/lib/asan/asan_thread.cc
    compiler-rt/trunk/lib/asan/asan_thread.h

Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Thu Mar 21 06:23:41 2013
@@ -20,7 +20,6 @@ set(ASAN_SOURCES
   asan_stack.cc
   asan_stats.cc
   asan_thread.cc
-  asan_thread_registry.cc
   asan_win.cc
   )
 

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Thu Mar 21 06:23:41 2013
@@ -33,7 +33,6 @@
 #include "asan_stats.h"
 #include "asan_report.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_mutex.h"

Modified: compiler-rt/trunk/lib/asan/asan_allocator2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator2.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Thu Mar 21 06:23:41 2013
@@ -21,7 +21,6 @@
 #include "asan_mapping.h"
 #include "asan_report.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_allocator.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "sanitizer_common/sanitizer_list.h"

Modified: compiler-rt/trunk/lib/asan/asan_fake_stack.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_fake_stack.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_fake_stack.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_fake_stack.cc Thu Mar 21 06:23:41 2013
@@ -13,7 +13,6 @@
 //===----------------------------------------------------------------------===//
 #include "asan_allocator.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 
 namespace __asan {
 

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Thu Mar 21 06:23:41 2013
@@ -20,7 +20,6 @@
 #include "asan_report.h"
 #include "asan_stack.h"
 #include "asan_stats.h"
-#include "asan_thread_registry.h"
 #include "interception/interception.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
@@ -91,7 +90,7 @@ static inline uptr MaybeRealStrnlen(cons
 void SetThreadName(const char *name) {
   AsanThread *t = GetCurrentThread();
   if (t)
-    t->summary()->set_name(name);
+    asanThreadRegistry().SetThreadName(t->tid(), name);
 }
 
 }  // namespace __asan
@@ -116,16 +115,23 @@ using namespace __asan;  // NOLINT
 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
   AsanThread *t = (AsanThread*)arg;
   SetCurrentThread(t);
-  return t->ThreadStart();
+  return t->ThreadStart(GetTid());
 }
 
 #if ASAN_INTERCEPT_PTHREAD_CREATE
+extern "C" int pthread_attr_getdetachstate(void *attr, int *v);
+
 INTERCEPTOR(int, pthread_create, void *thread,
     void *attr, void *(*start_routine)(void*), void *arg) {
   GET_STACK_TRACE_THREAD;
+  int detached = 0;
+  if (attr != 0)
+    pthread_attr_getdetachstate(attr, &detached);
+
   u32 current_tid = GetCurrentTidOrInvalid();
-  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
-  asanThreadRegistry().RegisterThread(t);
+  AsanThread *t = AsanThread::Create(start_routine, arg);
+  CreateThreadContextArgs args = { t, &stack };
+  asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
   return REAL(pthread_create)(thread, attr, asan_thread_start, t);
 }
 #endif  // ASAN_INTERCEPT_PTHREAD_CREATE

Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Thu Mar 21 06:23:41 2013
@@ -18,7 +18,6 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Thu Mar 21 06:23:41 2013
@@ -21,7 +21,6 @@
 #include "asan_mapping.h"
 #include "asan_stack.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_libc.h"
 
 #include <crt_externs.h>  // for _NSGetArgv
@@ -293,9 +292,11 @@ static ALWAYS_INLINE
 void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
   AsanThread *t = GetCurrentThread();
   if (!t) {
-    t = AsanThread::Create(parent_tid, 0, 0, stack);
-    asanThreadRegistry().RegisterThread(t);
+    t = AsanThread::Create(0, 0);
+    CreateThreadContextArgs args = { t, stack };
+    asanThreadRegistry().CreateThread(*(uptr*)t, true, parent_tid, &args);
     t->Init();
+    asanThreadRegistry().StartThread(t->tid(), 0, 0);
     SetCurrentThread(t);
   }
 }

Modified: compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_linux.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_linux.cc Thu Mar 21 06:23:41 2013
@@ -21,7 +21,6 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_stack.h"
-#include "asan_thread_registry.h"
 
 #if SANITIZER_ANDROID
 DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)

Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Thu Mar 21 06:23:41 2013
@@ -27,7 +27,6 @@
 #include "asan_report.h"
 #include "asan_stack.h"
 #include "asan_stats.h"
-#include "asan_thread_registry.h"
 
 // Similar code is used in Google Perftools,
 // http://code.google.com/p/google-perftools.

Modified: compiler-rt/trunk/lib/asan/asan_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_posix.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_posix.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_posix.cc Thu Mar 21 06:23:41 2013
@@ -20,7 +20,6 @@
 #include "asan_mapping.h"
 #include "asan_report.h"
 #include "asan_stack.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "sanitizer_common/sanitizer_procmaps.h"
 

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Thu Mar 21 06:23:41 2013
@@ -17,7 +17,6 @@
 #include "asan_report.h"
 #include "asan_stack.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_report_decorator.h"
 #include "sanitizer_common/sanitizer_symbolizer.h"
@@ -237,7 +236,7 @@ bool DescribeAddressIfShadow(uptr addr)
 }
 
 bool DescribeAddressIfStack(uptr addr, uptr access_size) {
-  AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
+  AsanThread *t = FindThreadByStackAddress(addr);
   if (!t) return false;
   const sptr kBufSize = 4095;
   char buf[kBufSize];
@@ -286,7 +285,7 @@ bool DescribeAddressIfStack(uptr addr, u
   Printf("HINT: this may be a false positive if your program uses "
              "some custom stack unwind mechanism or swapcontext\n"
              "      (longjmp and C++ exceptions *are* supported)\n");
-  DescribeThread(t->summary());
+  DescribeThread(t->context());
   return true;
 }
 
@@ -315,10 +314,10 @@ static void DescribeAccessToHeapChunk(As
 }
 
 // Return " (thread_name) " or an empty string if the name is empty.
-const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
+const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
                                       uptr buff_len) {
-  const char *name = t->name();
-  if (*name == 0) return "";
+  const char *name = t->name;
+  if (name[0] == '\0') return "";
   buff[0] = 0;
   internal_strncat(buff, " (", 3);
   internal_strncat(buff, name, buff_len - 4);
@@ -329,7 +328,8 @@ const char *ThreadNameWithParenthesis(As
 const char *ThreadNameWithParenthesis(u32 tid, char buff[],
                                       uptr buff_len) {
   if (tid == kInvalidTid) return "";
-  AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid);
+  asanThreadRegistry().CheckLocked();
+  AsanThreadContext *t = GetThreadContextByTidLocked(tid);
   return ThreadNameWithParenthesis(t, buff, buff_len);
 }
 
@@ -338,8 +338,9 @@ void DescribeHeapAddress(uptr addr, uptr
   if (!chunk.IsValid()) return;
   DescribeAccessToHeapChunk(chunk, addr, access_size);
   CHECK(chunk.AllocTid() != kInvalidTid);
-  AsanThreadSummary *alloc_thread =
-      asanThreadRegistry().FindByTid(chunk.AllocTid());
+  asanThreadRegistry().CheckLocked();
+  AsanThreadContext *alloc_thread =
+      GetThreadContextByTidLocked(chunk.AllocTid());
   StackTrace alloc_stack;
   chunk.GetAllocStack(&alloc_stack);
   AsanThread *t = GetCurrentThread();
@@ -347,30 +348,30 @@ void DescribeHeapAddress(uptr addr, uptr
   char tname[128];
   Decorator d;
   if (chunk.FreeTid() != kInvalidTid) {
-    AsanThreadSummary *free_thread =
-        asanThreadRegistry().FindByTid(chunk.FreeTid());
+    AsanThreadContext *free_thread =
+        GetThreadContextByTidLocked(chunk.FreeTid());
     Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
-           free_thread->tid(),
+           free_thread->tid,
            ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
            d.EndAllocation());
     StackTrace free_stack;
     chunk.GetFreeStack(&free_stack);
     PrintStack(&free_stack);
     Printf("%spreviously allocated by thread T%d%s here:%s\n",
-           d.Allocation(), alloc_thread->tid(),
+           d.Allocation(), alloc_thread->tid,
            ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
            d.EndAllocation());
     PrintStack(&alloc_stack);
-    DescribeThread(t->summary());
+    DescribeThread(t->context());
     DescribeThread(free_thread);
     DescribeThread(alloc_thread);
   } else {
     Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
-           alloc_thread->tid(),
+           alloc_thread->tid,
            ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
            d.EndAllocation());
     PrintStack(&alloc_stack);
-    DescribeThread(t->summary());
+    DescribeThread(t->context());
     DescribeThread(alloc_thread);
   }
 }
@@ -390,26 +391,27 @@ void DescribeAddress(uptr addr, uptr acc
 
 // ------------------- Thread description -------------------- {{{1
 
-void DescribeThread(AsanThreadSummary *summary) {
-  CHECK(summary);
+void DescribeThread(AsanThreadContext *context) {
+  CHECK(context);
+  asanThreadRegistry().CheckLocked();
   // No need to announce the main thread.
-  if (summary->tid() == 0 || summary->announced()) {
+  if (context->tid == 0 || context->announced) {
     return;
   }
-  summary->set_announced(true);
+  context->announced = true;
   char tname[128];
-  Printf("Thread T%d%s", summary->tid(),
-         ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
+  Printf("Thread T%d%s", context->tid,
+         ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
   Printf(" created by T%d%s here:\n",
-         summary->parent_tid(),
-         ThreadNameWithParenthesis(summary->parent_tid(),
+         context->parent_tid,
+         ThreadNameWithParenthesis(context->parent_tid,
                                    tname, sizeof(tname)));
-  PrintStack(summary->stack());
+  PrintStack(&context->stack);
   // Recursively described parent thread if needed.
   if (flags()->print_full_thread_history) {
-    AsanThreadSummary *parent_summary =
-        asanThreadRegistry().FindByTid(summary->parent_tid());
-    DescribeThread(parent_summary);
+    AsanThreadContext *parent_context =
+        GetThreadContextByTidLocked(context->parent_tid);
+    DescribeThread(parent_context);
   }
 }
 
@@ -440,6 +442,10 @@ class ScopedInErrorReport {
       internal__exit(flags()->exitcode);
     }
     ASAN_ON_ERROR();
+    // Make sure the registry is locked while we're printing an error report.
+    // We can lock the registry only here to avoid self-deadlock in case of
+    // recursive reports.
+    asanThreadRegistry().Lock();
     reporting_thread_tid = GetCurrentTidOrInvalid();
     Printf("===================================================="
            "=============\n");
@@ -456,7 +462,7 @@ class ScopedInErrorReport {
     // Make sure the current thread is announced.
     AsanThread *curr_thread = GetCurrentThread();
     if (curr_thread) {
-      DescribeThread(curr_thread->summary());
+      DescribeThread(curr_thread->context());
     }
     // Print memory stats.
     if (flags()->print_stats)

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Thu Mar 21 06:23:41 2013
@@ -29,7 +29,7 @@ bool DescribeAddressIfStack(uptr addr, u
 // Determines memory type on its own.
 void DescribeAddress(uptr addr, uptr access_size);
 
-void DescribeThread(AsanThreadSummary *summary);
+void DescribeThread(AsanThreadContext *context);
 
 // Different kinds of error reports.
 void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Thu Mar 21 06:23:41 2013
@@ -19,7 +19,6 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
@@ -517,8 +516,15 @@ void __asan_init() {
   asan_inited = 1;
   asan_init_is_running = false;
 
-  asanThreadRegistry().Init();
-  asanThreadRegistry().GetMain()->ThreadStart();
+  // Create main thread.
+  AsanTSDInit(AsanThread::TSDDtor);
+  AsanThread *main_thread = AsanThread::Create(0, 0);
+  CreateThreadContextArgs create_main_args = { main_thread, 0 };
+  u32 main_tid = asanThreadRegistry().CreateThread(
+      0, true, 0, &create_main_args);
+  CHECK_EQ(0, main_tid);
+  SetCurrentThread(main_thread);
+  main_thread->ThreadStart(GetPid());
   force_interface_symbols();  // no-op.
 
   InitializeAllocator();

Modified: compiler-rt/trunk/lib/asan/asan_stats.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stats.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stats.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_stats.cc Thu Mar 21 06:23:41 2013
@@ -14,7 +14,7 @@
 #include "asan_interceptors.h"
 #include "asan_internal.h"
 #include "asan_stats.h"
-#include "asan_thread_registry.h"
+#include "asan_thread.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 #include "sanitizer_common/sanitizer_stackdepot.h"
 
@@ -75,7 +75,7 @@ static AsanStats accumulated_stats(LINKE
 static uptr max_malloced_memory;
 static BlockingMutex acc_stats_lock(LINKER_INITIALIZED);
 
-void FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
+static void FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
   acc_stats_lock.CheckLocked();
   uptr *dst = (uptr*)&accumulated_stats;
   uptr *src = (uptr*)stats;
@@ -86,9 +86,18 @@ void FlushToAccumulatedStatsUnlocked(Asa
   }
 }
 
+static void FlushThreadStats(ThreadContextBase *tctx_base, void *arg) {
+  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
+  if (AsanThread *t = tctx->thread)
+    FlushToAccumulatedStatsUnlocked(&t->stats());
+}
+
 static void UpdateAccumulatedStatsUnlocked() {
   acc_stats_lock.CheckLocked();
-  asanThreadRegistry().FlushAllStats();
+  {
+    ThreadRegistryLock l(&asanThreadRegistry());
+    asanThreadRegistry().RunCallbackForEachThreadLocked(FlushThreadStats, 0);
+  }
   FlushToAccumulatedStatsUnlocked(&unknown_thread_stats);
   // This is not very accurate: we may miss allocation peaks that happen
   // between two updates of accumulated_stats_. For more accurate bookkeeping

Modified: compiler-rt/trunk/lib/asan/asan_stats.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stats.h?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stats.h (original)
+++ compiler-rt/trunk/lib/asan/asan_stats.h Thu Mar 21 06:23:41 2013
@@ -64,8 +64,6 @@ AsanStats &GetCurrentThreadStats();
 void GetAccumulatedStats(AsanStats *stats);
 // Flushes a given stats into accumulated stats.
 void FlushToAccumulatedStats(AsanStats *stats);
-// FIXME: Hide this method when AsanThreadRegistry is removed.
-void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
 
 // A cross-platform equivalent of malloc_statistics_t on Mac OS.
 struct AsanMallocStats {

Modified: compiler-rt/trunk/lib/asan/asan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.cc?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.cc Thu Mar 21 06:23:41 2013
@@ -15,44 +15,77 @@
 #include "asan_interceptors.h"
 #include "asan_stack.h"
 #include "asan_thread.h"
-#include "asan_thread_registry.h"
 #include "asan_mapping.h"
 #include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
 
 namespace __asan {
 
-AsanThread::AsanThread(LinkerInitialized x)
-    : fake_stack_(x),
-      malloc_storage_(x),
-      stats_(x) { }
+// AsanThreadContext implementation.
 
-AsanThread *AsanThread::Create(u32 parent_tid, thread_callback_t start_routine,
-                               void *arg, StackTrace *stack) {
+void AsanThreadContext::OnCreated(void *arg) {
+  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
+  if (args->stack) {
+    internal_memcpy(&stack, args->stack, sizeof(stack));
+  }
+  thread = args->thread;
+  thread->set_context(this);
+}
+
+void AsanThreadContext::OnFinished() {
+  // Drop the link to the AsanThread object.
+  thread = 0;
+}
+
+static char thread_registry_placeholder[sizeof(ThreadRegistry)];
+static ThreadRegistry *asan_thread_registry;
+
+static ThreadContextBase *GetAsanThreadContext(u32 tid) {
+  void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
+  return new(mem) AsanThreadContext(tid);
+}
+
+ThreadRegistry &asanThreadRegistry() {
+  static bool initialized;
+  // Don't worry about thread_safety - this should be called when there is
+  // a single thread.
+  if (!initialized) {
+    // Never reuse ASan threads: we store pointer to AsanThreadContext
+    // in TSD and can't reliably tell when no more TSD destructors will
+    // be called. It would be wrong to reuse AsanThreadContext for another
+    // thread before all TSD destructors will be called for it.
+    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
+        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
+    initialized = true;
+  }
+  return *asan_thread_registry;
+}
+
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
+  return static_cast<AsanThreadContext *>(
+      asanThreadRegistry().GetThreadLocked(tid));
+}
+
+// AsanThread implementation.
+
+AsanThread *AsanThread::Create(thread_callback_t start_routine,
+                               void *arg) {
   uptr PageSize = GetPageSizeCached();
   uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
   AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
   thread->start_routine_ = start_routine;
   thread->arg_ = arg;
-
-  const uptr kSummaryAllocSize = PageSize;
-  CHECK_LE(sizeof(AsanThreadSummary), kSummaryAllocSize);
-  AsanThreadSummary *summary =
-      (AsanThreadSummary*)MmapOrDie(PageSize, "AsanThreadSummary");
-  summary->Init(parent_tid, stack);
-  summary->set_thread(thread);
-  thread->set_summary(summary);
+  thread->context_ = 0;
 
   return thread;
 }
 
-void AsanThreadSummary::TSDDtor(void *tsd) {
-  AsanThreadSummary *summary = (AsanThreadSummary*)tsd;
-  if (flags()->verbosity >= 1) {
-    Report("T%d TSDDtor\n", summary->tid());
-  }
-  if (summary->thread()) {
-    summary->thread()->Destroy();
-  }
+void AsanThread::TSDDtor(void *tsd) {
+  AsanThreadContext *context = (AsanThreadContext*)tsd;
+  if (flags()->verbosity >= 1)
+    Report("T%d TSDDtor\n", context->tid);
+  if (context->thread)
+    context->thread->Destroy();
 }
 
 void AsanThread::Destroy() {
@@ -60,8 +93,8 @@ void AsanThread::Destroy() {
     Report("T%d exited\n", tid());
   }
 
-  asanThreadRegistry().UnregisterThread(this);
-  CHECK(summary()->thread() == 0);
+  asanThreadRegistry().FinishThread(tid());
+  FlushToAccumulatedStats(&stats_);
   // We also clear the shadow on thread destruction because
   // some code may still be executing in later TSD destructors
   // and we don't want it to have any poisoned stack.
@@ -86,8 +119,9 @@ void AsanThread::Init() {
   AsanPlatformThreadInit();
 }
 
-thread_return_t AsanThread::ThreadStart() {
+thread_return_t AsanThread::ThreadStart(uptr os_id) {
   Init();
+  asanThreadRegistry().StartThread(tid(), os_id, 0);
   if (flags()->use_sigaltstack) SetAlternateSignalStack();
 
   if (!start_routine_) {
@@ -152,37 +186,45 @@ const char *AsanThread::GetFrameNameByAd
   return (const char*)ptr[1];
 }
 
+static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
+                                       void *addr) {
+  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
+  AsanThread *t = tctx->thread;
+  return (t && t->fake_stack().StackSize() &&
+          (t->fake_stack().AddrIsInFakeStack((uptr)addr) ||
+           t->AddrIsInStack((uptr)addr)));
+}
+
 AsanThread *GetCurrentThread() {
-  AsanThreadSummary *summary = (AsanThreadSummary *)AsanTSDGet();
-  if (!summary) {
-#if SANITIZER_ANDROID
-    // On Android, libc constructor is called _after_ asan_init, and cleans up
-    // TSD. Try to figure out if this is still the main thread by the stack
-    // address. We are not entirely sure that we have correct main thread
-    // limits, so only do this magic on Android, and only if the found thread is
-    // the main thread.
-    AsanThread *thread =
-        asanThreadRegistry().FindThreadByStackAddress((uptr)&summary);
-    if (thread && thread->tid() == 0) {
-      SetCurrentThread(thread);
-      return thread;
+  AsanThreadContext *context = (AsanThreadContext*)AsanTSDGet();
+  if (!context) {
+    if (SANITIZER_ANDROID) {
+      // On Android, libc constructor is called _after_ asan_init, and cleans up
+      // TSD. Try to figure out if this is still the main thread by the stack
+      // address. We are not entirely sure that we have correct main thread
+      // limits, so only do this magic on Android, and only if the found thread is
+      // the main thread.
+      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
+      if (ThreadStackContainsAddress(tctx, &context)) {
+        SetCurrentThread(tctx->thread);
+        return tctx->thread;
+      }
     }
-#endif
     return 0;
   }
-  return summary->thread();
+  return context->thread;
 }
 
 void SetCurrentThread(AsanThread *t) {
-  CHECK(t->summary());
+  CHECK(t->context());
   if (flags()->verbosity >= 2) {
     Report("SetCurrentThread: %p for thread %p\n",
-           t->summary(), (void*)GetThreadSelf());
+           t->context(), (void*)GetThreadSelf());
   }
   // Make sure we do not reset the current AsanThread.
-  CHECK(AsanTSDGet() == 0);
-  AsanTSDSet(t->summary());
-  CHECK(AsanTSDGet() == t->summary());
+  CHECK_EQ(0, AsanTSDGet());
+  AsanTSDSet(t->context());
+  CHECK_EQ(t->context(), AsanTSDGet());
 }
 
 u32 GetCurrentTidOrInvalid() {
@@ -190,4 +232,12 @@ u32 GetCurrentTidOrInvalid() {
   return t ? t->tid() : kInvalidTid;
 }
 
+AsanThread *FindThreadByStackAddress(uptr addr) {
+  asanThreadRegistry().CheckLocked();
+  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
+      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
+                                                   (void *)addr));
+  return tctx ? tctx->thread : 0;
+}
+
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/asan_thread.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.h?rev=177634&r1=177633&r2=177634&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.h (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.h Thu Mar 21 06:23:41 2013
@@ -19,71 +19,52 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 #include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
 
 namespace __asan {
 
 const u32 kInvalidTid = 0xffffff;  // Must fit into 24 bits.
+const u32 kMaxNumberOfThreads = (1 << 22);  // 4M
 
 class AsanThread;
 
 // These objects are created for every thread and are never deleted,
 // so we can find them by tid even if the thread is long dead.
-class AsanThreadSummary {
+class AsanThreadContext : public ThreadContextBase {
  public:
-  explicit AsanThreadSummary(LinkerInitialized) { }  // for T0.
-  void Init(u32 parent_tid, StackTrace *stack) {
-    parent_tid_ = parent_tid;
-    announced_ = false;
-    tid_ = kInvalidTid;
-    if (stack) {
-      internal_memcpy(&stack_, stack, sizeof(*stack));
-    }
-    thread_ = 0;
-    name_[0] = 0;
+  explicit AsanThreadContext(int tid)
+      : ThreadContextBase(tid),
+        announced(false),
+        thread(0) {
+    internal_memset(&stack, 0, sizeof(stack));
   }
-  u32 tid() { return tid_; }
-  void set_tid(u32 tid) { tid_ = tid; }
-  u32 parent_tid() { return parent_tid_; }
-  bool announced() { return announced_; }
-  void set_announced(bool announced) { announced_ = announced; }
-  StackTrace *stack() { return &stack_; }
-  AsanThread *thread() { return thread_; }
-  void set_thread(AsanThread *thread) { thread_ = thread; }
-  static void TSDDtor(void *tsd);
-  void set_name(const char *name) {
-    internal_strncpy(name_, name, sizeof(name_) - 1);
-  }
-  const char *name() { return name_; }
+  bool announced;
+  StackTrace stack;
+  AsanThread *thread;
 
- private:
-  u32 tid_;
-  u32 parent_tid_;
-  bool announced_;
-  StackTrace stack_;
-  AsanThread *thread_;
-  char name_[128];
+  void OnCreated(void *arg);
+  void OnFinished();
 };
 
-// AsanThreadSummary objects are never freed, so we need many of them.
-COMPILER_CHECK(sizeof(AsanThreadSummary) <= 4094);
+// AsanThreadContext objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(AsanThreadContext) <= 4096);
 
 // AsanThread are stored in TSD and destroyed when the thread dies.
 class AsanThread {
  public:
-  explicit AsanThread(LinkerInitialized);  // for T0.
-  static AsanThread *Create(u32 parent_tid, thread_callback_t start_routine,
-                            void *arg, StackTrace *stack);
+  static AsanThread *Create(thread_callback_t start_routine, void *arg);
+  static void TSDDtor(void *tsd);
   void Destroy();
 
   void Init();  // Should be called from the thread itself.
-  thread_return_t ThreadStart();
+  thread_return_t ThreadStart(uptr os_id);
 
   uptr stack_top() { return stack_top_; }
   uptr stack_bottom() { return stack_bottom_; }
   uptr stack_size() { return stack_top_ - stack_bottom_; }
-  u32 tid() { return summary_->tid(); }
-  AsanThreadSummary *summary() { return summary_; }
-  void set_summary(AsanThreadSummary *summary) { summary_ = summary; }
+  u32 tid() { return context_->tid; }
+  AsanThreadContext *context() { return context_; }
+  void set_context(AsanThreadContext *context) { context_ = context; }
 
   const char *GetFrameNameByAddr(uptr addr, uptr *offset);
 
@@ -96,9 +77,10 @@ class AsanThread {
   AsanStats &stats() { return stats_; }
 
  private:
+  AsanThread() {}
   void SetThreadStackTopAndBottom();
   void ClearShadowForThreadStack();
-  AsanThreadSummary *summary_;
+  AsanThreadContext *context_;
   thread_callback_t start_routine_;
   void *arg_;
   uptr  stack_top_;
@@ -109,10 +91,22 @@ class AsanThread {
   AsanStats stats_;
 };
 
+struct CreateThreadContextArgs {
+  AsanThread *thread;
+  StackTrace *stack;
+};
+
+// Returns a single instance of registry.
+ThreadRegistry &asanThreadRegistry();
+
+// Must be called under ThreadRegistryLock.
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
+
 // Get the current thread. May return 0.
 AsanThread *GetCurrentThread();
 void SetCurrentThread(AsanThread *t);
 u32 GetCurrentTidOrInvalid();
+AsanThread *FindThreadByStackAddress(uptr addr);
 
 }  // namespace __asan
 

Removed: compiler-rt/trunk/lib/asan/asan_thread_registry.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread_registry.cc?rev=177633&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread_registry.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread_registry.cc (removed)
@@ -1,96 +0,0 @@
-//===-- asan_thread_registry.cc -------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// AsanThreadRegistry-related code. AsanThreadRegistry is a container
-// for summaries of all created threads.
-//===----------------------------------------------------------------------===//
-
-#include "asan_stack.h"
-#include "asan_thread.h"
-#include "asan_thread_registry.h"
-#include "sanitizer_common/sanitizer_common.h"
-
-namespace __asan {
-
-static AsanThreadRegistry asan_thread_registry(LINKER_INITIALIZED);
-
-AsanThreadRegistry &asanThreadRegistry() {
-  return asan_thread_registry;
-}
-
-AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
-    : main_thread_(x),
-      main_thread_summary_(x),
-      mu_(x) { }
-
-void AsanThreadRegistry::Init() {
-  AsanTSDInit(AsanThreadSummary::TSDDtor);
-  main_thread_.set_summary(&main_thread_summary_);
-  main_thread_summary_.set_thread(&main_thread_);
-  RegisterThread(&main_thread_);
-  SetCurrentThread(&main_thread_);
-  // At this point only one thread exists.
-  inited_ = true;
-}
-
-void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
-  BlockingMutexLock lock(&mu_);
-  u32 tid = n_threads_;
-  n_threads_++;
-  CHECK(n_threads_ < kMaxNumberOfThreads);
-
-  AsanThreadSummary *summary = thread->summary();
-  CHECK(summary != 0);
-  summary->set_tid(tid);
-  thread_summaries_[tid] = summary;
-}
-
-void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
-  BlockingMutexLock lock(&mu_);
-  FlushToAccumulatedStats(&thread->stats());
-  AsanThreadSummary *summary = thread->summary();
-  CHECK(summary);
-  summary->set_thread(0);
-}
-
-AsanThread *AsanThreadRegistry::GetMain() {
-  return &main_thread_;
-}
-
-void AsanThreadRegistry::FlushAllStats() {
-  BlockingMutexLock lock(&mu_);
-  for (u32 tid = 0; tid < n_threads_; tid++) {
-    AsanThread *t = thread_summaries_[tid]->thread();
-    if (t != 0) {
-      FlushToAccumulatedStatsUnlocked(&t->stats());
-    }
-  }
-}
-
-AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
-  CHECK(tid < n_threads_);
-  CHECK(thread_summaries_[tid]);
-  return thread_summaries_[tid];
-}
-
-AsanThread *AsanThreadRegistry::FindThreadByStackAddress(uptr addr) {
-  BlockingMutexLock lock(&mu_);
-  for (u32 tid = 0; tid < n_threads_; tid++) {
-    AsanThread *t = thread_summaries_[tid]->thread();
-    if (!t || !(t->fake_stack().StackSize())) continue;
-    if (t->fake_stack().AddrIsInFakeStack(addr) || t->AddrIsInStack(addr)) {
-      return t;
-    }
-  }
-  return 0;
-}
-
-}  // namespace __asan

Removed: compiler-rt/trunk/lib/asan/asan_thread_registry.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread_registry.h?rev=177633&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread_registry.h (original)
+++ compiler-rt/trunk/lib/asan/asan_thread_registry.h (removed)
@@ -1,57 +0,0 @@
-//===-- asan_thread_registry.h ----------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// ASan-private header for asan_thread_registry.cc
-//===----------------------------------------------------------------------===//
-
-#ifndef ASAN_THREAD_REGISTRY_H
-#define ASAN_THREAD_REGISTRY_H
-
-#include "asan_stack.h"
-#include "asan_stats.h"
-#include "asan_thread.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-
-namespace __asan {
-
-// Stores summaries of all created threads, returns current thread,
-// thread by tid, thread by stack address. There is a single instance
-// of AsanThreadRegistry for the whole program.
-// AsanThreadRegistry is thread-safe.
-class AsanThreadRegistry {
- public:
-  explicit AsanThreadRegistry(LinkerInitialized);
-  void Init();
-  void RegisterThread(AsanThread *thread);
-  void UnregisterThread(AsanThread *thread);
-
-  AsanThread *GetMain();
-  void FlushAllStats();
-
-  AsanThreadSummary *FindByTid(u32 tid);
-  AsanThread *FindThreadByStackAddress(uptr addr);
-
- private:
-  static const u32 kMaxNumberOfThreads = (1 << 22);  // 4M
-  AsanThreadSummary *thread_summaries_[kMaxNumberOfThreads];
-  AsanThread main_thread_;
-  AsanThreadSummary main_thread_summary_;
-  u32 n_threads_;
-  BlockingMutex mu_;
-  bool inited_;
-};
-
-// Returns a single instance of registry.
-AsanThreadRegistry &asanThreadRegistry();
-
-}  // namespace __asan
-
-#endif  // ASAN_THREAD_REGISTRY_H





More information about the llvm-commits mailing list