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