Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -187,7 +187,7 @@ uptr registers_begin = reinterpret_cast(registers.data()); uptr registers_end = registers_begin + registers.size(); for (uptr i = 0; i < suspended_threads.thread_count(); i++) { - uptr os_id = static_cast(suspended_threads.GetThreadID(i)); + uptr os_id = static_cast(suspended_threads.GetThread(i).tid); LOG_THREADS("Processing thread %d.\n", os_id); uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end; DTLS *dtls; Index: lib/sanitizer_common/sanitizer_stoptheworld.h =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld.h +++ lib/sanitizer_common/sanitizer_stoptheworld.h @@ -17,36 +17,53 @@ #include "sanitizer_internal_defs.h" #include "sanitizer_common.h" +#if SANITIZER_MAC +#include +#endif + namespace __sanitizer { -typedef int SuspendedThreadID; +// On Darwin, we need both the thread_t and the tid, but +// converting between the two requires an expensive syscall, +// so we store both in the struct. On Linux, contains the tid. +typedef struct { +#if SANITIZER_LINUX + pid_t tid; +#elif SANITIZER_MAC + uptr tid; + thread_t thread; +#endif +} SuspendedThreadInfo; // Holds the list of suspended threads and provides an interface to dump their // register contexts. class SuspendedThreadsList { public: SuspendedThreadsList() - : thread_ids_(1024) {} - SuspendedThreadID GetThreadID(uptr index) const { - CHECK_LT(index, thread_ids_.size()); - return thread_ids_[index]; + : threads_(1024) {} + + SuspendedThreadInfo GetThread(uptr index) const { + CHECK_LT(index, threads_.size()); + return threads_[index]; } + int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const; // The buffer in GetRegistersAndSP should be at least this big. static uptr RegisterCount(); - uptr thread_count() const { return thread_ids_.size(); } - bool Contains(SuspendedThreadID thread_id) const { - for (uptr i = 0; i < thread_ids_.size(); i++) { - if (thread_ids_[i] == thread_id) + uptr thread_count() const { return threads_.size(); } + bool Contains(SuspendedThreadInfo const &info) const { + for (uptr i = 0; i < threads_.size(); i++) { + if (threads_[i].tid == info.tid) return true; } return false; } - void Append(SuspendedThreadID thread_id) { - thread_ids_.push_back(thread_id); + + void Append(SuspendedThreadInfo const &info) { + threads_.push_back(info); } private: - InternalMmapVector thread_ids_; + InternalMmapVector threads_; // Prohibit copy and assign. SuspendedThreadsList(const SuspendedThreadsList&); Index: lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -81,8 +81,6 @@ namespace __sanitizer { -COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t)); - // Structure for passing arguments into the tracer thread. struct TracerThreadArgument { StopTheWorldCallback callback; @@ -113,14 +111,15 @@ private: SuspendedThreadsList suspended_threads_list_; pid_t pid_; - bool SuspendThread(SuspendedThreadID thread_id); + bool SuspendThread(pid_t thread_id); }; -bool ThreadSuspender::SuspendThread(SuspendedThreadID tid) { +bool ThreadSuspender::SuspendThread(pid_t tid) { + SuspendedThreadInfo info = {tid}; // Are we already attached to this thread? // Currently this check takes linear time, however the number of threads is // usually small. - if (suspended_threads_list_.Contains(tid)) + if (suspended_threads_list_.Contains(info)) return false; int pterrno; if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr), @@ -160,14 +159,14 @@ } break; } - suspended_threads_list_.Append(tid); + suspended_threads_list_.Append(info); return true; } } void ThreadSuspender::ResumeAllThreads() { for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { - pid_t tid = suspended_threads_list_.GetThreadID(i); + pid_t tid = suspended_threads_list_.GetThread(i).tid; int pterrno; if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, nullptr, nullptr), &pterrno)) { @@ -183,7 +182,7 @@ void ThreadSuspender::KillAllThreads() { for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) - internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i), + internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThread(i).tid, nullptr, nullptr); } @@ -496,7 +495,7 @@ int SuspendedThreadsList::GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const { - pid_t tid = GetThreadID(index); + pid_t tid = GetThread(index).tid; regs_struct regs; int pterrno; #ifdef ARCH_IOVEC_FOR_GETREGSET