diff options
author | Kostya Serebryany <kcc@google.com> | 2012-01-11 02:03:16 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2012-01-11 02:03:16 +0000 |
commit | 332923be323e42ddc6ffd0b34647d139e676552f (patch) | |
tree | 8d3a4fa7bec46f7c3b04754f6ed4fe485bfe5872 | |
parent | 4876b5fccd3fd7fe0c73ed6f648e14d88e718e68 (diff) | |
download | bcm5719-llvm-332923be323e42ddc6ffd0b34647d139e676552f.tar.gz bcm5719-llvm-332923be323e42ddc6ffd0b34647d139e676552f.zip |
[asan] get rid of the scary TSD destructor code. Now, we store the leaky AsanThreadSummary in TSD and never remove it from there.
llvm-svn: 147910
-rw-r--r-- | compiler-rt/lib/asan/asan_interceptors.cc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_mac.cc | 29 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_thread.cc | 4 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_thread_registry.cc | 85 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_thread_registry.h | 1 |
5 files changed, 18 insertions, 103 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index eca06888c6f..27e4ee8ef8e 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -230,8 +230,6 @@ __attribute__((visibility("default"))) int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); - AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); - CHECK(curr_thread || asanThreadRegistry().IsCurrentThreadDying()); int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); AsanThread *t = AsanThread::Create(current_tid, start_routine, arg); asanThreadRegistry().RegisterThread(t, current_tid, &stack); diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 695d957d63e..7efb0efeb2f 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -191,22 +191,8 @@ void asan_dispatch_call_block_and_release(void *block) { block, pthread_self()); } AsanThread *t = asanThreadRegistry().GetCurrent(); - if (t) { - // We've already executed a job on this worker thread. Let's reuse the - // AsanThread object. - if (t != asanThreadRegistry().GetMain()) { - // Flush the statistics and update the current thread's tid. - asanThreadRegistry().UnregisterThread(t); - asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack); - } - // Otherwise the worker is being executed on the main thread -- we are - // draining the dispatch queue. - // TODO(glider): any checks for that? - } else { - // It's incorrect to assert that the current thread is not dying: at least - // the callbacks from dispatch_sync() are sometimes called after the TSD is - // destroyed. - AsanThread *t = AsanThread::Create(context->parent_tid, NULL, NULL); + if (!t) { + t = AsanThread::Create(context->parent_tid, NULL, NULL); asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack); t->Init(); asanThreadRegistry().SetCurrent(t); @@ -229,17 +215,6 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func, (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack); asan_ctxt->block = ctxt; asan_ctxt->func = func; - AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); - if (FLAG_debug) { - // Sometimes at Chromium teardown this assertion is violated: - // -- a task is created via dispatch_async() on the "CFMachPort" - // thread while doing _dispatch_queue_drain(); - // -- a task is created via dispatch_async_f() on the - // "com.apple.root.default-overcommit-priority" thread while doing - // _dispatch_dispose(). - // TODO(glider): find out what's going on. - CHECK(curr_thread || asanThreadRegistry().IsCurrentThreadDying()); - } asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); return asan_ctxt; } diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 459b2ef9c00..c61b2b4bd95 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -15,6 +15,7 @@ #include "asan_interceptors.h" #include "asan_procmaps.h" #include "asan_thread.h" +#include "asan_thread_registry.h" #include "asan_mapping.h" namespace __asan { @@ -83,6 +84,9 @@ void *AsanThread::ThreadStart() { Report("T%d exited\n", tid()); } + asanThreadRegistry().UnregisterThread(this); + this->Destroy(); + return res; } diff --git a/compiler-rt/lib/asan/asan_thread_registry.cc b/compiler-rt/lib/asan/asan_thread_registry.cc index 2d4efa6196f..b341a439e71 100644 --- a/compiler-rt/lib/asan/asan_thread_registry.cc +++ b/compiler-rt/lib/asan/asan_thread_registry.cc @@ -28,49 +28,6 @@ AsanThreadRegistry &asanThreadRegistry() { return asan_thread_registry; } -#ifdef ANDROID -#ifndef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS 4 -#endif -#endif - -// Dark magic below. In order to be able to notice that we're not handling -// some thread creation routines (e.g. on Mac OS) we want to distinguish the -// thread that used to have a corresponding AsanThread object from the thread -// that never had one. That's why upon AsanThread destruction we set the -// pthread_key value to some odd number (that's not a valid pointer), instead -// of NULL. -// Because the TSD destructor for a non-NULL key value is called iteratively, -// we increase the value by two, keeping it an invalid pointer. -// Because the TSD implementations are allowed to call such a destructor -// infinitely (see -// http://pubs.opengroup.org/onlinepubs/009604499/functions/pthread_key_create.html -// ), we exit the program after a certain number of iterations. -static void DestroyAsanTsd(void *tsd) { - intptr_t iter = (intptr_t)tsd; - if (iter % 2 == 0) { - // The pointer is valid. - AsanThread *t = (AsanThread*)tsd; - if (t != asanThreadRegistry().GetMain()) { - asanThreadRegistry().UnregisterThread(t); - t->Destroy(); - } - iter = 1; - } else { - // The pointer is invalid -- we've already destroyed the TSD before. - // If |iter| is too big, we're in the infinite loop. This should be - // impossible on the systems AddressSanitizer was tested on. - CHECK(iter < 4 * PTHREAD_DESTRUCTOR_ITERATIONS); - iter += 2; - } - CHECK(0 == pthread_setspecific(asanThreadRegistry().GetTlsKey(), - (void*)iter)); - if (FLAG_v >= 2) { - Report("DestroyAsanTsd: writing %p to the TSD slot of thread %p\n", - (void*)iter, pthread_self()); - } -} - AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x) : main_thread_(x), main_thread_summary_(x), @@ -78,11 +35,11 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x) mu_(x) { } void AsanThreadRegistry::Init() { - CHECK(0 == pthread_key_create(&tls_key_, DestroyAsanTsd)); + CHECK(0 == pthread_key_create(&tls_key_, 0)); tls_key_created_ = true; - SetCurrent(&main_thread_); main_thread_.set_summary(&main_thread_summary_); main_thread_summary_.set_thread(&main_thread_); + SetCurrent(&main_thread_); thread_summaries_[0] = &main_thread_summary_; n_threads_ = 1; } @@ -114,46 +71,28 @@ AsanThread *AsanThreadRegistry::GetMain() { AsanThread *AsanThreadRegistry::GetCurrent() { CHECK(tls_key_created_); - AsanThread *thread = (AsanThread*)pthread_getspecific(tls_key_); - if ((!thread || (intptr_t)thread % 2) && FLAG_v >= 2) { - Report("GetCurrent: %p for thread %p\n", thread, pthread_self()); - } - if ((intptr_t)thread % 2) { - // Invalid pointer -- we've deleted the AsanThread already. Return NULL as - // if the TSD was empty. - // TODO(glider): if the code in the client TSD destructor calls - // pthread_create(), we'll set the parent tid of the spawned thread to NULL, - // although the creation stack will belong to the current thread. This may - // confuse the user, but is quite unlikely. - return NULL; - } else { - // NULL or valid pointer to AsanThread. - return thread; - } + AsanThreadSummary *summary = + (AsanThreadSummary *)pthread_getspecific(tls_key_); + if (!summary) return 0; + return summary->thread(); } void AsanThreadRegistry::SetCurrent(AsanThread *t) { - if (FLAG_v >=2) { - Report("SetCurrent: %p for thread %p\n", t, pthread_self()); + CHECK(t->summary()); + if (FLAG_v >= 2) { + Report("SetCurrent: %p for thread %p\n", t->summary(), pthread_self()); } // Make sure we do not reset the current AsanThread. intptr_t old_key = (intptr_t)pthread_getspecific(tls_key_); - CHECK(!old_key || old_key % 2); - CHECK(0 == pthread_setspecific(tls_key_, t)); - CHECK(pthread_getspecific(tls_key_) == t); + CHECK(!old_key); + CHECK(0 == pthread_setspecific(tls_key_, t->summary())); + CHECK(pthread_getspecific(tls_key_) == t->summary()); } pthread_key_t AsanThreadRegistry::GetTlsKey() { return tls_key_; } -// Returns true iff DestroyAsanTsd() was already called for this thread. -bool AsanThreadRegistry::IsCurrentThreadDying() { - CHECK(tls_key_created_); - intptr_t thread = (intptr_t)pthread_getspecific(tls_key_); - return (bool)(thread % 2); -} - AsanStats &AsanThreadRegistry::GetCurrentThreadStats() { AsanThread *t = GetCurrent(); return (t) ? t->stats() : main_thread_.stats(); diff --git a/compiler-rt/lib/asan/asan_thread_registry.h b/compiler-rt/lib/asan/asan_thread_registry.h index b80dd4da4df..0e8e924e3a4 100644 --- a/compiler-rt/lib/asan/asan_thread_registry.h +++ b/compiler-rt/lib/asan/asan_thread_registry.h @@ -39,7 +39,6 @@ class AsanThreadRegistry { AsanThread *GetCurrent(); void SetCurrent(AsanThread *t); pthread_key_t GetTlsKey(); - bool IsCurrentThreadDying(); int GetCurrentTidOrMinusOne() { AsanThread *t = GetCurrent(); |