diff options
| author | Francis Ricci <francisjricci@gmail.com> | 2017-04-17 20:29:38 +0000 |
|---|---|---|
| committer | Francis Ricci <francisjricci@gmail.com> | 2017-04-17 20:29:38 +0000 |
| commit | 5989dd241e751c946ea39cb88e63f4bf33823b5f (patch) | |
| tree | 5ba7da615c5e4c2cfb7f4c44b67283cd562484de | |
| parent | f7a4f3dd95b907b693a986cb0cf076fa1e93e276 (diff) | |
| download | bcm5719-llvm-5989dd241e751c946ea39cb88e63f4bf33823b5f.tar.gz bcm5719-llvm-5989dd241e751c946ea39cb88e63f4bf33823b5f.zip | |
Update suspended threads info to be compatible with darwin
Summary:
On Darwin, we need to track thread and tid as separate values.
This patch splits out the implementation of the suspended threads list
to be OS-specific.
Reviewers: glider, kubamracek, kcc
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D31474
llvm-svn: 300491
4 files changed, 119 insertions, 37 deletions
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index 8ca0905d62f..e7eea68537c 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -200,10 +200,10 @@ void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg) { // Scans thread data (stacks and TLS) for heap pointers. static void ProcessThreads(SuspendedThreadsList const &suspended_threads, Frontier *frontier) { - InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount()); + InternalScopedBuffer<uptr> registers(suspended_threads.RegisterCount()); uptr registers_begin = reinterpret_cast<uptr>(registers.data()); uptr registers_end = registers_begin + registers.size(); - for (uptr i = 0; i < suspended_threads.thread_count(); i++) { + for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) { tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i)); LOG_THREADS("Processing thread %d.\n", os_id); uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h index f7ee018b6e8..20b49ae78b8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld.h @@ -29,31 +29,21 @@ enum PtraceRegistersStatus { // register contexts. class SuspendedThreadsList { public: - SuspendedThreadsList() - : thread_ids_(1024) {} - tid_t GetThreadID(uptr index) const { - CHECK_LT(index, thread_ids_.size()); - return thread_ids_[index]; + SuspendedThreadsList() = default; + + // Can't declare pure virtual functions in sanitizer runtimes: + // __cxa_pure_virtual might be unavailable. Use UNIMPLEMENTED() instead. + virtual PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, + uptr *sp) const { + UNIMPLEMENTED(); } - 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) - return true; - } - return false; - } - void Append(tid_t thread_id) { - thread_ids_.push_back(thread_id); - } + virtual uptr RegisterCount() const { UNIMPLEMENTED(); } + virtual uptr ThreadCount() const { UNIMPLEMENTED(); } + virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); } private: - InternalMmapVector<tid_t> thread_ids_; - // Prohibit copy and assign. SuspendedThreadsList(const SuspendedThreadsList&); void operator=(const SuspendedThreadsList&); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index 81ff70963e2..91f798cd2f8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -82,6 +82,23 @@ namespace __sanitizer { +class SuspendedThreadsListLinux : public SuspendedThreadsList { + public: + SuspendedThreadsListLinux() : thread_ids_(1024) {} + + tid_t GetThreadID(uptr index) const; + uptr ThreadCount() const; + bool ContainsTid(tid_t thread_id) const; + void Append(tid_t tid); + + PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, + uptr *sp) const; + uptr RegisterCount() const; + + private: + InternalMmapVector<tid_t> thread_ids_; +}; + // Structure for passing arguments into the tracer thread. struct TracerThreadArgument { StopTheWorldCallback callback; @@ -105,12 +122,12 @@ class ThreadSuspender { bool SuspendAllThreads(); void ResumeAllThreads(); void KillAllThreads(); - SuspendedThreadsList &suspended_threads_list() { + SuspendedThreadsListLinux &suspended_threads_list() { return suspended_threads_list_; } TracerThreadArgument *arg; private: - SuspendedThreadsList suspended_threads_list_; + SuspendedThreadsListLinux suspended_threads_list_; pid_t pid_; bool SuspendThread(tid_t thread_id); }; @@ -119,8 +136,7 @@ bool ThreadSuspender::SuspendThread(tid_t 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)) - return false; + if (suspended_threads_list_.ContainsTid(tid)) return false; int pterrno; if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr), &pterrno)) { @@ -165,7 +181,7 @@ bool ThreadSuspender::SuspendThread(tid_t tid) { } void ThreadSuspender::ResumeAllThreads() { - for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { + for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++) { pid_t tid = suspended_threads_list_.GetThreadID(i); int pterrno; if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, nullptr, nullptr), @@ -181,7 +197,7 @@ void ThreadSuspender::ResumeAllThreads() { } void ThreadSuspender::KillAllThreads() { - for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) + for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++) internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i), nullptr, nullptr); } @@ -492,9 +508,28 @@ typedef _user_regs_struct regs_struct; #error "Unsupported architecture" #endif // SANITIZER_ANDROID && defined(__arm__) -PtraceRegistersStatus SuspendedThreadsList::GetRegistersAndSP(uptr index, - uptr *buffer, - uptr *sp) const { +tid_t SuspendedThreadsListLinux::GetThreadID(uptr index) const { + CHECK_LT(index, thread_ids_.size()); + return thread_ids_[index]; +} + +uptr SuspendedThreadsListLinux::ThreadCount() const { + return thread_ids_.size(); +} + +bool SuspendedThreadsListLinux::ContainsTid(tid_t thread_id) const { + for (uptr i = 0; i < thread_ids_.size(); i++) { + if (thread_ids_[i] == thread_id) return true; + } + return false; +} + +void SuspendedThreadsListLinux::Append(tid_t tid) { + thread_ids_.push_back(tid); +} + +PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP( + uptr index, uptr *buffer, uptr *sp) const { pid_t tid = GetThreadID(index); regs_struct regs; int pterrno; @@ -524,7 +559,7 @@ PtraceRegistersStatus SuspendedThreadsList::GetRegistersAndSP(uptr index, return REGISTERS_AVAILABLE; } -uptr SuspendedThreadsList::RegisterCount() { +uptr SuspendedThreadsListLinux::RegisterCount() const { return sizeof(regs_struct) / sizeof(uptr); } } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc index 047472a657a..f65065e276a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cc @@ -16,21 +16,78 @@ #if SANITIZER_MAC && (defined(__x86_64__) || defined(__aarch64__) || \ defined(__mips64) || defined(__i386)) +#include <mach/mach.h> + #include "sanitizer_stoptheworld.h" namespace __sanitizer { +typedef struct { + tid_t tid; + thread_t thread; +} SuspendedThreadInfo; + +class SuspendedThreadsListMac : public SuspendedThreadsList { + public: + SuspendedThreadsListMac() : threads_(1024) {} + + tid_t GetThreadID(uptr index) const; + thread_t GetThread(uptr index) const; + uptr ThreadCount() const; + bool ContainsThread(thread_t thread) const; + void Append(thread_t thread); + + PtraceRegistersStatus GetRegistersAndSP(uptr index, uptr *buffer, + uptr *sp) const; + uptr RegisterCount() const; + + private: + InternalMmapVector<SuspendedThreadInfo> threads_; +}; + void StopTheWorld(StopTheWorldCallback callback, void *argument) { CHECK(0 && "unimplemented"); } -PtraceRegistersStatus SuspendedThreadsList::GetRegistersAndSP(uptr index, - uptr *buffer, - uptr *sp) const { +tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const { + CHECK_LT(index, threads_.size()); + return threads_[index].tid; +} + +thread_t SuspendedThreadsListMac::GetThread(uptr index) const { + CHECK_LT(index, threads_.size()); + return threads_[index].thread; +} + +uptr SuspendedThreadsListMac::ThreadCount() const { + return threads_.size(); +} + +bool SuspendedThreadsListMac::ContainsThread(thread_t thread) const { + for (uptr i = 0; i < threads_.size(); i++) { + if (threads_[i].thread == thread) return true; + } + return false; +} + +void SuspendedThreadsListMac::Append(thread_t thread) { + 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; + } + threads_.push_back({info.thread_id, thread}); +} + +PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP( + uptr index, uptr *buffer, uptr *sp) const { CHECK(0 && "unimplemented"); return REGISTERS_UNAVAILABLE_FATAL; } -uptr SuspendedThreadsList::RegisterCount() { +uptr SuspendedThreadsListMac::RegisterCount() const { CHECK(0 && "unimplemented"); return 0; } |

