diff options
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_clock.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_defs.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 22 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc | 40 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 8 | 
6 files changed, 63 insertions, 13 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_clock.cc b/compiler-rt/lib/tsan/rtl/tsan_clock.cc index 59e3de435f1..1e2050d1f20 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_clock.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_clock.cc @@ -90,8 +90,6 @@  namespace __tsan { -const unsigned kInvalidTid = (unsigned)-1; -  ThreadClock::ThreadClock(unsigned tid, unsigned reused)      : tid_(tid)      , reused_(reused + 1) {  // 0 has special meaning diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h index d869d95e087..385e366c39b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -83,6 +83,8 @@ const bool kCollectHistory = false;  const bool kCollectHistory = true;  #endif +const unsigned kInvalidTid = (unsigned)-1; +  // The following "build consistency" machinery ensures that all source files  // are built in the same configuration. Inconsistent builds lead to  // hard to debug crashes. diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index c9dc34934f6..0d9bba5b2fd 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -812,6 +812,18 @@ extern "C" void INTERFACE_ATTRIBUTE __cxa_guard_abort(atomic_uint32_t *g) {    atomic_store(g, 0, memory_order_relaxed);  } +namespace __tsan { +void DestroyThreadState() { +  ThreadState *thr = cur_thread(); +  ThreadFinish(thr); +  ThreadSignalContext *sctx = thr->signal_ctx; +  if (sctx) { +    thr->signal_ctx = 0; +    UnmapOrDie(sctx, sizeof(*sctx)); +  } +} +}  // namespace __tsan +  static void thread_finalize(void *v) {    uptr iter = (uptr)v;    if (iter > 1) { @@ -821,15 +833,7 @@ static void thread_finalize(void *v) {      }      return;    } -  { -    ThreadState *thr = cur_thread(); -    ThreadFinish(thr); -    ThreadSignalContext *sctx = thr->signal_ctx; -    if (sctx) { -      thr->signal_ctx = 0; -      UnmapOrDie(sctx, sizeof(*sctx)); -    } -  } +  DestroyThreadState();  } diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 87169fc089e..57cd86d8304 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -355,6 +355,8 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,      void *abstime), void *c, void *m, void *abstime,      void(*cleanup)(void *arg), void *arg); +void DestroyThreadState(); +  }  // namespace __tsan  #endif  // TSAN_PLATFORM_H diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc index 550f9705edd..4677adda32e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc @@ -54,11 +54,51 @@ void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive) {  void InitializeShadowMemoryPlatform() { }  #endif +// On OS X, GCD worker threads are created without a call to pthread_create. We +// need to properly register these threads with ThreadCreate and ThreadStart. +// These threads don't have a parent thread, as they are created "spuriously". +// We're using a libpthread API that notifies us about a newly created thread. +// The `thread == pthread_self()` check indicates this is actually a worker +// thread. If it's just a regular thread, this hook is called on the parent +// thread. +typedef void (*pthread_introspection_hook_t)(unsigned int event, +                                             pthread_t thread, void *addr, +                                             size_t size); +extern "C" pthread_introspection_hook_t pthread_introspection_hook_install( +    pthread_introspection_hook_t hook); +static const uptr PTHREAD_INTROSPECTION_THREAD_CREATE = 1; +static const uptr PTHREAD_INTROSPECTION_THREAD_DESTROY = 4; +static pthread_introspection_hook_t prev_pthread_introspection_hook; +static void my_pthread_introspection_hook(unsigned int event, pthread_t thread, +                                          void *addr, size_t size) { +  if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) { +    if (thread == pthread_self()) { +      // The current thread is a newly created GCD worker thread. +      ThreadState *parent_thread_state = nullptr;  // No parent. +      int tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true); +      CHECK_NE(tid, 0); +      ThreadState *thr = cur_thread(); +      ThreadStart(thr, tid, GetTid()); +    } +  } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) { +    ThreadState *thr = cur_thread(); +    if (thr->tctx->parent_tid == kInvalidTid) { +      DestroyThreadState(); +    } +  } + +  if (prev_pthread_introspection_hook != nullptr) +    prev_pthread_introspection_hook(event, thread, addr, size); +} +  void InitializePlatform() {    DisableCoreDumperIfNecessary();  #ifndef SANITIZER_GO    CheckAndProtect();  #endif + +  prev_pthread_introspection_hook = +      pthread_introspection_hook_install(&my_pthread_introspection_hook);  }  #ifndef SANITIZER_GO diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index 66c78cfdd7c..dcae255f764 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -55,6 +55,8 @@ void ThreadContext::OnCreated(void *arg) {    if (tid == 0)      return;    OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg); +  if (!args->thr)  // GCD workers don't have a parent thread. +    return;    args->thr->fast_state.IncrementEpoch();    // Can't increment epoch w/o writing to the trace as well.    TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0); @@ -231,8 +233,10 @@ int ThreadCount(ThreadState *thr) {  int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {    StatInc(thr, StatThreadCreate);    OnCreatedArgs args = { thr, pc }; -  int tid = ctx->thread_registry->CreateThread(uid, detached, thr->tid, &args); -  DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid); +  u32 parent_tid = thr ? thr->tid : kInvalidTid;  // No parent for GCD workers. +  int tid = +      ctx->thread_registry->CreateThread(uid, detached, parent_tid, &args); +  DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent_tid, tid, uid);    StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads());    return tid;  }  | 

