Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -201,13 +201,13 @@ } // Scans thread data (stacks and TLS) for heap pointers. -static void ProcessThreads(SuspendedThreadsList const &suspended_threads, +static void ProcessThreads(SuspendedThreadsRegisters const &suspended_threads, Frontier *frontier) { - InternalScopedBuffer registers(SuspendedThreadsList::RegisterCount()); + InternalScopedBuffer registers(suspended_threads.RegisterCount()); 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)); + for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) { + uptr os_id = 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; bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end, @@ -330,7 +330,8 @@ } // Sets the appropriate tag on each chunk. -static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) { +static void ClassifyAllChunks( + SuspendedThreadsRegisters const &suspended_threads) { // Holds the flood fill frontier. Frontier frontier(1); @@ -407,8 +408,9 @@ LeakReport leak_report; }; -static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads, - void *arg) { +static void DoLeakCheckCallback( + const SuspendedThreadsRegisters &suspended_threads, + void *arg) { DoLeakCheckParam *param = reinterpret_cast(arg); CHECK(param); CHECK(!param->success); Index: lib/sanitizer_common/sanitizer_stoptheworld.h =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld.h +++ lib/sanitizer_common/sanitizer_stoptheworld.h @@ -18,22 +18,36 @@ #include "sanitizer_common.h" namespace __sanitizer { -typedef int SuspendedThreadID; // Holds the list of suspended threads and provides an interface to dump their // register contexts. -class SuspendedThreadsList { +class SuspendedThreadsRegisters { + public: + // The buffer in GetRegistersAndSP should be at least this big. + virtual uptr RegisterCount() const { UNIMPLEMENTED(); } + virtual uptr ThreadCount() const { UNIMPLEMENTED(); } + // Only used by LSan to print the thread ID. + virtual uptr GetThreadID(uptr index) const { UNIMPLEMENTED(); } + virtual int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const { + UNIMPLEMENTED(); + } +}; + +template +class SuspendedThreadsList : public SuspendedThreadsRegisters { public: SuspendedThreadsList() : thread_ids_(1024) {} - SuspendedThreadID GetThreadID(uptr index) const { + virtual uptr RegisterCount() const; + virtual uptr ThreadCount() const { return thread_ids_.size(); } + SuspendedThreadID GetNativeThreadID(uptr index) const { CHECK_LT(index, thread_ids_.size()); return thread_ids_[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(); } + virtual uptr GetThreadID(uptr index) const { + return (uptr)GetNativeThreadID(index); + } + virtual int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const; bool Contains(SuspendedThreadID thread_id) const { for (uptr i = 0; i < thread_ids_.size(); i++) { if (thread_ids_[i] == thread_id) @@ -53,8 +67,9 @@ void operator=(const SuspendedThreadsList&); }; + typedef void (*StopTheWorldCallback)( - const SuspendedThreadsList &suspended_threads_list, + const SuspendedThreadsRegisters &suspended_threads_list, void *argument); // Suspend all threads in the current process and run the callback on the list 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 @@ -67,25 +67,26 @@ // thread-local variables used by libc will be shared between the tracer task // and the thread which spawned it. -COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t)); +typedef pid_t SuspendedThreadID; namespace __sanitizer { + // This class handles thread suspending/unsuspending in the tracer thread. class ThreadSuspender { public: - explicit ThreadSuspender(pid_t pid) + explicit ThreadSuspender(SuspendedThreadID pid) : pid_(pid) { CHECK_GE(pid, 0); } bool SuspendAllThreads(); void ResumeAllThreads(); void KillAllThreads(); - SuspendedThreadsList &suspended_threads_list() { + SuspendedThreadsList &suspended_threads_list() { return suspended_threads_list_; } private: - SuspendedThreadsList suspended_threads_list_; - pid_t pid_; + SuspendedThreadsList suspended_threads_list_; + SuspendedThreadID pid_; bool SuspendThread(SuspendedThreadID thread_id); }; @@ -124,8 +125,8 @@ } void ThreadSuspender::ResumeAllThreads() { - for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { - pid_t tid = suspended_threads_list_.GetThreadID(i); + for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++) { + pid_t tid = suspended_threads_list_.GetNativeThreadID(i); int pterrno; if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL), &pterrno)) { @@ -140,8 +141,8 @@ } void ThreadSuspender::KillAllThreads() { - for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) - internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i), + for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++) + internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetNativeThreadID(i), NULL, NULL); } @@ -436,10 +437,10 @@ #error "Unsupported architecture" #endif // SANITIZER_ANDROID && defined(__arm__) -int SuspendedThreadsList::GetRegistersAndSP(uptr index, - uptr *buffer, - uptr *sp) const { - pid_t tid = GetThreadID(index); +template <> +int SuspendedThreadsList::GetRegistersAndSP( + uptr index, uptr *buffer, uptr *sp) const { + pid_t tid = GetNativeThreadID(index); regs_struct regs; int pterrno; if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, ®s), @@ -454,9 +455,11 @@ return 0; } -uptr SuspendedThreadsList::RegisterCount() { +template <> +uptr SuspendedThreadsList::RegisterCount() const { return sizeof(regs_struct) / sizeof(uptr); } + } // namespace __sanitizer #endif // SANITIZER_LINUX && defined(__x86_64__)