1ac7ddfbfSEd Maste //===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
99f2f44ceSEd Maste
10ac7ddfbfSEd Maste #include <stdlib.h>
11ac7ddfbfSEd Maste
12ac7ddfbfSEd Maste #include <algorithm>
13ac7ddfbfSEd Maste
14ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
15435933ddSDimitry Andric #include "lldb/Target/RegisterContext.h"
16435933ddSDimitry Andric #include "lldb/Target/Thread.h"
17435933ddSDimitry Andric #include "lldb/Target/ThreadList.h"
18435933ddSDimitry Andric #include "lldb/Target/ThreadPlan.h"
199f2f44ceSEd Maste #include "lldb/Utility/LLDBAssert.h"
20f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
21*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
22ac7ddfbfSEd Maste
23ac7ddfbfSEd Maste using namespace lldb;
24ac7ddfbfSEd Maste using namespace lldb_private;
25ac7ddfbfSEd Maste
ThreadList(Process * process)26435933ddSDimitry Andric ThreadList::ThreadList(Process *process)
27435933ddSDimitry Andric : ThreadCollection(), m_process(process), m_stop_id(0),
28435933ddSDimitry Andric m_selected_tid(LLDB_INVALID_THREAD_ID) {}
29ac7ddfbfSEd Maste
ThreadList(const ThreadList & rhs)30435933ddSDimitry Andric ThreadList::ThreadList(const ThreadList &rhs)
31435933ddSDimitry Andric : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id),
32435933ddSDimitry Andric m_selected_tid() {
33ac7ddfbfSEd Maste // Use the assignment operator since it uses the mutex
34ac7ddfbfSEd Maste *this = rhs;
35ac7ddfbfSEd Maste }
36ac7ddfbfSEd Maste
operator =(const ThreadList & rhs)37435933ddSDimitry Andric const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
38435933ddSDimitry Andric if (this != &rhs) {
394ba319b5SDimitry Andric // Lock both mutexes to make sure neither side changes anyone on us while
404ba319b5SDimitry Andric // the assignment occurs
414bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
42435933ddSDimitry Andric std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex());
434bb0738eSEd Maste
44ac7ddfbfSEd Maste m_process = rhs.m_process;
45ac7ddfbfSEd Maste m_stop_id = rhs.m_stop_id;
46ac7ddfbfSEd Maste m_threads = rhs.m_threads;
47ac7ddfbfSEd Maste m_selected_tid = rhs.m_selected_tid;
48ac7ddfbfSEd Maste }
49ac7ddfbfSEd Maste return *this;
50ac7ddfbfSEd Maste }
51ac7ddfbfSEd Maste
~ThreadList()52435933ddSDimitry Andric ThreadList::~ThreadList() {
534ba319b5SDimitry Andric // Clear the thread list. Clear will take the mutex lock which will ensure
544ba319b5SDimitry Andric // that if anyone is using the list they won't get it removed while using it.
55ac7ddfbfSEd Maste Clear();
56ac7ddfbfSEd Maste }
57ac7ddfbfSEd Maste
GetExpressionExecutionThread()58435933ddSDimitry Andric lldb::ThreadSP ThreadList::GetExpressionExecutionThread() {
594bb0738eSEd Maste if (m_expression_tid_stack.empty())
604bb0738eSEd Maste return GetSelectedThread();
614bb0738eSEd Maste ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back());
624bb0738eSEd Maste if (expr_thread_sp)
634bb0738eSEd Maste return expr_thread_sp;
644bb0738eSEd Maste else
654bb0738eSEd Maste return GetSelectedThread();
664bb0738eSEd Maste }
674bb0738eSEd Maste
PushExpressionExecutionThread(lldb::tid_t tid)68435933ddSDimitry Andric void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) {
694bb0738eSEd Maste m_expression_tid_stack.push_back(tid);
704bb0738eSEd Maste }
714bb0738eSEd Maste
PopExpressionExecutionThread(lldb::tid_t tid)72435933ddSDimitry Andric void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) {
734bb0738eSEd Maste assert(m_expression_tid_stack.back() == tid);
744bb0738eSEd Maste m_expression_tid_stack.pop_back();
754bb0738eSEd Maste }
76ac7ddfbfSEd Maste
GetStopID() const77435933ddSDimitry Andric uint32_t ThreadList::GetStopID() const { return m_stop_id; }
78ac7ddfbfSEd Maste
SetStopID(uint32_t stop_id)79435933ddSDimitry Andric void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }
80ac7ddfbfSEd Maste
GetSize(bool can_update)81435933ddSDimitry Andric uint32_t ThreadList::GetSize(bool can_update) {
824bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
834bb0738eSEd Maste
84ac7ddfbfSEd Maste if (can_update)
85ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
86ac7ddfbfSEd Maste return m_threads.size();
87ac7ddfbfSEd Maste }
88ac7ddfbfSEd Maste
GetThreadAtIndex(uint32_t idx,bool can_update)89435933ddSDimitry Andric ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) {
904bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
914bb0738eSEd Maste
92ac7ddfbfSEd Maste if (can_update)
93ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
94ac7ddfbfSEd Maste
95ac7ddfbfSEd Maste ThreadSP thread_sp;
96ac7ddfbfSEd Maste if (idx < m_threads.size())
97ac7ddfbfSEd Maste thread_sp = m_threads[idx];
98ac7ddfbfSEd Maste return thread_sp;
99ac7ddfbfSEd Maste }
100ac7ddfbfSEd Maste
FindThreadByID(lldb::tid_t tid,bool can_update)101435933ddSDimitry Andric ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) {
1024bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
103ac7ddfbfSEd Maste
104ac7ddfbfSEd Maste if (can_update)
105ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
106ac7ddfbfSEd Maste
107ac7ddfbfSEd Maste ThreadSP thread_sp;
108ac7ddfbfSEd Maste uint32_t idx = 0;
109ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
110435933ddSDimitry Andric for (idx = 0; idx < num_threads; ++idx) {
111435933ddSDimitry Andric if (m_threads[idx]->GetID() == tid) {
112ac7ddfbfSEd Maste thread_sp = m_threads[idx];
113ac7ddfbfSEd Maste break;
114ac7ddfbfSEd Maste }
115ac7ddfbfSEd Maste }
116ac7ddfbfSEd Maste return thread_sp;
117ac7ddfbfSEd Maste }
118ac7ddfbfSEd Maste
FindThreadByProtocolID(lldb::tid_t tid,bool can_update)119435933ddSDimitry Andric ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) {
1204bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
121ac7ddfbfSEd Maste
122ac7ddfbfSEd Maste if (can_update)
123ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
124ac7ddfbfSEd Maste
125ac7ddfbfSEd Maste ThreadSP thread_sp;
126ac7ddfbfSEd Maste uint32_t idx = 0;
127ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
128435933ddSDimitry Andric for (idx = 0; idx < num_threads; ++idx) {
129435933ddSDimitry Andric if (m_threads[idx]->GetProtocolID() == tid) {
130ac7ddfbfSEd Maste thread_sp = m_threads[idx];
131ac7ddfbfSEd Maste break;
132ac7ddfbfSEd Maste }
133ac7ddfbfSEd Maste }
134ac7ddfbfSEd Maste return thread_sp;
135ac7ddfbfSEd Maste }
136ac7ddfbfSEd Maste
RemoveThreadByID(lldb::tid_t tid,bool can_update)137435933ddSDimitry Andric ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) {
1384bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
139ac7ddfbfSEd Maste
140ac7ddfbfSEd Maste if (can_update)
141ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
142ac7ddfbfSEd Maste
143ac7ddfbfSEd Maste ThreadSP thread_sp;
144ac7ddfbfSEd Maste uint32_t idx = 0;
145ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
146435933ddSDimitry Andric for (idx = 0; idx < num_threads; ++idx) {
147435933ddSDimitry Andric if (m_threads[idx]->GetID() == tid) {
148ac7ddfbfSEd Maste thread_sp = m_threads[idx];
149ac7ddfbfSEd Maste m_threads.erase(m_threads.begin() + idx);
150ac7ddfbfSEd Maste break;
151ac7ddfbfSEd Maste }
152ac7ddfbfSEd Maste }
153ac7ddfbfSEd Maste return thread_sp;
154ac7ddfbfSEd Maste }
155ac7ddfbfSEd Maste
RemoveThreadByProtocolID(lldb::tid_t tid,bool can_update)156435933ddSDimitry Andric ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid,
157435933ddSDimitry Andric bool can_update) {
1584bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
159ac7ddfbfSEd Maste
160ac7ddfbfSEd Maste if (can_update)
161ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
162ac7ddfbfSEd Maste
163ac7ddfbfSEd Maste ThreadSP thread_sp;
164ac7ddfbfSEd Maste uint32_t idx = 0;
165ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
166435933ddSDimitry Andric for (idx = 0; idx < num_threads; ++idx) {
167435933ddSDimitry Andric if (m_threads[idx]->GetProtocolID() == tid) {
168ac7ddfbfSEd Maste thread_sp = m_threads[idx];
169ac7ddfbfSEd Maste m_threads.erase(m_threads.begin() + idx);
170ac7ddfbfSEd Maste break;
171ac7ddfbfSEd Maste }
172ac7ddfbfSEd Maste }
173ac7ddfbfSEd Maste return thread_sp;
174ac7ddfbfSEd Maste }
175ac7ddfbfSEd Maste
GetThreadSPForThreadPtr(Thread * thread_ptr)176435933ddSDimitry Andric ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
177ac7ddfbfSEd Maste ThreadSP thread_sp;
178435933ddSDimitry Andric if (thread_ptr) {
1794bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
180ac7ddfbfSEd Maste
181ac7ddfbfSEd Maste uint32_t idx = 0;
182ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
183435933ddSDimitry Andric for (idx = 0; idx < num_threads; ++idx) {
184435933ddSDimitry Andric if (m_threads[idx].get() == thread_ptr) {
185ac7ddfbfSEd Maste thread_sp = m_threads[idx];
186ac7ddfbfSEd Maste break;
187ac7ddfbfSEd Maste }
188ac7ddfbfSEd Maste }
189ac7ddfbfSEd Maste }
190ac7ddfbfSEd Maste return thread_sp;
191ac7ddfbfSEd Maste }
192ac7ddfbfSEd Maste
GetBackingThread(const ThreadSP & real_thread)1934ba319b5SDimitry Andric ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) {
1944ba319b5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetMutex());
1954ba319b5SDimitry Andric
1964ba319b5SDimitry Andric ThreadSP thread_sp;
1974ba319b5SDimitry Andric const uint32_t num_threads = m_threads.size();
1984ba319b5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
1994ba319b5SDimitry Andric if (m_threads[idx]->GetBackingThread() == real_thread) {
2004ba319b5SDimitry Andric thread_sp = m_threads[idx];
2014ba319b5SDimitry Andric break;
2024ba319b5SDimitry Andric }
2034ba319b5SDimitry Andric }
2044ba319b5SDimitry Andric return thread_sp;
2054ba319b5SDimitry Andric }
2064ba319b5SDimitry Andric
FindThreadByIndexID(uint32_t index_id,bool can_update)207435933ddSDimitry Andric ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
2084bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
209ac7ddfbfSEd Maste
210ac7ddfbfSEd Maste if (can_update)
211ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
212ac7ddfbfSEd Maste
213ac7ddfbfSEd Maste ThreadSP thread_sp;
214ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
215435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
216435933ddSDimitry Andric if (m_threads[idx]->GetIndexID() == index_id) {
217ac7ddfbfSEd Maste thread_sp = m_threads[idx];
218ac7ddfbfSEd Maste break;
219ac7ddfbfSEd Maste }
220ac7ddfbfSEd Maste }
221ac7ddfbfSEd Maste return thread_sp;
222ac7ddfbfSEd Maste }
223ac7ddfbfSEd Maste
ShouldStop(Event * event_ptr)224435933ddSDimitry Andric bool ThreadList::ShouldStop(Event *event_ptr) {
225ac7ddfbfSEd Maste // Running events should never stop, obviously...
226ac7ddfbfSEd Maste
227ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
228ac7ddfbfSEd Maste
2294ba319b5SDimitry Andric // The ShouldStop method of the threads can do a whole lot of work, figuring
2304ba319b5SDimitry Andric // out whether the thread plan conditions are met. So we don't want to keep
2314ba319b5SDimitry Andric // the ThreadList locked the whole time we are doing this.
232ac7ddfbfSEd Maste // FIXME: It is possible that running code could cause new threads
2334ba319b5SDimitry Andric // to be created. If that happens, we will miss asking them whether they
2344ba319b5SDimitry Andric // should stop. This is not a big deal since we haven't had a chance to hang
2354ba319b5SDimitry Andric // any interesting operations on those threads yet.
236ac7ddfbfSEd Maste
237ac7ddfbfSEd Maste collection threads_copy;
238ac7ddfbfSEd Maste {
239ac7ddfbfSEd Maste // Scope for locker
2404bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
241ac7ddfbfSEd Maste
242ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
243435933ddSDimitry Andric for (lldb::ThreadSP thread_sp : m_threads) {
244435933ddSDimitry Andric // This is an optimization... If we didn't let a thread run in between
2454ba319b5SDimitry Andric // the previous stop and this one, we shouldn't have to consult it for
2464ba319b5SDimitry Andric // ShouldStop. So just leave it off the list we are going to inspect. On
2474ba319b5SDimitry Andric // Linux, if a thread-specific conditional breakpoint was hit, it won't
2484ba319b5SDimitry Andric // necessarily be the thread that hit the breakpoint itself that
2494ba319b5SDimitry Andric // evaluates the conditional expression, so the thread that hit the
2504ba319b5SDimitry Andric // breakpoint could still be asked to stop, even though it hasn't been
2514ba319b5SDimitry Andric // allowed to run since the previous stop.
252435933ddSDimitry Andric if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
253435933ddSDimitry Andric thread_sp->IsStillAtLastBreakpointHit())
2549f2f44ceSEd Maste threads_copy.push_back(thread_sp);
2559f2f44ceSEd Maste }
2569f2f44ceSEd Maste
257435933ddSDimitry Andric // It is possible the threads we were allowing to run all exited and then
2584ba319b5SDimitry Andric // maybe the user interrupted or something, then fall back on looking at
2594ba319b5SDimitry Andric // all threads:
2609f2f44ceSEd Maste
2619f2f44ceSEd Maste if (threads_copy.size() == 0)
262ac7ddfbfSEd Maste threads_copy = m_threads;
263ac7ddfbfSEd Maste }
264ac7ddfbfSEd Maste
265ac7ddfbfSEd Maste collection::iterator pos, end = threads_copy.end();
266ac7ddfbfSEd Maste
267435933ddSDimitry Andric if (log) {
268ac7ddfbfSEd Maste log->PutCString("");
269435933ddSDimitry Andric log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64
270435933ddSDimitry Andric " unsuspended threads",
271435933ddSDimitry Andric __FUNCTION__, (uint64_t)m_threads.size(),
2729f2f44ceSEd Maste (uint64_t)threads_copy.size());
273ac7ddfbfSEd Maste }
274ac7ddfbfSEd Maste
275ac7ddfbfSEd Maste bool did_anybody_stop_for_a_reason = false;
2760127ef0fSEd Maste
277435933ddSDimitry Andric // If the event is an Interrupt event, then we're going to stop no matter
278435933ddSDimitry Andric // what. Otherwise, presume we won't stop.
279ac7ddfbfSEd Maste bool should_stop = false;
280435933ddSDimitry Andric if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
2810127ef0fSEd Maste if (log)
282435933ddSDimitry Andric log->Printf(
283435933ddSDimitry Andric "ThreadList::%s handling interrupt event, should stop set to true",
284435933ddSDimitry Andric __FUNCTION__);
2850127ef0fSEd Maste
2860127ef0fSEd Maste should_stop = true;
2870127ef0fSEd Maste }
288ac7ddfbfSEd Maste
289435933ddSDimitry Andric // Now we run through all the threads and get their stop info's. We want to
2904ba319b5SDimitry Andric // make sure to do this first before we start running the ShouldStop, because
2914ba319b5SDimitry Andric // one thread's ShouldStop could destroy information (like deleting a thread
2924ba319b5SDimitry Andric // specific breakpoint another thread had stopped at) which could lead us to
2934ba319b5SDimitry Andric // compute the StopInfo incorrectly. We don't need to use it here, we just
2944ba319b5SDimitry Andric // want to make sure it gets computed.
295ac7ddfbfSEd Maste
296435933ddSDimitry Andric for (pos = threads_copy.begin(); pos != end; ++pos) {
297ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
298ac7ddfbfSEd Maste thread_sp->GetStopInfo();
299ac7ddfbfSEd Maste }
300ac7ddfbfSEd Maste
301435933ddSDimitry Andric for (pos = threads_copy.begin(); pos != end; ++pos) {
302ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
303ac7ddfbfSEd Maste
304435933ddSDimitry Andric // We should never get a stop for which no thread had a stop reason, but
3054ba319b5SDimitry Andric // sometimes we do see this - for instance when we first connect to a
3064ba319b5SDimitry Andric // remote stub. In that case we should stop, since we can't figure out the
3074ba319b5SDimitry Andric // right thing to do and stopping gives the user control over what to do in
3084ba319b5SDimitry Andric // this instance.
30912b93ac6SEd Maste //
310435933ddSDimitry Andric // Note, this causes a problem when you have a thread specific breakpoint,
3114ba319b5SDimitry Andric // and a bunch of threads hit the breakpoint, but not the thread which we
3124ba319b5SDimitry Andric // are waiting for. All the threads that are not "supposed" to hit the
3134ba319b5SDimitry Andric // breakpoint are marked as having no stop reason, which is right, they
3144ba319b5SDimitry Andric // should not show a stop reason. But that triggers this code and causes
3154ba319b5SDimitry Andric // us to stop seemingly for no reason.
31612b93ac6SEd Maste //
317435933ddSDimitry Andric // Since the only way we ever saw this error was on first attach, I'm only
3184ba319b5SDimitry Andric // going to trigger set did_anybody_stop_for_a_reason to true unless this
3194ba319b5SDimitry Andric // is the first stop.
32012b93ac6SEd Maste //
321435933ddSDimitry Andric // If this becomes a problem, we'll have to have another StopReason like
3224ba319b5SDimitry Andric // "StopInfoHidden" which will look invalid everywhere but at this check.
32312b93ac6SEd Maste
32412b93ac6SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1)
32512b93ac6SEd Maste did_anybody_stop_for_a_reason = true;
32612b93ac6SEd Maste else
327ac7ddfbfSEd Maste did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
328ac7ddfbfSEd Maste
329ac7ddfbfSEd Maste const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
330ac7ddfbfSEd Maste if (thread_should_stop)
331ac7ddfbfSEd Maste should_stop |= true;
332ac7ddfbfSEd Maste }
333ac7ddfbfSEd Maste
334435933ddSDimitry Andric if (!should_stop && !did_anybody_stop_for_a_reason) {
335ac7ddfbfSEd Maste should_stop = true;
336ac7ddfbfSEd Maste if (log)
337435933ddSDimitry Andric log->Printf("ThreadList::%s we stopped but no threads had a stop reason, "
338435933ddSDimitry Andric "overriding should_stop and stopping.",
339435933ddSDimitry Andric __FUNCTION__);
340ac7ddfbfSEd Maste }
341ac7ddfbfSEd Maste
342ac7ddfbfSEd Maste if (log)
343435933ddSDimitry Andric log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__,
344435933ddSDimitry Andric should_stop);
345ac7ddfbfSEd Maste
346435933ddSDimitry Andric if (should_stop) {
347435933ddSDimitry Andric for (pos = threads_copy.begin(); pos != end; ++pos) {
348ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
349ac7ddfbfSEd Maste thread_sp->WillStop();
350ac7ddfbfSEd Maste }
351ac7ddfbfSEd Maste }
352ac7ddfbfSEd Maste
353ac7ddfbfSEd Maste return should_stop;
354ac7ddfbfSEd Maste }
355ac7ddfbfSEd Maste
ShouldReportStop(Event * event_ptr)356435933ddSDimitry Andric Vote ThreadList::ShouldReportStop(Event *event_ptr) {
3574bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
358ac7ddfbfSEd Maste
359ac7ddfbfSEd Maste Vote result = eVoteNoOpinion;
360ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
361ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
362ac7ddfbfSEd Maste
363ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
364ac7ddfbfSEd Maste
365ac7ddfbfSEd Maste if (log)
366435933ddSDimitry Andric log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
367435933ddSDimitry Andric (uint64_t)m_threads.size());
368ac7ddfbfSEd Maste
3694ba319b5SDimitry Andric // Run through the threads and ask whether we should report this event. For
3704ba319b5SDimitry Andric // stopping, a YES vote wins over everything. A NO vote wins over NO
371435933ddSDimitry Andric // opinion.
372435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
373ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
374ac7ddfbfSEd Maste const Vote vote = thread_sp->ShouldReportStop(event_ptr);
375435933ddSDimitry Andric switch (vote) {
376ac7ddfbfSEd Maste case eVoteNoOpinion:
377ac7ddfbfSEd Maste continue;
378ac7ddfbfSEd Maste
379ac7ddfbfSEd Maste case eVoteYes:
380ac7ddfbfSEd Maste result = eVoteYes;
381ac7ddfbfSEd Maste break;
382ac7ddfbfSEd Maste
383ac7ddfbfSEd Maste case eVoteNo:
384435933ddSDimitry Andric if (result == eVoteNoOpinion) {
385ac7ddfbfSEd Maste result = eVoteNo;
386435933ddSDimitry Andric } else {
387f678e45dSDimitry Andric LLDB_LOG(log,
388f678e45dSDimitry Andric "Thread {0:x} voted {1}, but lost out because result was {2}",
389f678e45dSDimitry Andric thread_sp->GetID(), vote, result);
390ac7ddfbfSEd Maste }
391ac7ddfbfSEd Maste break;
392ac7ddfbfSEd Maste }
393ac7ddfbfSEd Maste }
394f678e45dSDimitry Andric LLDB_LOG(log, "Returning {0}", result);
395ac7ddfbfSEd Maste return result;
396ac7ddfbfSEd Maste }
397ac7ddfbfSEd Maste
SetShouldReportStop(Vote vote)398435933ddSDimitry Andric void ThreadList::SetShouldReportStop(Vote vote) {
3994bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
4004bb0738eSEd Maste
401ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
402ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
403435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
404ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
405ac7ddfbfSEd Maste thread_sp->SetShouldReportStop(vote);
406ac7ddfbfSEd Maste }
407ac7ddfbfSEd Maste }
408ac7ddfbfSEd Maste
ShouldReportRun(Event * event_ptr)409435933ddSDimitry Andric Vote ThreadList::ShouldReportRun(Event *event_ptr) {
410ac7ddfbfSEd Maste
4114bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
412ac7ddfbfSEd Maste
413ac7ddfbfSEd Maste Vote result = eVoteNoOpinion;
414ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
415ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
416ac7ddfbfSEd Maste
4174ba319b5SDimitry Andric // Run through the threads and ask whether we should report this event. The
4184ba319b5SDimitry Andric // rule is NO vote wins over everything, a YES vote wins over no opinion.
419ac7ddfbfSEd Maste
420ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
421ac7ddfbfSEd Maste
422435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
423435933ddSDimitry Andric if ((*pos)->GetResumeState() != eStateSuspended) {
424435933ddSDimitry Andric switch ((*pos)->ShouldReportRun(event_ptr)) {
425ac7ddfbfSEd Maste case eVoteNoOpinion:
426ac7ddfbfSEd Maste continue;
427ac7ddfbfSEd Maste case eVoteYes:
428ac7ddfbfSEd Maste if (result == eVoteNoOpinion)
429ac7ddfbfSEd Maste result = eVoteYes;
430ac7ddfbfSEd Maste break;
431ac7ddfbfSEd Maste case eVoteNo:
432ac7ddfbfSEd Maste if (log)
433435933ddSDimitry Andric log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64
434435933ddSDimitry Andric ") says don't report.",
435435933ddSDimitry Andric (*pos)->GetIndexID(), (*pos)->GetID());
436ac7ddfbfSEd Maste result = eVoteNo;
437ac7ddfbfSEd Maste break;
438ac7ddfbfSEd Maste }
439ac7ddfbfSEd Maste }
440ac7ddfbfSEd Maste }
441ac7ddfbfSEd Maste return result;
442ac7ddfbfSEd Maste }
443ac7ddfbfSEd Maste
Clear()444435933ddSDimitry Andric void ThreadList::Clear() {
4454bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
446ac7ddfbfSEd Maste m_stop_id = 0;
447ac7ddfbfSEd Maste m_threads.clear();
448ac7ddfbfSEd Maste m_selected_tid = LLDB_INVALID_THREAD_ID;
449ac7ddfbfSEd Maste }
450ac7ddfbfSEd Maste
Destroy()451435933ddSDimitry Andric void ThreadList::Destroy() {
4524bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
453ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
454435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
455ac7ddfbfSEd Maste m_threads[idx]->DestroyThread();
456ac7ddfbfSEd Maste }
457ac7ddfbfSEd Maste }
458ac7ddfbfSEd Maste
RefreshStateAfterStop()459435933ddSDimitry Andric void ThreadList::RefreshStateAfterStop() {
4604bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
461ac7ddfbfSEd Maste
462ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
463ac7ddfbfSEd Maste
464ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
465ac7ddfbfSEd Maste if (log && log->GetVerbose())
466435933ddSDimitry Andric log->Printf("Turning off notification of new threads while single stepping "
467435933ddSDimitry Andric "a thread.");
468ac7ddfbfSEd Maste
469ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
470ac7ddfbfSEd Maste for (pos = m_threads.begin(); pos != end; ++pos)
471ac7ddfbfSEd Maste (*pos)->RefreshStateAfterStop();
472ac7ddfbfSEd Maste }
473ac7ddfbfSEd Maste
DiscardThreadPlans()474435933ddSDimitry Andric void ThreadList::DiscardThreadPlans() {
4754ba319b5SDimitry Andric // You don't need to update the thread list here, because only threads that
4764ba319b5SDimitry Andric // you currently know about have any thread plans.
4774bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
478ac7ddfbfSEd Maste
479ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
480ac7ddfbfSEd Maste for (pos = m_threads.begin(); pos != end; ++pos)
481ac7ddfbfSEd Maste (*pos)->DiscardThreadPlans(true);
482ac7ddfbfSEd Maste }
483ac7ddfbfSEd Maste
WillResume()484435933ddSDimitry Andric bool ThreadList::WillResume() {
4854ba319b5SDimitry Andric // Run through the threads and perform their momentary actions. But we only
4864ba319b5SDimitry Andric // do this for threads that are running, user suspended threads stay where
4874ba319b5SDimitry Andric // they are.
488ac7ddfbfSEd Maste
4894bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
490ac7ddfbfSEd Maste m_process->UpdateThreadListIfNeeded();
491ac7ddfbfSEd Maste
492ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
493ac7ddfbfSEd Maste
494ac7ddfbfSEd Maste // See if any thread wants to run stopping others. If it does, then we won't
4954ba319b5SDimitry Andric // setup the other threads for resume, since they aren't going to get a
4964ba319b5SDimitry Andric // chance to run. This is necessary because the SetupForResume might add
4974ba319b5SDimitry Andric // "StopOthers" plans which would then get to be part of the who-gets-to-run
4984ba319b5SDimitry Andric // negotiation, but they're coming in after the fact, and the threads that
4994ba319b5SDimitry Andric // are already set up should take priority.
500ac7ddfbfSEd Maste
501ac7ddfbfSEd Maste bool wants_solo_run = false;
502ac7ddfbfSEd Maste
503435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
504435933ddSDimitry Andric lldbassert((*pos)->GetCurrentPlan() &&
505435933ddSDimitry Andric "thread should not have null thread plan");
506ac7ddfbfSEd Maste if ((*pos)->GetResumeState() != eStateSuspended &&
507435933ddSDimitry Andric (*pos)->GetCurrentPlan()->StopOthers()) {
508435933ddSDimitry Andric if ((*pos)->IsOperatingSystemPluginThread() &&
509435933ddSDimitry Andric !(*pos)->GetBackingThread())
510ac7ddfbfSEd Maste continue;
511ac7ddfbfSEd Maste wants_solo_run = true;
512ac7ddfbfSEd Maste break;
513ac7ddfbfSEd Maste }
514ac7ddfbfSEd Maste }
515ac7ddfbfSEd Maste
516435933ddSDimitry Andric if (wants_solo_run) {
517ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
518ac7ddfbfSEd Maste if (log && log->GetVerbose())
519435933ddSDimitry Andric log->Printf("Turning on notification of new threads while single "
520435933ddSDimitry Andric "stepping a thread.");
521ac7ddfbfSEd Maste m_process->StartNoticingNewThreads();
522435933ddSDimitry Andric } else {
523ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
524ac7ddfbfSEd Maste if (log && log->GetVerbose())
525435933ddSDimitry Andric log->Printf("Turning off notification of new threads while single "
526435933ddSDimitry Andric "stepping a thread.");
527ac7ddfbfSEd Maste m_process->StopNoticingNewThreads();
528ac7ddfbfSEd Maste }
529ac7ddfbfSEd Maste
530435933ddSDimitry Andric // Give all the threads that are likely to run a last chance to set up their
5314ba319b5SDimitry Andric // state before we negotiate who is actually going to get a chance to run...
532435933ddSDimitry Andric // Don't set to resume suspended threads, and if any thread wanted to stop
5334ba319b5SDimitry Andric // others, only call setup on the threads that request StopOthers...
534ac7ddfbfSEd Maste
535435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
536435933ddSDimitry Andric if ((*pos)->GetResumeState() != eStateSuspended &&
537435933ddSDimitry Andric (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) {
538435933ddSDimitry Andric if ((*pos)->IsOperatingSystemPluginThread() &&
539435933ddSDimitry Andric !(*pos)->GetBackingThread())
540ac7ddfbfSEd Maste continue;
541ac7ddfbfSEd Maste (*pos)->SetupForResume();
542ac7ddfbfSEd Maste }
543ac7ddfbfSEd Maste }
544ac7ddfbfSEd Maste
545ac7ddfbfSEd Maste // Now go through the threads and see if any thread wants to run just itself.
546ac7ddfbfSEd Maste // if so then pick one and run it.
547ac7ddfbfSEd Maste
548ac7ddfbfSEd Maste ThreadList run_me_only_list(m_process);
549ac7ddfbfSEd Maste
550ac7ddfbfSEd Maste run_me_only_list.SetStopID(m_process->GetStopID());
551ac7ddfbfSEd Maste
552ac7ddfbfSEd Maste bool run_only_current_thread = false;
553ac7ddfbfSEd Maste
554435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
555ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
556ac7ddfbfSEd Maste if (thread_sp->GetResumeState() != eStateSuspended &&
557435933ddSDimitry Andric thread_sp->GetCurrentPlan()->StopOthers()) {
558435933ddSDimitry Andric if ((*pos)->IsOperatingSystemPluginThread() &&
559435933ddSDimitry Andric !(*pos)->GetBackingThread())
560ac7ddfbfSEd Maste continue;
561ac7ddfbfSEd Maste
562ac7ddfbfSEd Maste // You can't say "stop others" and also want yourself to be suspended.
563ac7ddfbfSEd Maste assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
564ac7ddfbfSEd Maste
565435933ddSDimitry Andric if (thread_sp == GetSelectedThread()) {
566435933ddSDimitry Andric // If the currently selected thread wants to run on its own, always let
567435933ddSDimitry Andric // it.
568ac7ddfbfSEd Maste run_only_current_thread = true;
569ac7ddfbfSEd Maste run_me_only_list.Clear();
570ac7ddfbfSEd Maste run_me_only_list.AddThread(thread_sp);
571ac7ddfbfSEd Maste break;
572ac7ddfbfSEd Maste }
573ac7ddfbfSEd Maste
574ac7ddfbfSEd Maste run_me_only_list.AddThread(thread_sp);
575ac7ddfbfSEd Maste }
576ac7ddfbfSEd Maste }
577ac7ddfbfSEd Maste
578ac7ddfbfSEd Maste bool need_to_resume = true;
579ac7ddfbfSEd Maste
580435933ddSDimitry Andric if (run_me_only_list.GetSize(false) == 0) {
581ac7ddfbfSEd Maste // Everybody runs as they wish:
582435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
583ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
584ac7ddfbfSEd Maste StateType run_state;
585ac7ddfbfSEd Maste if (thread_sp->GetResumeState() != eStateSuspended)
586ac7ddfbfSEd Maste run_state = thread_sp->GetCurrentPlan()->RunState();
587ac7ddfbfSEd Maste else
588ac7ddfbfSEd Maste run_state = eStateSuspended;
589ac7ddfbfSEd Maste if (!thread_sp->ShouldResume(run_state))
590ac7ddfbfSEd Maste need_to_resume = false;
591ac7ddfbfSEd Maste }
592435933ddSDimitry Andric } else {
593ac7ddfbfSEd Maste ThreadSP thread_to_run;
594ac7ddfbfSEd Maste
595435933ddSDimitry Andric if (run_only_current_thread) {
596ac7ddfbfSEd Maste thread_to_run = GetSelectedThread();
597435933ddSDimitry Andric } else if (run_me_only_list.GetSize(false) == 1) {
598ac7ddfbfSEd Maste thread_to_run = run_me_only_list.GetThreadAtIndex(0);
599435933ddSDimitry Andric } else {
600435933ddSDimitry Andric int random_thread =
601435933ddSDimitry Andric (int)((run_me_only_list.GetSize(false) * (double)rand()) /
602435933ddSDimitry Andric (RAND_MAX + 1.0));
603ac7ddfbfSEd Maste thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
604ac7ddfbfSEd Maste }
605ac7ddfbfSEd Maste
606435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
607ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
608435933ddSDimitry Andric if (thread_sp == thread_to_run) {
609ac7ddfbfSEd Maste if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
610ac7ddfbfSEd Maste need_to_resume = false;
611435933ddSDimitry Andric } else
612ac7ddfbfSEd Maste thread_sp->ShouldResume(eStateSuspended);
613ac7ddfbfSEd Maste }
614ac7ddfbfSEd Maste }
615ac7ddfbfSEd Maste
616ac7ddfbfSEd Maste return need_to_resume;
617ac7ddfbfSEd Maste }
618ac7ddfbfSEd Maste
DidResume()619435933ddSDimitry Andric void ThreadList::DidResume() {
6204bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
621ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
622435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
623ac7ddfbfSEd Maste // Don't clear out threads that aren't going to get a chance to run, rather
624ac7ddfbfSEd Maste // leave their state for the next time around.
625ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
626ac7ddfbfSEd Maste if (thread_sp->GetResumeState() != eStateSuspended)
627ac7ddfbfSEd Maste thread_sp->DidResume();
628ac7ddfbfSEd Maste }
629ac7ddfbfSEd Maste }
630ac7ddfbfSEd Maste
DidStop()631435933ddSDimitry Andric void ThreadList::DidStop() {
6324bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
633ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
634435933ddSDimitry Andric for (pos = m_threads.begin(); pos != end; ++pos) {
6354ba319b5SDimitry Andric // Notify threads that the process just stopped. Note, this currently
6364ba319b5SDimitry Andric // assumes that all threads in the list stop when the process stops. In
6374ba319b5SDimitry Andric // the future we will want to support a debugging model where some threads
6384ba319b5SDimitry Andric // continue to run while others are stopped. We either need to handle that
6394ba319b5SDimitry Andric // somehow here or create a special thread list containing only threads
6404ba319b5SDimitry Andric // which will stop in the code that calls this method (currently
641ac7ddfbfSEd Maste // Process::SetPrivateState).
642ac7ddfbfSEd Maste ThreadSP thread_sp(*pos);
643ac7ddfbfSEd Maste if (StateIsRunningState(thread_sp->GetState()))
644ac7ddfbfSEd Maste thread_sp->DidStop();
645ac7ddfbfSEd Maste }
646ac7ddfbfSEd Maste }
647ac7ddfbfSEd Maste
GetSelectedThread()648435933ddSDimitry Andric ThreadSP ThreadList::GetSelectedThread() {
6494bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
650ac7ddfbfSEd Maste ThreadSP thread_sp = FindThreadByID(m_selected_tid);
651435933ddSDimitry Andric if (!thread_sp.get()) {
652ac7ddfbfSEd Maste if (m_threads.size() == 0)
653ac7ddfbfSEd Maste return thread_sp;
654ac7ddfbfSEd Maste m_selected_tid = m_threads[0]->GetID();
655ac7ddfbfSEd Maste thread_sp = m_threads[0];
656ac7ddfbfSEd Maste }
657ac7ddfbfSEd Maste return thread_sp;
658ac7ddfbfSEd Maste }
659ac7ddfbfSEd Maste
SetSelectedThreadByID(lldb::tid_t tid,bool notify)660435933ddSDimitry Andric bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) {
6614bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
662ac7ddfbfSEd Maste ThreadSP selected_thread_sp(FindThreadByID(tid));
663435933ddSDimitry Andric if (selected_thread_sp) {
664ac7ddfbfSEd Maste m_selected_tid = tid;
665ac7ddfbfSEd Maste selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
666435933ddSDimitry Andric } else
667ac7ddfbfSEd Maste m_selected_tid = LLDB_INVALID_THREAD_ID;
668ac7ddfbfSEd Maste
669ac7ddfbfSEd Maste if (notify)
670ac7ddfbfSEd Maste NotifySelectedThreadChanged(m_selected_tid);
671ac7ddfbfSEd Maste
672ac7ddfbfSEd Maste return m_selected_tid != LLDB_INVALID_THREAD_ID;
673ac7ddfbfSEd Maste }
674ac7ddfbfSEd Maste
SetSelectedThreadByIndexID(uint32_t index_id,bool notify)675435933ddSDimitry Andric bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) {
6764bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
677ac7ddfbfSEd Maste ThreadSP selected_thread_sp(FindThreadByIndexID(index_id));
678435933ddSDimitry Andric if (selected_thread_sp.get()) {
679ac7ddfbfSEd Maste m_selected_tid = selected_thread_sp->GetID();
680ac7ddfbfSEd Maste selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
681435933ddSDimitry Andric } else
682ac7ddfbfSEd Maste m_selected_tid = LLDB_INVALID_THREAD_ID;
683ac7ddfbfSEd Maste
684ac7ddfbfSEd Maste if (notify)
685ac7ddfbfSEd Maste NotifySelectedThreadChanged(m_selected_tid);
686ac7ddfbfSEd Maste
687ac7ddfbfSEd Maste return m_selected_tid != LLDB_INVALID_THREAD_ID;
688ac7ddfbfSEd Maste }
689ac7ddfbfSEd Maste
NotifySelectedThreadChanged(lldb::tid_t tid)690435933ddSDimitry Andric void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
691ac7ddfbfSEd Maste ThreadSP selected_thread_sp(FindThreadByID(tid));
692435933ddSDimitry Andric if (selected_thread_sp->EventTypeHasListeners(
693435933ddSDimitry Andric Thread::eBroadcastBitThreadSelected))
694435933ddSDimitry Andric selected_thread_sp->BroadcastEvent(
695435933ddSDimitry Andric Thread::eBroadcastBitThreadSelected,
696ac7ddfbfSEd Maste new Thread::ThreadEventData(selected_thread_sp));
697ac7ddfbfSEd Maste }
698ac7ddfbfSEd Maste
Update(ThreadList & rhs)699435933ddSDimitry Andric void ThreadList::Update(ThreadList &rhs) {
700435933ddSDimitry Andric if (this != &rhs) {
7014ba319b5SDimitry Andric // Lock both mutexes to make sure neither side changes anyone on us while
7024ba319b5SDimitry Andric // the assignment occurs
7034bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
7044bb0738eSEd Maste
705ac7ddfbfSEd Maste m_process = rhs.m_process;
706ac7ddfbfSEd Maste m_stop_id = rhs.m_stop_id;
707ac7ddfbfSEd Maste m_threads.swap(rhs.m_threads);
708ac7ddfbfSEd Maste m_selected_tid = rhs.m_selected_tid;
709ac7ddfbfSEd Maste
7104ba319b5SDimitry Andric // Now we look for threads that we are done with and make sure to clear
7114ba319b5SDimitry Andric // them up as much as possible so anyone with a shared pointer will still
7124ba319b5SDimitry Andric // have a reference, but the thread won't be of much use. Using
7134ba319b5SDimitry Andric // std::weak_ptr for all backward references (such as a thread to a
7144ba319b5SDimitry Andric // process) will eventually solve this issue for us, but for now, we need
7154ba319b5SDimitry Andric // to work around the issue
716ac7ddfbfSEd Maste collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
717435933ddSDimitry Andric for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
718ac7ddfbfSEd Maste const lldb::tid_t tid = (*rhs_pos)->GetID();
719ac7ddfbfSEd Maste bool thread_is_alive = false;
720ac7ddfbfSEd Maste const uint32_t num_threads = m_threads.size();
721435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
7229f2f44ceSEd Maste ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
723435933ddSDimitry Andric if (m_threads[idx]->GetID() == tid ||
724435933ddSDimitry Andric (backing_thread && backing_thread->GetID() == tid)) {
725ac7ddfbfSEd Maste thread_is_alive = true;
726ac7ddfbfSEd Maste break;
727ac7ddfbfSEd Maste }
728ac7ddfbfSEd Maste }
729ac7ddfbfSEd Maste if (!thread_is_alive)
730ac7ddfbfSEd Maste (*rhs_pos)->DestroyThread();
731ac7ddfbfSEd Maste }
732ac7ddfbfSEd Maste }
733ac7ddfbfSEd Maste }
734ac7ddfbfSEd Maste
Flush()735435933ddSDimitry Andric void ThreadList::Flush() {
7364bb0738eSEd Maste std::lock_guard<std::recursive_mutex> guard(GetMutex());
737ac7ddfbfSEd Maste collection::iterator pos, end = m_threads.end();
738ac7ddfbfSEd Maste for (pos = m_threads.begin(); pos != end; ++pos)
739ac7ddfbfSEd Maste (*pos)->Flush();
740ac7ddfbfSEd Maste }
741ac7ddfbfSEd Maste
GetMutex() const742435933ddSDimitry Andric std::recursive_mutex &ThreadList::GetMutex() const {
743ac7ddfbfSEd Maste return m_process->m_thread_mutex;
744ac7ddfbfSEd Maste }
745ac7ddfbfSEd Maste
ExpressionExecutionThreadPusher(lldb::ThreadSP thread_sp)746435933ddSDimitry Andric ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher(
747435933ddSDimitry Andric lldb::ThreadSP thread_sp)
748435933ddSDimitry Andric : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) {
749435933ddSDimitry Andric if (thread_sp) {
7504bb0738eSEd Maste m_tid = thread_sp->GetID();
7514bb0738eSEd Maste m_thread_list = &thread_sp->GetProcess()->GetThreadList();
7524bb0738eSEd Maste m_thread_list->PushExpressionExecutionThread(m_tid);
7534bb0738eSEd Maste }
7544bb0738eSEd Maste }
755