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