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++) { - tid_t os_id = static_cast(suspended_threads.GetThreadID(i)); + tid_t 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 @@ -16,9 +16,11 @@ #include "sanitizer_internal_defs.h" #include "sanitizer_common.h" +#include "sanitizer_stoptheworld_linux.h" +#include "sanitizer_stoptheworld_mac.h" +#include "sanitizer_stoptheworld_win.h" namespace __sanitizer { - enum PtraceRegistersStatus { REGISTERS_UNAVAILABLE_FATAL = -1, REGISTERS_UNAVAILABLE = 0, @@ -30,29 +32,32 @@ class SuspendedThreadsList { public: SuspendedThreadsList() - : thread_ids_(1024) {} - tid_t GetThreadID(uptr index) const { - CHECK_LT(index, thread_ids_.size()); - return thread_ids_[index]; + : threads_(1024) {} + + const SuspendedThreadInfo& GetThread(uptr index) const { + CHECK_LT(index, threads_.size()); + return threads_[index]; } + PtraceRegistersStatus 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(tid_t 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 ContainsTid(tid_t thread_id) const { + for (uptr i = 0; i < threads_.size(); i++) { + if (threads_[i].tid == thread_id) return true; } return false; } - void Append(tid_t 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.h =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_stoptheworld_linux.h @@ -0,0 +1,28 @@ +//===-- sanitizer_stoptheworld_linux.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Linux-specific code for StopTheWorld. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_STOPTHEWORLD_LINUX_H +#define SANITIZER_STOPTHEWORLD_LINUX_H + +#include "sanitizer_platform.h" +#if SANITIZER_LINUX +#include "sanitizer_internal_defs.h" + +namespace __sanitizer { +typedef struct { + tid_t tid; +} SuspendedThreadInfo; +} // namespace __sanitizer + +#endif // SANITIZER_LINUX +#endif // SANITIZER_STOPTHEWORLD_LINUX_H 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 @@ -121,7 +121,7 @@ // 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_.ContainsTid(tid)) return false; int pterrno; if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr), @@ -161,14 +161,14 @@ } break; } - suspended_threads_list_.Append(tid); + suspended_threads_list_.Append({tid}); 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)) { @@ -184,7 +184,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); } @@ -497,7 +497,7 @@ PtraceRegistersStatus 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 Index: lib/sanitizer_common/sanitizer_stoptheworld_mac.h =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_stoptheworld_mac.h @@ -0,0 +1,35 @@ +//===-- sanitizer_stoptheworld_mac.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Linux-specific code for StopTheWorld. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_STOPTHEWORLD_MAC_H +#define SANITIZER_STOPTHEWORLD_MAC_H + +#include "sanitizer_platform.h" +#if SANITIZER_MAC +#include "sanitizer_internal_defs.h" + +namespace __sanitizer { +typedef unsigned int SuspendedThread; + +// 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 { + tid_t tid; + SuspendedThread thread; +} SuspendedThreadInfo; + +} // namespace __sanitizer + +#endif // SANITIZER_MAC +#endif // SANITIZER_STOPTHEWORLD_MAC_H Index: lib/sanitizer_common/sanitizer_stoptheworld_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld_mac.cc +++ lib/sanitizer_common/sanitizer_stoptheworld_mac.cc @@ -16,9 +16,14 @@ #if SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__) || \ defined(__mips64) || defined(__i386)) +#include + #include "sanitizer_stoptheworld.h" namespace __sanitizer { + +COMPILER_CHECK(sizeof(SuspendedThread) == sizeof(thread_t)); + void StopTheWorld(StopTheWorldCallback callback, void *argument) { CHECK(0 && "unimplemented"); } Index: lib/sanitizer_common/sanitizer_stoptheworld_win.h =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_stoptheworld_win.h @@ -0,0 +1,31 @@ +//===-- sanitizer_stoptheworld_windows.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Windows-specific code for StopTheWorld. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_STOPTHEWORLD_WINDOWS_H +#define SANITIZER_STOPTHEWORLD_WINDOWS_H + +#include "sanitizer_platform.h" +#if SANITIZER_WINDOWS +#include "sanitizer_internal_defs.h" + +namespace __sanitizer { + +// Dummy struct to allow compilation of sanitizer_stoptheworld.h on Windows +typedef struct { + tid_t tid; +} SuspendedThreadInfo; + +} // namespace __sanitizer + +#endif // SANITIZER_WINDOWS +#endif // SANITIZER_STOPTHEWORLD_WINDOWS_H