1be691f3bSpatrick //===-- CommandObjectThreadUtil.h -------------------------------*- C++ -*-===// 2be691f3bSpatrick // 3be691f3bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4be691f3bSpatrick // See https://llvm.org/LICENSE.txt for license information. 5be691f3bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6be691f3bSpatrick // 7be691f3bSpatrick //===----------------------------------------------------------------------===// 8be691f3bSpatrick 9be691f3bSpatrick #ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREADUTIL_H 10be691f3bSpatrick #define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREADUTIL_H 11be691f3bSpatrick 12be691f3bSpatrick #include "lldb/Interpreter/CommandObjectMultiword.h" 13be691f3bSpatrick 14be691f3bSpatrick namespace lldb_private { 15be691f3bSpatrick 16be691f3bSpatrick class CommandObjectIterateOverThreads : public CommandObjectParsed { 17be691f3bSpatrick 18be691f3bSpatrick class UniqueStack { 19be691f3bSpatrick public: UniqueStack(std::stack<lldb::addr_t> stack_frames,uint32_t thread_index_id)20be691f3bSpatrick UniqueStack(std::stack<lldb::addr_t> stack_frames, uint32_t thread_index_id) 21be691f3bSpatrick : m_stack_frames(stack_frames) { 22be691f3bSpatrick m_thread_index_ids.push_back(thread_index_id); 23be691f3bSpatrick } 24be691f3bSpatrick AddThread(uint32_t thread_index_id)25be691f3bSpatrick void AddThread(uint32_t thread_index_id) const { 26be691f3bSpatrick m_thread_index_ids.push_back(thread_index_id); 27be691f3bSpatrick } 28be691f3bSpatrick GetUniqueThreadIndexIDs()29be691f3bSpatrick const std::vector<uint32_t> &GetUniqueThreadIndexIDs() const { 30be691f3bSpatrick return m_thread_index_ids; 31be691f3bSpatrick } 32be691f3bSpatrick GetRepresentativeThread()33be691f3bSpatrick lldb::tid_t GetRepresentativeThread() const { 34be691f3bSpatrick return m_thread_index_ids.front(); 35be691f3bSpatrick } 36be691f3bSpatrick 37be691f3bSpatrick friend bool inline operator<(const UniqueStack &lhs, 38be691f3bSpatrick const UniqueStack &rhs) { 39be691f3bSpatrick return lhs.m_stack_frames < rhs.m_stack_frames; 40be691f3bSpatrick } 41be691f3bSpatrick 42be691f3bSpatrick protected: 43be691f3bSpatrick // Mark the thread index as mutable, as we don't care about it from a const 44be691f3bSpatrick // perspective, we only care about m_stack_frames so we keep our std::set 45be691f3bSpatrick // sorted. 46be691f3bSpatrick mutable std::vector<uint32_t> m_thread_index_ids; 47be691f3bSpatrick std::stack<lldb::addr_t> m_stack_frames; 48be691f3bSpatrick }; 49be691f3bSpatrick 50be691f3bSpatrick public: 51be691f3bSpatrick CommandObjectIterateOverThreads(CommandInterpreter &interpreter, 52be691f3bSpatrick const char *name, const char *help, 53be691f3bSpatrick const char *syntax, uint32_t flags); 54be691f3bSpatrick 55be691f3bSpatrick ~CommandObjectIterateOverThreads() override = default; 56be691f3bSpatrick 57be691f3bSpatrick bool DoExecute(Args &command, CommandReturnObject &result) override; 58be691f3bSpatrick 59be691f3bSpatrick protected: 60be691f3bSpatrick // Override this to do whatever you need to do for one thread. 61be691f3bSpatrick // 62be691f3bSpatrick // If you return false, the iteration will stop, otherwise it will proceed. 63be691f3bSpatrick // The result is set to m_success_return (defaults to 64be691f3bSpatrick // eReturnStatusSuccessFinishResult) before the iteration, so you only need 65be691f3bSpatrick // to set the return status in HandleOneThread if you want to indicate an 66be691f3bSpatrick // error. If m_add_return is true, a blank line will be inserted between each 67be691f3bSpatrick // of the listings (except the last one.) 68be691f3bSpatrick 69be691f3bSpatrick virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0; 70be691f3bSpatrick 71be691f3bSpatrick bool BucketThread(lldb::tid_t tid, std::set<UniqueStack> &unique_stacks, 72be691f3bSpatrick CommandReturnObject &result); 73be691f3bSpatrick 74be691f3bSpatrick lldb::ReturnStatus m_success_return = lldb::eReturnStatusSuccessFinishResult; 75be691f3bSpatrick bool m_unique_stacks = false; 76be691f3bSpatrick bool m_add_return = true; 77be691f3bSpatrick }; 78be691f3bSpatrick 79be691f3bSpatrick /// Class similar to \a CommandObjectIterateOverThreads, but which performs 80be691f3bSpatrick /// an action on multiple threads at once instead of iterating over each thread. 81be691f3bSpatrick class CommandObjectMultipleThreads : public CommandObjectParsed { 82be691f3bSpatrick public: 83*f6aab3d8Srobert CommandObjectMultipleThreads(CommandInterpreter &interpreter, 84*f6aab3d8Srobert const char *name, const char *help, 85*f6aab3d8Srobert const char *syntax, uint32_t flags); 86be691f3bSpatrick 87be691f3bSpatrick bool DoExecute(Args &command, CommandReturnObject &result) override; 88be691f3bSpatrick 89be691f3bSpatrick protected: 90be691f3bSpatrick /// Method that handles the command after the main arguments have been parsed. 91be691f3bSpatrick /// 92be691f3bSpatrick /// \param[in] tids 93be691f3bSpatrick /// The thread ids passed as arguments. 94be691f3bSpatrick /// 95be691f3bSpatrick /// \return 96be691f3bSpatrick /// A boolean result similar to the one expected from \a DoExecute. 97be691f3bSpatrick virtual bool DoExecuteOnThreads(Args &command, CommandReturnObject &result, 98be691f3bSpatrick llvm::ArrayRef<lldb::tid_t> tids) = 0; 99be691f3bSpatrick }; 100be691f3bSpatrick 101be691f3bSpatrick } // namespace lldb_private 102be691f3bSpatrick 103be691f3bSpatrick #endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTHREADUTIL_H 104