Index: lib/sanitizer_common/sanitizer_stoptheworld.h =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld.h +++ lib/sanitizer_common/sanitizer_stoptheworld.h @@ -17,36 +17,65 @@ #include "sanitizer_internal_defs.h" #include "sanitizer_common.h" +#if SANITIZER_MAC +#include +#endif + namespace __sanitizer { typedef int SuspendedThreadID; +#if SANITIZER_LINUX +typedef SuspendedThreadID SuspendedThread; +#elif SANITIZER_MAC +typedef thread_t SuspendedThread; +#endif + +// 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 2 copies +// of the tid. +struct SuspendedThreadInfo { + SuspendedThread thread; + SuspendedThreadID tid; +}; + // Holds the list of suspended threads and provides an interface to dump their // register contexts. class SuspendedThreadsList { public: SuspendedThreadsList() - : thread_ids_(1024) {} + : threads_(1024) {} + + SuspendedThread GetThread(uptr index) const { + CHECK_LT(index, threads_.size()); + return threads_[index].thread; + } + SuspendedThreadID GetThreadID(uptr index) const { - CHECK_LT(index, thread_ids_.size()); - return thread_ids_[index]; + CHECK_LT(index, threads_.size()); + return threads_[index].tid; } + + SuspendedThreadID ThreadToThreadID(SuspendedThread) const; + 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(SuspendedThread thread) const { + for (uptr i = 0; i < threads_.size(); i++) { + if (threads_[i].thread == thread) return true; } return false; } - void Append(SuspendedThreadID thread_id) { - thread_ids_.push_back(thread_id); + + void Append(SuspendedThread thread) { + threads_.push_back({thread, ThreadToThreadID(thread)}); } 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 @@ -493,6 +493,11 @@ #error "Unsupported architecture" #endif // SANITIZER_ANDROID && defined(__arm__) +SuspendedThreadID +SuspendedThreadsList::ThreadToThreadID(SuspendedThread thread) const { + return thread; +} + int SuspendedThreadsList::GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const { Index: lib/sanitizer_common/sanitizer_stoptheworld_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld_mac.cc +++ lib/sanitizer_common/sanitizer_stoptheworld_mac.cc @@ -16,6 +16,8 @@ #if SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__) || \ defined(__mips64) || defined(__i386)) +#include + #include "sanitizer_stoptheworld.h" namespace __sanitizer { @@ -23,6 +25,19 @@ CHECK(0 && "unimplemented"); } +SuspendedThreadID +SuspendedThreadsList::ThreadToThreadID(SuspendedThread thread) const { + thread_identifier_info_data_t info; + mach_msg_type_number_t info_count = THREAD_IDENTIFIER_INFO_COUNT; + kern_return_t err = thread_info(thread, THREAD_IDENTIFIER_INFO, + (thread_info_t)&info, &info_count); + if (err != KERN_SUCCESS) { + VReport(1, "Error - unable to get thread ident for a thread\n"); + return 0; + } + return info.thread_id; +} + int SuspendedThreadsList::GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const {