https://github.com/felipepiovezan created https://github.com/llvm/llvm-project/pull/132734
Please read the two commit messages individually. >From 00da78461321b019303ddffcec5620859829cd40 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <fpiove...@apple.com> Date: Thu, 20 Mar 2025 14:59:33 -0300 Subject: [PATCH 1/2] [lldb][NFC] Break ThreadMemory into smaller abstractions ThreadMemory attempts to be a class abstracting the notion of a "fake" Thread that is backed by a "real" thread. According to its documentation, it is meant to be a class forwarding most methods to the backing thread, but it does so only for a handful of methods. Along the way, it also tries to represent a Thread that may or may not have a different name, and may or may not have a different queue from the backing thread. This can be problematic for a couple of reasons: 1. It forces all users into this optional behavior. 2. The forwarding behavior is incomplete: not all methods are currently being forwarded properly. Some of them involve queues and seem to have been intentionally left unimplemented. This commit creates the following separation: ThreadMemory <- NamedThreadMemory <- NamedThreadMemoryWithQueue ThreadMemory captures the notion of a backed thread that _really_ forwards all methods to the backing thread. (Missing methods should be implemented in a later commit, and allowing them to be implemented without changing behavior of other derived classes is the main purpose of this refactor). NamedThreadMemory is a ThreadMemory that allows users to override the thread name. If a name is present, it is used; otherwise the forwarding behavior is used. NamedThreadMemoryWithQueue is a NamedThreadMemory that allows users to override queue information. If queue information is present, it is used; otherwise, the forwarding behavior is used. With this separation, we can more explicitly implement missing methods of the base class and override them, if needed, in ThreadMemoryWithQueue. But this commit really is NFC, no new methods are implemented and no method implementation is changed. --- .../Python/OperatingSystemPython.cpp | 4 +- .../Plugins/Process/Utility/ThreadMemory.cpp | 23 +++--- .../Plugins/Process/Utility/ThreadMemory.h | 72 ++++++++++++++----- 3 files changed, 66 insertions(+), 33 deletions(-) diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index aff521890858c..ef2291f5c1b3d 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -259,8 +259,8 @@ ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo( if (!thread_sp) { if (did_create_ptr) *did_create_ptr = true; - thread_sp = std::make_shared<ThreadMemory>(*m_process, tid, name, queue, - reg_data_addr); + thread_sp = std::make_shared<NamedThreadMemoryWithQueue>( + *m_process, tid, name, queue, reg_data_addr); } if (core_number < core_thread_list.GetSize(false)) { diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 550b53688fd39..2824a943f757b 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -20,18 +20,17 @@ using namespace lldb; using namespace lldb_private; -ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, - const ValueObjectSP &thread_info_valobj_sp) - : Thread(process, tid), m_backing_thread_sp(), - m_thread_info_valobj_sp(thread_info_valobj_sp), m_name(), m_queue(), - m_register_data_addr(LLDB_INVALID_ADDRESS) {} - -ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, - llvm::StringRef name, llvm::StringRef queue, - lldb::addr_t register_data_addr) - : Thread(process, tid), m_backing_thread_sp(), m_thread_info_valobj_sp(), - m_name(std::string(name)), m_queue(std::string(queue)), - m_register_data_addr(register_data_addr) {} +NamedThreadMemoryWithQueue::NamedThreadMemoryWithQueue( + Process &process, lldb::tid_t tid, + const ValueObjectSP &thread_info_valobj_sp) + : NamedThreadMemory(process, tid, LLDB_INVALID_ADDRESS, ""), + m_thread_info_valobj_sp(thread_info_valobj_sp), m_queue() {} + +NamedThreadMemoryWithQueue::NamedThreadMemoryWithQueue( + Process &process, lldb::tid_t tid, llvm::StringRef name, + llvm::StringRef queue, lldb::addr_t register_data_addr) + : NamedThreadMemory(process, tid, register_data_addr, name), + m_thread_info_valobj_sp(), m_queue(std::string(queue)) {} ThreadMemory::~ThreadMemory() { DestroyThread(); } diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index cebb31538eaf2..d7a73e63964fc 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -13,14 +13,14 @@ #include "lldb/Target/Thread.h" +/// A memory thread optionally backed by a real thread. +/// All methods of this class dispatch to the real thread, if it is not null. +/// Otherwise the methods are no-op. class ThreadMemory : public lldb_private::Thread { public: ThreadMemory(lldb_private::Process &process, lldb::tid_t tid, - const lldb::ValueObjectSP &thread_info_valobj_sp); - - ThreadMemory(lldb_private::Process &process, lldb::tid_t tid, - llvm::StringRef name, llvm::StringRef queue, - lldb::addr_t register_data_addr); + lldb::addr_t register_data_addr) + : Thread(process, tid), m_register_data_addr(register_data_addr) {} ~ThreadMemory() override; @@ -38,16 +38,12 @@ class ThreadMemory : public lldb_private::Thread { } const char *GetName() override { - if (!m_name.empty()) - return m_name.c_str(); if (m_backing_thread_sp) return m_backing_thread_sp->GetName(); return nullptr; } const char *GetQueueName() override { - if (!m_queue.empty()) - return m_queue.c_str(); if (m_backing_thread_sp) return m_backing_thread_sp->GetQueueName(); return nullptr; @@ -68,8 +64,6 @@ class ThreadMemory : public lldb_private::Thread { void RefreshStateAfterStop() override; - lldb::ValueObjectSP &GetValueObject() { return m_thread_info_valobj_sp; } - void ClearStackFrames() override; void ClearBackingThread() override { @@ -79,34 +73,74 @@ class ThreadMemory : public lldb_private::Thread { } bool SetBackingThread(const lldb::ThreadSP &thread_sp) override { - // printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), - // thread_sp->GetID()); m_backing_thread_sp = thread_sp; thread_sp->SetBackedThread(*this); - return (bool)thread_sp; + return thread_sp.get(); } lldb::ThreadSP GetBackingThread() const override { return m_backing_thread_sp; } -protected: bool IsOperatingSystemPluginThread() const override { return true; } +private: + lldb::addr_t m_register_data_addr; // If this memory thread is actually represented by a thread from the // lldb_private::Process subclass, then fill in the thread here and // all APIs will be routed through this thread object. If m_backing_thread_sp // is empty, then this thread is simply in memory with no representation // through the process plug-in. lldb::ThreadSP m_backing_thread_sp; - lldb::ValueObjectSP m_thread_info_valobj_sp; + + ThreadMemory(const ThreadMemory &) = delete; + const ThreadMemory &operator=(const ThreadMemory &) = delete; +}; + +class NamedThreadMemory : public ThreadMemory { +public: + NamedThreadMemory(lldb_private::Process &process, lldb::tid_t tid, + lldb::addr_t register_data_addr, llvm::StringRef name) + : ThreadMemory(process, tid, register_data_addr), m_name(name) {} + + const char *GetName() override { + if (!m_name.empty()) + return m_name.c_str(); + return ThreadMemory::GetName(); + } + +private: std::string m_name; +}; + +/// A NamedThreadMemory that has optional queue information. +class NamedThreadMemoryWithQueue : public NamedThreadMemory { +public: + NamedThreadMemoryWithQueue(lldb_private::Process &process, lldb::tid_t tid, + const lldb::ValueObjectSP &thread_info_valobj_sp); + + NamedThreadMemoryWithQueue(lldb_private::Process &process, lldb::tid_t tid, + llvm::StringRef name, llvm::StringRef queue, + lldb::addr_t register_data_addr); + + ~NamedThreadMemoryWithQueue() override = default; + + const char *GetQueueName() override { + if (!m_queue.empty()) + return m_queue.c_str(); + return ThreadMemory::GetQueueName(); + } + + lldb::ValueObjectSP &GetValueObject() { return m_thread_info_valobj_sp; } + +protected: + lldb::ValueObjectSP m_thread_info_valobj_sp; std::string m_queue; - lldb::addr_t m_register_data_addr; private: - ThreadMemory(const ThreadMemory &) = delete; - const ThreadMemory &operator=(const ThreadMemory &) = delete; + NamedThreadMemoryWithQueue(const NamedThreadMemoryWithQueue &) = delete; + const NamedThreadMemoryWithQueue & + operator=(const NamedThreadMemoryWithQueue &) = delete; }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_THREADMEMORY_H >From 36c9b8d37ccdaf8e1934cf56b5f9c2f6bf2232ec Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <fpiove...@apple.com> Date: Fri, 21 Mar 2025 14:59:05 -0300 Subject: [PATCH 2/2] [lldb] Implement missing queue overloads from ThreadMemory This commit makes ThreadMemory a real "forwarder" class by implementing the missing queue methods: they will just call the corresponding backing thread method. To make this patch NFC(*) and not change the behavior of the Python OS plugin, NamedThreadMemoryWithQueue also overrides these methods to simply call the `Thread` method, just as it was doing before. This also makes it obvious that there are missing pieces of this class if it were to provide full queue support. (*) This patch is NFC in the sense that all llvm.org plugins will not have any behavior change, but downstream consumers of ThreadMemory will benefit from the newly implemented forwarding methods. --- .../Plugins/Process/Utility/ThreadMemory.h | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.h b/lldb/source/Plugins/Process/Utility/ThreadMemory.h index d7a73e63964fc..2d196c33d475d 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.h +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.h @@ -51,6 +51,69 @@ class ThreadMemory : public lldb_private::Thread { void WillResume(lldb::StateType resume_state) override; + void SetQueueName(const char *name) override { + if (m_backing_thread_sp) + m_backing_thread_sp->SetQueueName(name); + } + + lldb::queue_id_t GetQueueID() override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetQueueID(); + return LLDB_INVALID_QUEUE_ID; + } + + void SetQueueID(lldb::queue_id_t new_val) override { + if (m_backing_thread_sp) + m_backing_thread_sp->GetQueueID(); + } + + lldb::QueueKind GetQueueKind() override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetQueueKind(); + return lldb::eQueueKindUnknown; + } + + void SetQueueKind(lldb::QueueKind kind) override { + if (m_backing_thread_sp) + m_backing_thread_sp->SetQueueKind(kind); + } + + lldb::QueueSP GetQueue() override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetQueue(); + return lldb::QueueSP(); + } + + lldb::addr_t GetQueueLibdispatchQueueAddress() override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetQueueLibdispatchQueueAddress(); + return LLDB_INVALID_ADDRESS; + } + + void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override { + if (m_backing_thread_sp) + m_backing_thread_sp->SetQueueLibdispatchQueueAddress(dispatch_queue_t); + } + + lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override { + if (m_backing_thread_sp) + return m_backing_thread_sp->GetAssociatedWithLibdispatchQueue(); + return lldb_private::eLazyBoolNo; + } + + void SetAssociatedWithLibdispatchQueue( + lldb_private::LazyBool associated_with_libdispatch_queue) override { + if (m_backing_thread_sp) + m_backing_thread_sp->SetAssociatedWithLibdispatchQueue( + associated_with_libdispatch_queue); + } + + bool ThreadHasQueueInformation() const override { + if (m_backing_thread_sp) + return m_backing_thread_sp->ThreadHasQueueInformation(); + return false; + } + void DidResume() override { if (m_backing_thread_sp) m_backing_thread_sp->DidResume(); @@ -131,6 +194,55 @@ class NamedThreadMemoryWithQueue : public NamedThreadMemory { return ThreadMemory::GetQueueName(); } + /// This method has not yet been specialized. + void SetQueueName(const char *name) override { Thread::SetQueueName(name); } + + /// This method has not yet been specialized. + lldb::queue_id_t GetQueueID() override { return Thread::GetQueueID(); } + + /// This method has not yet been specialized. + void SetQueueID(lldb::queue_id_t new_val) override { + Thread::SetQueueID(new_val); + } + + /// This method has not yet been specialized. + lldb::QueueKind GetQueueKind() override { return Thread::GetQueueKind(); } + + /// This method has not yet been specialized. + void SetQueueKind(lldb::QueueKind kind) override { + Thread::SetQueueKind(kind); + } + + /// This method has not yet been specialized. + lldb::QueueSP GetQueue() override { return Thread::GetQueue(); } + + /// This method has not yet been specialized. + lldb::addr_t GetQueueLibdispatchQueueAddress() override { + return Thread::GetQueueLibdispatchQueueAddress(); + } + + /// This method has not yet been specialized. + void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override { + Thread::SetQueueLibdispatchQueueAddress(dispatch_queue_t); + } + + /// This method has not yet been specialized. + bool ThreadHasQueueInformation() const override { + return Thread::ThreadHasQueueInformation(); + } + + /// This method has not yet been specialized. + lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override { + return Thread::GetAssociatedWithLibdispatchQueue(); + } + + /// This method has not yet been specialized. + void SetAssociatedWithLibdispatchQueue( + lldb_private::LazyBool associated_with_libdispatch_queue) override { + Thread::SetAssociatedWithLibdispatchQueue( + associated_with_libdispatch_queue); + } + lldb::ValueObjectSP &GetValueObject() { return m_thread_info_valobj_sp; } protected: _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits