130fdc8d8SChris Lattner //===-- ThreadList.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9e65b2cf2SEugene Zelenko 
10e65b2cf2SEugene Zelenko // C Includes
1130fdc8d8SChris Lattner #include <stdlib.h>
1230fdc8d8SChris Lattner 
13e65b2cf2SEugene Zelenko // C++ Includes
1430fdc8d8SChris Lattner #include <algorithm>
1530fdc8d8SChris Lattner 
16e65b2cf2SEugene Zelenko // Other libraries and framework includes
17e65b2cf2SEugene Zelenko // Project includes
1829d65744SAndrew Kaylor #include "lldb/Core/State.h"
1930fdc8d8SChris Lattner #include "lldb/Target/Process.h"
20b9c1b51eSKate Stone #include "lldb/Target/RegisterContext.h"
21b9c1b51eSKate Stone #include "lldb/Target/Thread.h"
22b9c1b51eSKate Stone #include "lldb/Target/ThreadList.h"
23b9c1b51eSKate Stone #include "lldb/Target/ThreadPlan.h"
248f186f85SZachary Turner #include "lldb/Utility/LLDBAssert.h"
25*6f9e6901SZachary Turner #include "lldb/Utility/Log.h"
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
2930fdc8d8SChris Lattner 
30b9c1b51eSKate Stone ThreadList::ThreadList(Process *process)
31b9c1b51eSKate Stone     : ThreadCollection(), m_process(process), m_stop_id(0),
32b9c1b51eSKate Stone       m_selected_tid(LLDB_INVALID_THREAD_ID) {}
3330fdc8d8SChris Lattner 
34b9c1b51eSKate Stone ThreadList::ThreadList(const ThreadList &rhs)
35b9c1b51eSKate Stone     : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id),
36b9c1b51eSKate Stone       m_selected_tid() {
3730fdc8d8SChris Lattner   // Use the assignment operator since it uses the mutex
3830fdc8d8SChris Lattner   *this = rhs;
3930fdc8d8SChris Lattner }
4030fdc8d8SChris Lattner 
41b9c1b51eSKate Stone const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
42b9c1b51eSKate Stone   if (this != &rhs) {
4330fdc8d8SChris Lattner     // Lock both mutexes to make sure neither side changes anyone on us
44e171da5cSBruce Mitchener     // while the assignment occurs
45bb19a13cSSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(GetMutex());
46b5cd6e7bSGreg Clayton     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex());
47bb19a13cSSaleem Abdulrasool 
4830fdc8d8SChris Lattner     m_process = rhs.m_process;
4930fdc8d8SChris Lattner     m_stop_id = rhs.m_stop_id;
5030fdc8d8SChris Lattner     m_threads = rhs.m_threads;
512976d00aSJim Ingham     m_selected_tid = rhs.m_selected_tid;
5230fdc8d8SChris Lattner   }
5330fdc8d8SChris Lattner   return *this;
5430fdc8d8SChris Lattner }
5530fdc8d8SChris Lattner 
56b9c1b51eSKate Stone ThreadList::~ThreadList() {
57ac358da5SGreg Clayton   // Clear the thread list. Clear will take the mutex lock
58ac358da5SGreg Clayton   // which will ensure that if anyone is using the list
59ac358da5SGreg Clayton   // they won't get it removed while using it.
60ac358da5SGreg Clayton   Clear();
6130fdc8d8SChris Lattner }
6230fdc8d8SChris Lattner 
63b9c1b51eSKate Stone lldb::ThreadSP ThreadList::GetExpressionExecutionThread() {
648d94ba0fSJim Ingham   if (m_expression_tid_stack.empty())
658d94ba0fSJim Ingham     return GetSelectedThread();
668d94ba0fSJim Ingham   ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back());
678d94ba0fSJim Ingham   if (expr_thread_sp)
688d94ba0fSJim Ingham     return expr_thread_sp;
698d94ba0fSJim Ingham   else
708d94ba0fSJim Ingham     return GetSelectedThread();
718d94ba0fSJim Ingham }
728d94ba0fSJim Ingham 
73b9c1b51eSKate Stone void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) {
748d94ba0fSJim Ingham   m_expression_tid_stack.push_back(tid);
758d94ba0fSJim Ingham }
768d94ba0fSJim Ingham 
77b9c1b51eSKate Stone void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) {
788d94ba0fSJim Ingham   assert(m_expression_tid_stack.back() == tid);
798d94ba0fSJim Ingham   m_expression_tid_stack.pop_back();
808d94ba0fSJim Ingham }
8130fdc8d8SChris Lattner 
82b9c1b51eSKate Stone uint32_t ThreadList::GetStopID() const { return m_stop_id; }
8330fdc8d8SChris Lattner 
84b9c1b51eSKate Stone void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }
8530fdc8d8SChris Lattner 
86b9c1b51eSKate Stone uint32_t ThreadList::GetSize(bool can_update) {
87bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
88bb19a13cSSaleem Abdulrasool 
8930fdc8d8SChris Lattner   if (can_update)
9030fdc8d8SChris Lattner     m_process->UpdateThreadListIfNeeded();
9130fdc8d8SChris Lattner   return m_threads.size();
9230fdc8d8SChris Lattner }
9330fdc8d8SChris Lattner 
94b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) {
95bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
96bb19a13cSSaleem Abdulrasool 
9730fdc8d8SChris Lattner   if (can_update)
9830fdc8d8SChris Lattner     m_process->UpdateThreadListIfNeeded();
9930fdc8d8SChris Lattner 
10030fdc8d8SChris Lattner   ThreadSP thread_sp;
10130fdc8d8SChris Lattner   if (idx < m_threads.size())
10230fdc8d8SChris Lattner     thread_sp = m_threads[idx];
10330fdc8d8SChris Lattner   return thread_sp;
10430fdc8d8SChris Lattner }
10530fdc8d8SChris Lattner 
106b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) {
107bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
10830fdc8d8SChris Lattner 
10930fdc8d8SChris Lattner   if (can_update)
11030fdc8d8SChris Lattner     m_process->UpdateThreadListIfNeeded();
11130fdc8d8SChris Lattner 
11230fdc8d8SChris Lattner   ThreadSP thread_sp;
11330fdc8d8SChris Lattner   uint32_t idx = 0;
11430fdc8d8SChris Lattner   const uint32_t num_threads = m_threads.size();
115b9c1b51eSKate Stone   for (idx = 0; idx < num_threads; ++idx) {
116b9c1b51eSKate Stone     if (m_threads[idx]->GetID() == tid) {
11730fdc8d8SChris Lattner       thread_sp = m_threads[idx];
11830fdc8d8SChris Lattner       break;
11930fdc8d8SChris Lattner     }
12030fdc8d8SChris Lattner   }
12130fdc8d8SChris Lattner   return thread_sp;
12230fdc8d8SChris Lattner }
12330fdc8d8SChris Lattner 
124b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) {
125bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
126160c9d81SGreg Clayton 
127160c9d81SGreg Clayton   if (can_update)
128160c9d81SGreg Clayton     m_process->UpdateThreadListIfNeeded();
129160c9d81SGreg Clayton 
130160c9d81SGreg Clayton   ThreadSP thread_sp;
131160c9d81SGreg Clayton   uint32_t idx = 0;
132160c9d81SGreg Clayton   const uint32_t num_threads = m_threads.size();
133b9c1b51eSKate Stone   for (idx = 0; idx < num_threads; ++idx) {
134b9c1b51eSKate Stone     if (m_threads[idx]->GetProtocolID() == tid) {
135160c9d81SGreg Clayton       thread_sp = m_threads[idx];
136160c9d81SGreg Clayton       break;
137160c9d81SGreg Clayton     }
138160c9d81SGreg Clayton   }
139160c9d81SGreg Clayton   return thread_sp;
140160c9d81SGreg Clayton }
141160c9d81SGreg Clayton 
142b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) {
143bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
144c2c423eaSHan Ming Ong 
145c2c423eaSHan Ming Ong   if (can_update)
146c2c423eaSHan Ming Ong     m_process->UpdateThreadListIfNeeded();
147c2c423eaSHan Ming Ong 
148c2c423eaSHan Ming Ong   ThreadSP thread_sp;
149c2c423eaSHan Ming Ong   uint32_t idx = 0;
150c2c423eaSHan Ming Ong   const uint32_t num_threads = m_threads.size();
151b9c1b51eSKate Stone   for (idx = 0; idx < num_threads; ++idx) {
152b9c1b51eSKate Stone     if (m_threads[idx]->GetID() == tid) {
153c2c423eaSHan Ming Ong       thread_sp = m_threads[idx];
154c2c423eaSHan Ming Ong       m_threads.erase(m_threads.begin() + idx);
155c2c423eaSHan Ming Ong       break;
156c2c423eaSHan Ming Ong     }
157c2c423eaSHan Ming Ong   }
158c2c423eaSHan Ming Ong   return thread_sp;
159c2c423eaSHan Ming Ong }
160c2c423eaSHan Ming Ong 
161b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid,
162b9c1b51eSKate Stone                                               bool can_update) {
163bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
164160c9d81SGreg Clayton 
165160c9d81SGreg Clayton   if (can_update)
166160c9d81SGreg Clayton     m_process->UpdateThreadListIfNeeded();
167160c9d81SGreg Clayton 
168160c9d81SGreg Clayton   ThreadSP thread_sp;
169160c9d81SGreg Clayton   uint32_t idx = 0;
170160c9d81SGreg Clayton   const uint32_t num_threads = m_threads.size();
171b9c1b51eSKate Stone   for (idx = 0; idx < num_threads; ++idx) {
172b9c1b51eSKate Stone     if (m_threads[idx]->GetProtocolID() == tid) {
173160c9d81SGreg Clayton       thread_sp = m_threads[idx];
174160c9d81SGreg Clayton       m_threads.erase(m_threads.begin() + idx);
175160c9d81SGreg Clayton       break;
176160c9d81SGreg Clayton     }
177160c9d81SGreg Clayton   }
178160c9d81SGreg Clayton   return thread_sp;
179160c9d81SGreg Clayton }
180160c9d81SGreg Clayton 
181b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
18230fdc8d8SChris Lattner   ThreadSP thread_sp;
183b9c1b51eSKate Stone   if (thread_ptr) {
184bb19a13cSSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(GetMutex());
18530fdc8d8SChris Lattner 
18630fdc8d8SChris Lattner     uint32_t idx = 0;
18730fdc8d8SChris Lattner     const uint32_t num_threads = m_threads.size();
188b9c1b51eSKate Stone     for (idx = 0; idx < num_threads; ++idx) {
189b9c1b51eSKate Stone       if (m_threads[idx].get() == thread_ptr) {
19030fdc8d8SChris Lattner         thread_sp = m_threads[idx];
19130fdc8d8SChris Lattner         break;
19230fdc8d8SChris Lattner       }
19330fdc8d8SChris Lattner     }
19430fdc8d8SChris Lattner   }
19530fdc8d8SChris Lattner   return thread_sp;
19630fdc8d8SChris Lattner }
19730fdc8d8SChris Lattner 
198b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
199bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
20030fdc8d8SChris Lattner 
20130fdc8d8SChris Lattner   if (can_update)
20230fdc8d8SChris Lattner     m_process->UpdateThreadListIfNeeded();
20330fdc8d8SChris Lattner 
20430fdc8d8SChris Lattner   ThreadSP thread_sp;
20530fdc8d8SChris Lattner   const uint32_t num_threads = m_threads.size();
206b9c1b51eSKate Stone   for (uint32_t idx = 0; idx < num_threads; ++idx) {
207b9c1b51eSKate Stone     if (m_threads[idx]->GetIndexID() == index_id) {
20830fdc8d8SChris Lattner       thread_sp = m_threads[idx];
20930fdc8d8SChris Lattner       break;
21030fdc8d8SChris Lattner     }
21130fdc8d8SChris Lattner   }
21230fdc8d8SChris Lattner   return thread_sp;
21330fdc8d8SChris Lattner }
21430fdc8d8SChris Lattner 
215b9c1b51eSKate Stone bool ThreadList::ShouldStop(Event *event_ptr) {
21630fdc8d8SChris Lattner   // Running events should never stop, obviously...
21730fdc8d8SChris Lattner 
2185160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
21930fdc8d8SChris Lattner 
220b42f3af3SJim Ingham   // The ShouldStop method of the threads can do a whole lot of work,
22135878c47SJim Ingham   // figuring out whether the thread plan conditions are met.  So we don't want
222b42f3af3SJim Ingham   // to keep the ThreadList locked the whole time we are doing this.
223b42f3af3SJim Ingham   // FIXME: It is possible that running code could cause new threads
2242f8e4c3bSAdrian McCarthy   // to be created.  If that happens, we will miss asking them whether
2252f8e4c3bSAdrian McCarthy   // they should stop.  This is not a big deal since we haven't had
226b42f3af3SJim Ingham   // a chance to hang any interesting operations on those threads yet.
22730fdc8d8SChris Lattner 
228b42f3af3SJim Ingham   collection threads_copy;
229b42f3af3SJim Ingham   {
230b42f3af3SJim Ingham     // Scope for locker
231bb19a13cSSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(GetMutex());
232b42f3af3SJim Ingham 
233b42f3af3SJim Ingham     m_process->UpdateThreadListIfNeeded();
234b9c1b51eSKate Stone     for (lldb::ThreadSP thread_sp : m_threads) {
235b9c1b51eSKate Stone       // This is an optimization...  If we didn't let a thread run in between
236b9c1b51eSKate Stone       // the previous stop and this
237b9c1b51eSKate Stone       // one, we shouldn't have to consult it for ShouldStop.  So just leave it
238b9c1b51eSKate Stone       // off the list we are going to
239569aaf9eSJim Ingham       // inspect.
240b9c1b51eSKate Stone       // On Linux, if a thread-specific conditional breakpoint was hit, it won't
241b9c1b51eSKate Stone       // necessarily be the thread
242b9c1b51eSKate Stone       // that hit the breakpoint itself that evaluates the conditional
243b9c1b51eSKate Stone       // expression, so the thread that hit
244b9c1b51eSKate Stone       // the breakpoint could still be asked to stop, even though it hasn't been
245b9c1b51eSKate Stone       // allowed to run since the
2466e8fbc6fSChaoren Lin       // previous stop.
247b9c1b51eSKate Stone       if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
248b9c1b51eSKate Stone           thread_sp->IsStillAtLastBreakpointHit())
249569aaf9eSJim Ingham         threads_copy.push_back(thread_sp);
250569aaf9eSJim Ingham     }
251569aaf9eSJim Ingham 
252b9c1b51eSKate Stone     // It is possible the threads we were allowing to run all exited and then
253b9c1b51eSKate Stone     // maybe the user interrupted
254569aaf9eSJim Ingham     // or something, then fall back on looking at all threads:
255569aaf9eSJim Ingham 
256569aaf9eSJim Ingham     if (threads_copy.size() == 0)
257b42f3af3SJim Ingham       threads_copy = m_threads;
258b42f3af3SJim Ingham   }
259b42f3af3SJim Ingham 
260b42f3af3SJim Ingham   collection::iterator pos, end = threads_copy.end();
26130fdc8d8SChris Lattner 
262b9c1b51eSKate Stone   if (log) {
26310c4b249SJim Ingham     log->PutCString("");
264b9c1b51eSKate Stone     log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64
265b9c1b51eSKate Stone                 " unsuspended threads",
266b9c1b51eSKate Stone                 __FUNCTION__, (uint64_t)m_threads.size(),
267569aaf9eSJim Ingham                 (uint64_t)threads_copy.size());
26810c4b249SJim Ingham   }
2692cad65a5SGreg Clayton 
270a0079044SJim Ingham   bool did_anybody_stop_for_a_reason = false;
27135878c47SJim Ingham 
272b9c1b51eSKate Stone   // If the event is an Interrupt event, then we're going to stop no matter
273b9c1b51eSKate Stone   // what.  Otherwise, presume we won't stop.
274a0079044SJim Ingham   bool should_stop = false;
275b9c1b51eSKate Stone   if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
27635878c47SJim Ingham     if (log)
277b9c1b51eSKate Stone       log->Printf(
278b9c1b51eSKate Stone           "ThreadList::%s handling interrupt event, should stop set to true",
279b9c1b51eSKate Stone           __FUNCTION__);
28035878c47SJim Ingham 
28135878c47SJim Ingham     should_stop = true;
28235878c47SJim Ingham   }
2837bc3465fSJim Ingham 
284b9c1b51eSKate Stone   // Now we run through all the threads and get their stop info's.  We want to
285b9c1b51eSKate Stone   // make sure to do this first before
286b9c1b51eSKate Stone   // we start running the ShouldStop, because one thread's ShouldStop could
287b9c1b51eSKate Stone   // destroy information (like deleting a
288b9c1b51eSKate Stone   // thread specific breakpoint another thread had stopped at) which could lead
289b9c1b51eSKate Stone   // us to compute the StopInfo incorrectly.
2907bc3465fSJim Ingham   // We don't need to use it here, we just want to make sure it gets computed.
2917bc3465fSJim Ingham 
292b9c1b51eSKate Stone   for (pos = threads_copy.begin(); pos != end; ++pos) {
2937bc3465fSJim Ingham     ThreadSP thread_sp(*pos);
2947bc3465fSJim Ingham     thread_sp->GetStopInfo();
2957bc3465fSJim Ingham   }
296a0079044SJim Ingham 
297b9c1b51eSKate Stone   for (pos = threads_copy.begin(); pos != end; ++pos) {
29830fdc8d8SChris Lattner     ThreadSP thread_sp(*pos);
2992cad65a5SGreg Clayton 
300b9c1b51eSKate Stone     // We should never get a stop for which no thread had a stop reason, but
301b9c1b51eSKate Stone     // sometimes we do see this -
302b9c1b51eSKate Stone     // for instance when we first connect to a remote stub.  In that case we
303b9c1b51eSKate Stone     // should stop, since we can't figure out
304b9c1b51eSKate Stone     // the right thing to do and stopping gives the user control over what to do
305b9c1b51eSKate Stone     // in this instance.
30639fdae7fSJim Ingham     //
307b9c1b51eSKate Stone     // Note, this causes a problem when you have a thread specific breakpoint,
308b9c1b51eSKate Stone     // and a bunch of threads hit the breakpoint,
309b9c1b51eSKate Stone     // but not the thread which we are waiting for.  All the threads that are
310b9c1b51eSKate Stone     // not "supposed" to hit the breakpoint
311b9c1b51eSKate Stone     // are marked as having no stop reason, which is right, they should not show
312b9c1b51eSKate Stone     // a stop reason.  But that triggers this
31339fdae7fSJim Ingham     // code and causes us to stop seemingly for no reason.
31439fdae7fSJim Ingham     //
315b9c1b51eSKate Stone     // Since the only way we ever saw this error was on first attach, I'm only
316b9c1b51eSKate Stone     // going to trigger set did_anybody_stop_for_a_reason
31739fdae7fSJim Ingham     // to true unless this is the first stop.
31839fdae7fSJim Ingham     //
319b9c1b51eSKate Stone     // If this becomes a problem, we'll have to have another StopReason like
320b9c1b51eSKate Stone     // "StopInfoHidden" which will look invalid
32139fdae7fSJim Ingham     // everywhere but at this check.
32239fdae7fSJim Ingham 
32321afbe03SEd Maste     if (thread_sp->GetProcess()->GetStopID() > 1)
32439fdae7fSJim Ingham       did_anybody_stop_for_a_reason = true;
32539fdae7fSJim Ingham     else
326a0079044SJim Ingham       did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
327a0079044SJim Ingham 
32810c4b249SJim Ingham     const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
3292cad65a5SGreg Clayton     if (thread_should_stop)
3302cad65a5SGreg Clayton       should_stop |= true;
3312cad65a5SGreg Clayton   }
3322cad65a5SGreg Clayton 
333b9c1b51eSKate Stone   if (!should_stop && !did_anybody_stop_for_a_reason) {
334a0079044SJim Ingham     should_stop = true;
335a0079044SJim Ingham     if (log)
336b9c1b51eSKate Stone       log->Printf("ThreadList::%s we stopped but no threads had a stop reason, "
337b9c1b51eSKate Stone                   "overriding should_stop and stopping.",
338b9c1b51eSKate Stone                   __FUNCTION__);
339a0079044SJim Ingham   }
340a0079044SJim Ingham 
3412cad65a5SGreg Clayton   if (log)
342b9c1b51eSKate Stone     log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__,
343b9c1b51eSKate Stone                 should_stop);
3442cad65a5SGreg Clayton 
345b9c1b51eSKate Stone   if (should_stop) {
346b9c1b51eSKate Stone     for (pos = threads_copy.begin(); pos != end; ++pos) {
34730fdc8d8SChris Lattner       ThreadSP thread_sp(*pos);
34830fdc8d8SChris Lattner       thread_sp->WillStop();
34930fdc8d8SChris Lattner     }
35030fdc8d8SChris Lattner   }
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner   return should_stop;
35330fdc8d8SChris Lattner }
35430fdc8d8SChris Lattner 
355b9c1b51eSKate Stone Vote ThreadList::ShouldReportStop(Event *event_ptr) {
356bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
3572cad65a5SGreg Clayton 
35830fdc8d8SChris Lattner   Vote result = eVoteNoOpinion;
35930fdc8d8SChris Lattner   m_process->UpdateThreadListIfNeeded();
36030fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
36130fdc8d8SChris Lattner 
3625160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
3632cad65a5SGreg Clayton 
3642cad65a5SGreg Clayton   if (log)
365b9c1b51eSKate Stone     log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
366b9c1b51eSKate Stone                 (uint64_t)m_threads.size());
3672cad65a5SGreg Clayton 
36830fdc8d8SChris Lattner   // Run through the threads and ask whether we should report this event.
369b9c1b51eSKate Stone   // For stopping, a YES vote wins over everything.  A NO vote wins over NO
370b9c1b51eSKate Stone   // opinion.
371b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
37230fdc8d8SChris Lattner     ThreadSP thread_sp(*pos);
373e0d378b3SGreg Clayton     const Vote vote = thread_sp->ShouldReportStop(event_ptr);
374b9c1b51eSKate Stone     switch (vote) {
37530fdc8d8SChris Lattner     case eVoteNoOpinion:
37630fdc8d8SChris Lattner       continue;
3772cad65a5SGreg Clayton 
37830fdc8d8SChris Lattner     case eVoteYes:
37930fdc8d8SChris Lattner       result = eVoteYes;
38030fdc8d8SChris Lattner       break;
3812cad65a5SGreg Clayton 
38230fdc8d8SChris Lattner     case eVoteNo:
383b9c1b51eSKate Stone       if (result == eVoteNoOpinion) {
38430fdc8d8SChris Lattner         result = eVoteNo;
385b9c1b51eSKate Stone       } else {
386df44988bSZachary Turner         LLDB_LOG(log,
387df44988bSZachary Turner           "Thread {0:x} voted {1}, but lost out because result was {2}",
388df44988bSZachary Turner           thread_sp->GetID(), vote, result);
3892cad65a5SGreg Clayton       }
39030fdc8d8SChris Lattner       break;
39130fdc8d8SChris Lattner     }
39230fdc8d8SChris Lattner   }
393df44988bSZachary Turner   LLDB_LOG(log, "Returning {0}", result);
39430fdc8d8SChris Lattner   return result;
39530fdc8d8SChris Lattner }
39630fdc8d8SChris Lattner 
397b9c1b51eSKate Stone void ThreadList::SetShouldReportStop(Vote vote) {
398bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
399bb19a13cSSaleem Abdulrasool 
400221d51cfSJim Ingham   m_process->UpdateThreadListIfNeeded();
401221d51cfSJim Ingham   collection::iterator pos, end = m_threads.end();
402b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
403221d51cfSJim Ingham     ThreadSP thread_sp(*pos);
404221d51cfSJim Ingham     thread_sp->SetShouldReportStop(vote);
405221d51cfSJim Ingham   }
406221d51cfSJim Ingham }
407221d51cfSJim Ingham 
408b9c1b51eSKate Stone Vote ThreadList::ShouldReportRun(Event *event_ptr) {
4092cad65a5SGreg Clayton 
410bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4112cad65a5SGreg Clayton 
41230fdc8d8SChris Lattner   Vote result = eVoteNoOpinion;
41330fdc8d8SChris Lattner   m_process->UpdateThreadListIfNeeded();
41430fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
41530fdc8d8SChris Lattner 
41630fdc8d8SChris Lattner   // Run through the threads and ask whether we should report this event.
41730fdc8d8SChris Lattner   // The rule is NO vote wins over everything, a YES vote wins over no opinion.
41830fdc8d8SChris Lattner 
4195160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
420ce579839SJim Ingham 
421b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
422b9c1b51eSKate Stone     if ((*pos)->GetResumeState() != eStateSuspended) {
423b9c1b51eSKate Stone       switch ((*pos)->ShouldReportRun(event_ptr)) {
42430fdc8d8SChris Lattner       case eVoteNoOpinion:
42530fdc8d8SChris Lattner         continue;
42630fdc8d8SChris Lattner       case eVoteYes:
42730fdc8d8SChris Lattner         if (result == eVoteNoOpinion)
42830fdc8d8SChris Lattner           result = eVoteYes;
42930fdc8d8SChris Lattner         break;
43030fdc8d8SChris Lattner       case eVoteNo:
431abcbc8acSGreg Clayton         if (log)
432b9c1b51eSKate Stone           log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64
433b9c1b51eSKate Stone                       ") says don't report.",
434b9c1b51eSKate Stone                       (*pos)->GetIndexID(), (*pos)->GetID());
43530fdc8d8SChris Lattner         result = eVoteNo;
43630fdc8d8SChris Lattner         break;
43730fdc8d8SChris Lattner       }
43830fdc8d8SChris Lattner     }
439ce579839SJim Ingham   }
44030fdc8d8SChris Lattner   return result;
44130fdc8d8SChris Lattner }
44230fdc8d8SChris Lattner 
443b9c1b51eSKate Stone void ThreadList::Clear() {
444bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
44530fdc8d8SChris Lattner   m_stop_id = 0;
44630fdc8d8SChris Lattner   m_threads.clear();
4472976d00aSJim Ingham   m_selected_tid = LLDB_INVALID_THREAD_ID;
44830fdc8d8SChris Lattner }
44930fdc8d8SChris Lattner 
450b9c1b51eSKate Stone void ThreadList::Destroy() {
451bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
452e1cd1be6SGreg Clayton   const uint32_t num_threads = m_threads.size();
453b9c1b51eSKate Stone   for (uint32_t idx = 0; idx < num_threads; ++idx) {
454e1cd1be6SGreg Clayton     m_threads[idx]->DestroyThread();
455e1cd1be6SGreg Clayton   }
456e1cd1be6SGreg Clayton }
457e1cd1be6SGreg Clayton 
458b9c1b51eSKate Stone void ThreadList::RefreshStateAfterStop() {
459bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
46030fdc8d8SChris Lattner 
46130fdc8d8SChris Lattner   m_process->UpdateThreadListIfNeeded();
46230fdc8d8SChris Lattner 
4635160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
46410c4b249SJim Ingham   if (log && log->GetVerbose())
465b9c1b51eSKate Stone     log->Printf("Turning off notification of new threads while single stepping "
466b9c1b51eSKate Stone                 "a thread.");
4671c823b43SJim Ingham 
46830fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
46930fdc8d8SChris Lattner   for (pos = m_threads.begin(); pos != end; ++pos)
47030fdc8d8SChris Lattner     (*pos)->RefreshStateAfterStop();
47130fdc8d8SChris Lattner }
47230fdc8d8SChris Lattner 
473b9c1b51eSKate Stone void ThreadList::DiscardThreadPlans() {
47430fdc8d8SChris Lattner   // You don't need to update the thread list here, because only threads
47530fdc8d8SChris Lattner   // that you currently know about have any thread plans.
476bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
47730fdc8d8SChris Lattner 
47830fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
47930fdc8d8SChris Lattner   for (pos = m_threads.begin(); pos != end; ++pos)
48030fdc8d8SChris Lattner     (*pos)->DiscardThreadPlans(true);
48130fdc8d8SChris Lattner }
48230fdc8d8SChris Lattner 
483b9c1b51eSKate Stone bool ThreadList::WillResume() {
48430fdc8d8SChris Lattner   // Run through the threads and perform their momentary actions.
48530fdc8d8SChris Lattner   // But we only do this for threads that are running, user suspended
48630fdc8d8SChris Lattner   // threads stay where they are.
48730fdc8d8SChris Lattner 
488bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
48930fdc8d8SChris Lattner   m_process->UpdateThreadListIfNeeded();
49030fdc8d8SChris Lattner 
49130fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
49230fdc8d8SChris Lattner 
493a3241c1bSJim Ingham   // See if any thread wants to run stopping others.  If it does, then we won't
494a3241c1bSJim Ingham   // setup the other threads for resume, since they aren't going to get a chance
495b9c1b51eSKate Stone   // to run.  This is necessary because the SetupForResume might add
496b9c1b51eSKate Stone   // "StopOthers"
497b9c1b51eSKate Stone   // plans which would then get to be part of the who-gets-to-run negotiation,
498b9c1b51eSKate Stone   // but
499b9c1b51eSKate Stone   // they're coming in after the fact, and the threads that are already set up
500b9c1b51eSKate Stone   // should
501a3241c1bSJim Ingham   // take priority.
502a3241c1bSJim Ingham 
503a3241c1bSJim Ingham   bool wants_solo_run = false;
50430fdc8d8SChris Lattner 
505b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
506b9c1b51eSKate Stone     lldbassert((*pos)->GetCurrentPlan() &&
507b9c1b51eSKate Stone                "thread should not have null thread plan");
5088f186f85SZachary Turner     if ((*pos)->GetResumeState() != eStateSuspended &&
509b9c1b51eSKate Stone         (*pos)->GetCurrentPlan()->StopOthers()) {
510b9c1b51eSKate Stone       if ((*pos)->IsOperatingSystemPluginThread() &&
511b9c1b51eSKate Stone           !(*pos)->GetBackingThread())
5126e0ff1a3SGreg Clayton         continue;
513a3241c1bSJim Ingham       wants_solo_run = true;
514a3241c1bSJim Ingham       break;
515a3241c1bSJim Ingham     }
516a3241c1bSJim Ingham   }
517a3241c1bSJim Ingham 
518b9c1b51eSKate Stone   if (wants_solo_run) {
5195160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
52010c4b249SJim Ingham     if (log && log->GetVerbose())
521b9c1b51eSKate Stone       log->Printf("Turning on notification of new threads while single "
522b9c1b51eSKate Stone                   "stepping a thread.");
5231c823b43SJim Ingham     m_process->StartNoticingNewThreads();
524b9c1b51eSKate Stone   } else {
5255160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
52610c4b249SJim Ingham     if (log && log->GetVerbose())
527b9c1b51eSKate Stone       log->Printf("Turning off notification of new threads while single "
528b9c1b51eSKate Stone                   "stepping a thread.");
5291c823b43SJim Ingham     m_process->StopNoticingNewThreads();
5301c823b43SJim Ingham   }
531a3241c1bSJim Ingham 
532b9c1b51eSKate Stone   // Give all the threads that are likely to run a last chance to set up their
533b9c1b51eSKate Stone   // state before we
534a3241c1bSJim Ingham   // negotiate who is actually going to get a chance to run...
535b9c1b51eSKate Stone   // Don't set to resume suspended threads, and if any thread wanted to stop
536b9c1b51eSKate Stone   // others, only
537a3241c1bSJim Ingham   // call setup on the threads that request StopOthers...
538a3241c1bSJim Ingham 
539b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
540b9c1b51eSKate Stone     if ((*pos)->GetResumeState() != eStateSuspended &&
541b9c1b51eSKate Stone         (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) {
542b9c1b51eSKate Stone       if ((*pos)->IsOperatingSystemPluginThread() &&
543b9c1b51eSKate Stone           !(*pos)->GetBackingThread())
5446e0ff1a3SGreg Clayton         continue;
54530fdc8d8SChris Lattner       (*pos)->SetupForResume();
546a3241c1bSJim Ingham     }
547a3241c1bSJim Ingham   }
54830fdc8d8SChris Lattner 
54930fdc8d8SChris Lattner   // Now go through the threads and see if any thread wants to run just itself.
55030fdc8d8SChris Lattner   // if so then pick one and run it.
551a3241c1bSJim Ingham 
55230fdc8d8SChris Lattner   ThreadList run_me_only_list(m_process);
55330fdc8d8SChris Lattner 
55430fdc8d8SChris Lattner   run_me_only_list.SetStopID(m_process->GetStopID());
55530fdc8d8SChris Lattner 
55630fdc8d8SChris Lattner   bool run_only_current_thread = false;
55730fdc8d8SChris Lattner 
558b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
55930fdc8d8SChris Lattner     ThreadSP thread_sp(*pos);
560b15bfc75SJim Ingham     if (thread_sp->GetResumeState() != eStateSuspended &&
561b9c1b51eSKate Stone         thread_sp->GetCurrentPlan()->StopOthers()) {
562b9c1b51eSKate Stone       if ((*pos)->IsOperatingSystemPluginThread() &&
563b9c1b51eSKate Stone           !(*pos)->GetBackingThread())
5646e0ff1a3SGreg Clayton         continue;
5656e0ff1a3SGreg Clayton 
56630fdc8d8SChris Lattner       // You can't say "stop others" and also want yourself to be suspended.
56730fdc8d8SChris Lattner       assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
56830fdc8d8SChris Lattner 
569b9c1b51eSKate Stone       if (thread_sp == GetSelectedThread()) {
570b9c1b51eSKate Stone         // If the currently selected thread wants to run on its own, always let
571b9c1b51eSKate Stone         // it.
57230fdc8d8SChris Lattner         run_only_current_thread = true;
57330fdc8d8SChris Lattner         run_me_only_list.Clear();
57430fdc8d8SChris Lattner         run_me_only_list.AddThread(thread_sp);
57530fdc8d8SChris Lattner         break;
57630fdc8d8SChris Lattner       }
57730fdc8d8SChris Lattner 
57830fdc8d8SChris Lattner       run_me_only_list.AddThread(thread_sp);
57930fdc8d8SChris Lattner     }
58030fdc8d8SChris Lattner   }
58130fdc8d8SChris Lattner 
582513c6bb8SJim Ingham   bool need_to_resume = true;
583513c6bb8SJim Ingham 
584b9c1b51eSKate Stone   if (run_me_only_list.GetSize(false) == 0) {
58530fdc8d8SChris Lattner     // Everybody runs as they wish:
586b9c1b51eSKate Stone     for (pos = m_threads.begin(); pos != end; ++pos) {
58730fdc8d8SChris Lattner       ThreadSP thread_sp(*pos);
588cb5d5a57SJim Ingham       StateType run_state;
589cb5d5a57SJim Ingham       if (thread_sp->GetResumeState() != eStateSuspended)
590cb5d5a57SJim Ingham         run_state = thread_sp->GetCurrentPlan()->RunState();
591cb5d5a57SJim Ingham       else
592cb5d5a57SJim Ingham         run_state = eStateSuspended;
593160c9d81SGreg Clayton       if (!thread_sp->ShouldResume(run_state))
594513c6bb8SJim Ingham         need_to_resume = false;
59530fdc8d8SChris Lattner     }
596b9c1b51eSKate Stone   } else {
59730fdc8d8SChris Lattner     ThreadSP thread_to_run;
59830fdc8d8SChris Lattner 
599b9c1b51eSKate Stone     if (run_only_current_thread) {
6002976d00aSJim Ingham       thread_to_run = GetSelectedThread();
601b9c1b51eSKate Stone     } else if (run_me_only_list.GetSize(false) == 1) {
60230fdc8d8SChris Lattner       thread_to_run = run_me_only_list.GetThreadAtIndex(0);
603b9c1b51eSKate Stone     } else {
604b9c1b51eSKate Stone       int random_thread =
605b9c1b51eSKate Stone           (int)((run_me_only_list.GetSize(false) * (double)rand()) /
606b9c1b51eSKate Stone                 (RAND_MAX + 1.0));
60730fdc8d8SChris Lattner       thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
60830fdc8d8SChris Lattner     }
60930fdc8d8SChris Lattner 
610b9c1b51eSKate Stone     for (pos = m_threads.begin(); pos != end; ++pos) {
61130fdc8d8SChris Lattner       ThreadSP thread_sp(*pos);
612b9c1b51eSKate Stone       if (thread_sp == thread_to_run) {
613160c9d81SGreg Clayton         if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
614513c6bb8SJim Ingham           need_to_resume = false;
615b9c1b51eSKate Stone       } else
616160c9d81SGreg Clayton         thread_sp->ShouldResume(eStateSuspended);
61730fdc8d8SChris Lattner     }
61830fdc8d8SChris Lattner   }
61930fdc8d8SChris Lattner 
620513c6bb8SJim Ingham   return need_to_resume;
62130fdc8d8SChris Lattner }
62230fdc8d8SChris Lattner 
623b9c1b51eSKate Stone void ThreadList::DidResume() {
624bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
62530fdc8d8SChris Lattner   collection::iterator pos, end = m_threads.end();
626b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
62730fdc8d8SChris Lattner     // Don't clear out threads that aren't going to get a chance to run, rather
62830fdc8d8SChris Lattner     // leave their state for the next time around.
62930fdc8d8SChris Lattner     ThreadSP thread_sp(*pos);
63030fdc8d8SChris Lattner     if (thread_sp->GetResumeState() != eStateSuspended)
63130fdc8d8SChris Lattner       thread_sp->DidResume();
63230fdc8d8SChris Lattner   }
63330fdc8d8SChris Lattner }
63430fdc8d8SChris Lattner 
635b9c1b51eSKate Stone void ThreadList::DidStop() {
636bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
63729d65744SAndrew Kaylor   collection::iterator pos, end = m_threads.end();
638b9c1b51eSKate Stone   for (pos = m_threads.begin(); pos != end; ++pos) {
63929d65744SAndrew Kaylor     // Notify threads that the process just stopped.
64029d65744SAndrew Kaylor     // Note, this currently assumes that all threads in the list
64129d65744SAndrew Kaylor     // stop when the process stops.  In the future we will want to support
64229d65744SAndrew Kaylor     // a debugging model where some threads continue to run while others
64329d65744SAndrew Kaylor     // are stopped.  We either need to handle that somehow here or
64429d65744SAndrew Kaylor     // create a special thread list containing only threads which will
64529d65744SAndrew Kaylor     // stop in the code that calls this method (currently
64629d65744SAndrew Kaylor     // Process::SetPrivateState).
64729d65744SAndrew Kaylor     ThreadSP thread_sp(*pos);
64829d65744SAndrew Kaylor     if (StateIsRunningState(thread_sp->GetState()))
64929d65744SAndrew Kaylor       thread_sp->DidStop();
65029d65744SAndrew Kaylor   }
65129d65744SAndrew Kaylor }
65229d65744SAndrew Kaylor 
653b9c1b51eSKate Stone ThreadSP ThreadList::GetSelectedThread() {
654bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
655943ddb73SJohnny Chen   ThreadSP thread_sp = FindThreadByID(m_selected_tid);
656b9c1b51eSKate Stone   if (!thread_sp.get()) {
657354b9a65SJason Molenda     if (m_threads.size() == 0)
658354b9a65SJason Molenda       return thread_sp;
659943ddb73SJohnny Chen     m_selected_tid = m_threads[0]->GetID();
660943ddb73SJohnny Chen     thread_sp = m_threads[0];
661943ddb73SJohnny Chen   }
662943ddb73SJohnny Chen   return thread_sp;
66330fdc8d8SChris Lattner }
66430fdc8d8SChris Lattner 
665b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) {
666bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
667b7f6b2faSJim Ingham   ThreadSP selected_thread_sp(FindThreadByID(tid));
668b9c1b51eSKate Stone   if (selected_thread_sp) {
6692976d00aSJim Ingham     m_selected_tid = tid;
670b7f6b2faSJim Ingham     selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
671b9c1b51eSKate Stone   } else
6722976d00aSJim Ingham     m_selected_tid = LLDB_INVALID_THREAD_ID;
67330fdc8d8SChris Lattner 
674c3faa195SJim Ingham   if (notify)
675c3faa195SJim Ingham     NotifySelectedThreadChanged(m_selected_tid);
676c3faa195SJim Ingham 
6772976d00aSJim Ingham   return m_selected_tid != LLDB_INVALID_THREAD_ID;
67830fdc8d8SChris Lattner }
67930fdc8d8SChris Lattner 
680b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) {
681bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
682b7f6b2faSJim Ingham   ThreadSP selected_thread_sp(FindThreadByIndexID(index_id));
683b9c1b51eSKate Stone   if (selected_thread_sp.get()) {
684b7f6b2faSJim Ingham     m_selected_tid = selected_thread_sp->GetID();
685b7f6b2faSJim Ingham     selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
686b9c1b51eSKate Stone   } else
6872976d00aSJim Ingham     m_selected_tid = LLDB_INVALID_THREAD_ID;
68830fdc8d8SChris Lattner 
689c3faa195SJim Ingham   if (notify)
690c3faa195SJim Ingham     NotifySelectedThreadChanged(m_selected_tid);
691c3faa195SJim Ingham 
6922976d00aSJim Ingham   return m_selected_tid != LLDB_INVALID_THREAD_ID;
69330fdc8d8SChris Lattner }
69430fdc8d8SChris Lattner 
695b9c1b51eSKate Stone void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
696c3faa195SJim Ingham   ThreadSP selected_thread_sp(FindThreadByID(tid));
697b9c1b51eSKate Stone   if (selected_thread_sp->EventTypeHasListeners(
698b9c1b51eSKate Stone           Thread::eBroadcastBitThreadSelected))
699b9c1b51eSKate Stone     selected_thread_sp->BroadcastEvent(
700b9c1b51eSKate Stone         Thread::eBroadcastBitThreadSelected,
701c3faa195SJim Ingham         new Thread::ThreadEventData(selected_thread_sp));
702c3faa195SJim Ingham }
703c3faa195SJim Ingham 
704b9c1b51eSKate Stone void ThreadList::Update(ThreadList &rhs) {
705b9c1b51eSKate Stone   if (this != &rhs) {
70656d9a1b3SGreg Clayton     // Lock both mutexes to make sure neither side changes anyone on us
707e171da5cSBruce Mitchener     // while the assignment occurs
708bb19a13cSSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(GetMutex());
709bb19a13cSSaleem Abdulrasool 
71056d9a1b3SGreg Clayton     m_process = rhs.m_process;
71156d9a1b3SGreg Clayton     m_stop_id = rhs.m_stop_id;
71256d9a1b3SGreg Clayton     m_threads.swap(rhs.m_threads);
71356d9a1b3SGreg Clayton     m_selected_tid = rhs.m_selected_tid;
714e1cd1be6SGreg Clayton 
715e1cd1be6SGreg Clayton     // Now we look for threads that we are done with and
716e1cd1be6SGreg Clayton     // make sure to clear them up as much as possible so
717e1cd1be6SGreg Clayton     // anyone with a shared pointer will still have a reference,
718e1cd1be6SGreg Clayton     // but the thread won't be of much use. Using std::weak_ptr
719e1cd1be6SGreg Clayton     // for all backward references (such as a thread to a process)
720e1cd1be6SGreg Clayton     // will eventually solve this issue for us, but for now, we
721e1cd1be6SGreg Clayton     // need to work around the issue
722e1cd1be6SGreg Clayton     collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
723b9c1b51eSKate Stone     for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
724e1cd1be6SGreg Clayton       const lldb::tid_t tid = (*rhs_pos)->GetID();
725e1cd1be6SGreg Clayton       bool thread_is_alive = false;
726e1cd1be6SGreg Clayton       const uint32_t num_threads = m_threads.size();
727b9c1b51eSKate Stone       for (uint32_t idx = 0; idx < num_threads; ++idx) {
72865d4d5c3SRyan Brown         ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
729b9c1b51eSKate Stone         if (m_threads[idx]->GetID() == tid ||
730b9c1b51eSKate Stone             (backing_thread && backing_thread->GetID() == tid)) {
731e1cd1be6SGreg Clayton           thread_is_alive = true;
732e1cd1be6SGreg Clayton           break;
733e1cd1be6SGreg Clayton         }
734e1cd1be6SGreg Clayton       }
735e1cd1be6SGreg Clayton       if (!thread_is_alive)
736e1cd1be6SGreg Clayton         (*rhs_pos)->DestroyThread();
737e1cd1be6SGreg Clayton     }
73856d9a1b3SGreg Clayton   }
73956d9a1b3SGreg Clayton }
74056d9a1b3SGreg Clayton 
741b9c1b51eSKate Stone void ThreadList::Flush() {
742bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(GetMutex());
743fa559e5cSGreg Clayton   collection::iterator pos, end = m_threads.end();
744fa559e5cSGreg Clayton   for (pos = m_threads.begin(); pos != end; ++pos)
745fa559e5cSGreg Clayton     (*pos)->Flush();
746fa559e5cSGreg Clayton }
74756d9a1b3SGreg Clayton 
748b5cd6e7bSGreg Clayton std::recursive_mutex &ThreadList::GetMutex() const {
749ba4e61d3SAndrew Kaylor   return m_process->m_thread_mutex;
750ba4e61d3SAndrew Kaylor }
751ba4e61d3SAndrew Kaylor 
752b9c1b51eSKate Stone ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher(
753b9c1b51eSKate Stone     lldb::ThreadSP thread_sp)
754b9c1b51eSKate Stone     : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) {
755b9c1b51eSKate Stone   if (thread_sp) {
7568d94ba0fSJim Ingham     m_tid = thread_sp->GetID();
7578d94ba0fSJim Ingham     m_thread_list = &thread_sp->GetProcess()->GetThreadList();
7588d94ba0fSJim Ingham     m_thread_list->PushExpressionExecutionThread(m_tid);
7598d94ba0fSJim Ingham   }
7608d94ba0fSJim Ingham }
761