1 | //===-- ThreadList.h --------------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_TARGET_THREADLIST_H |
10 | #define LLDB_TARGET_THREADLIST_H |
11 | |
12 | #include <mutex> |
13 | #include <vector> |
14 | |
15 | #include "lldb/Target/Thread.h" |
16 | #include "lldb/Target/ThreadCollection.h" |
17 | #include "lldb/Utility/Iterable.h" |
18 | #include "lldb/Utility/UserID.h" |
19 | #include "lldb/lldb-private.h" |
20 | |
21 | namespace lldb_private { |
22 | |
23 | // This is a thread list with lots of functionality for use only by the process |
24 | // for which this is the thread list. A generic container class with iterator |
25 | // functionality is ThreadCollection. |
26 | class ThreadList : public ThreadCollection { |
27 | friend class Process; |
28 | |
29 | public: |
30 | ThreadList(Process *process); |
31 | |
32 | ThreadList(const ThreadList &rhs); |
33 | |
34 | ~ThreadList() override; |
35 | |
36 | const ThreadList &operator=(const ThreadList &rhs); |
37 | |
38 | uint32_t GetSize(bool can_update = true); |
39 | |
40 | // Return the selected thread if there is one. Otherwise, return the thread |
41 | // selected at index 0. |
42 | lldb::ThreadSP GetSelectedThread(); |
43 | |
44 | // Manage the thread to use for running expressions. This is usually the |
45 | // Selected thread, but sometimes (e.g. when evaluating breakpoint conditions |
46 | // & stop hooks) it isn't. |
47 | class ExpressionExecutionThreadPusher { |
48 | public: |
49 | ExpressionExecutionThreadPusher(ThreadList &thread_list, lldb::tid_t tid) |
50 | : m_thread_list(&thread_list), m_tid(tid) { |
51 | m_thread_list->PushExpressionExecutionThread(tid: m_tid); |
52 | } |
53 | |
54 | ExpressionExecutionThreadPusher(lldb::ThreadSP thread_sp); |
55 | |
56 | ~ExpressionExecutionThreadPusher() { |
57 | if (m_thread_list && m_tid != LLDB_INVALID_THREAD_ID) |
58 | m_thread_list->PopExpressionExecutionThread(tid: m_tid); |
59 | } |
60 | |
61 | private: |
62 | ThreadList *m_thread_list; |
63 | lldb::tid_t m_tid; |
64 | }; |
65 | |
66 | lldb::ThreadSP GetExpressionExecutionThread(); |
67 | |
68 | protected: |
69 | void PushExpressionExecutionThread(lldb::tid_t tid); |
70 | |
71 | void PopExpressionExecutionThread(lldb::tid_t tid); |
72 | |
73 | public: |
74 | bool SetSelectedThreadByID(lldb::tid_t tid, bool notify = false); |
75 | |
76 | bool SetSelectedThreadByIndexID(uint32_t index_id, bool notify = false); |
77 | |
78 | void Clear(); |
79 | |
80 | void Flush(); |
81 | |
82 | void Destroy(); |
83 | |
84 | // Note that "idx" is not the same as the "thread_index". It is a zero based |
85 | // index to accessing the current threads, whereas "thread_index" is a unique |
86 | // index assigned |
87 | lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update = true); |
88 | |
89 | lldb::ThreadSP FindThreadByID(lldb::tid_t tid, bool can_update = true); |
90 | |
91 | lldb::ThreadSP FindThreadByProtocolID(lldb::tid_t tid, |
92 | bool can_update = true); |
93 | |
94 | lldb::ThreadSP RemoveThreadByID(lldb::tid_t tid, bool can_update = true); |
95 | |
96 | lldb::ThreadSP RemoveThreadByProtocolID(lldb::tid_t tid, |
97 | bool can_update = true); |
98 | |
99 | lldb::ThreadSP FindThreadByIndexID(uint32_t index_id, bool can_update = true); |
100 | |
101 | lldb::ThreadSP GetThreadSPForThreadPtr(Thread *thread_ptr); |
102 | |
103 | lldb::ThreadSP GetBackingThread(const lldb::ThreadSP &real_thread); |
104 | |
105 | bool ShouldStop(Event *event_ptr); |
106 | |
107 | Vote ShouldReportStop(Event *event_ptr); |
108 | |
109 | Vote ShouldReportRun(Event *event_ptr); |
110 | |
111 | void RefreshStateAfterStop(); |
112 | |
113 | /// The thread list asks tells all the threads it is about to resume. |
114 | /// If a thread can "resume" without having to resume the target, it |
115 | /// will return false for WillResume, and then the process will not be |
116 | /// restarted. |
117 | /// |
118 | /// \return |
119 | /// \b true instructs the process to resume normally, |
120 | /// \b false means start & stopped events will be generated, but |
121 | /// the process will not actually run. The thread must then return |
122 | /// the correct StopInfo when asked. |
123 | /// |
124 | bool WillResume(); |
125 | |
126 | void DidResume(); |
127 | |
128 | void DidStop(); |
129 | |
130 | void DiscardThreadPlans(); |
131 | |
132 | uint32_t GetStopID() const; |
133 | |
134 | void SetStopID(uint32_t stop_id); |
135 | |
136 | std::recursive_mutex &GetMutex() const override; |
137 | |
138 | void Update(ThreadList &rhs); |
139 | |
140 | protected: |
141 | void SetShouldReportStop(Vote vote); |
142 | |
143 | void NotifySelectedThreadChanged(lldb::tid_t tid); |
144 | |
145 | // Classes that inherit from Process can see and modify these |
146 | Process *m_process; ///< The process that manages this thread list. |
147 | uint32_t |
148 | m_stop_id; ///< The process stop ID that this thread list is valid for. |
149 | lldb::tid_t |
150 | m_selected_tid; ///< For targets that need the notion of a current thread. |
151 | std::vector<lldb::tid_t> m_expression_tid_stack; |
152 | |
153 | private: |
154 | ThreadList() = delete; |
155 | }; |
156 | |
157 | } // namespace lldb_private |
158 | |
159 | #endif // LLDB_TARGET_THREADLIST_H |
160 | |