15ffd83dbSDimitry Andric //===-- ThreadList.cpp ----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include <stdlib.h>
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include <algorithm>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "lldb/Target/Process.h"
140b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
150b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
160b57cec5SDimitry Andric #include "lldb/Target/ThreadList.h"
170b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
180b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
200b57cec5SDimitry Andric #include "lldb/Utility/State.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace lldb;
230b57cec5SDimitry Andric using namespace lldb_private;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric ThreadList::ThreadList(Process *process)
260b57cec5SDimitry Andric     : ThreadCollection(), m_process(process), m_stop_id(0),
270b57cec5SDimitry Andric       m_selected_tid(LLDB_INVALID_THREAD_ID) {}
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric ThreadList::ThreadList(const ThreadList &rhs)
300b57cec5SDimitry Andric     : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id),
310b57cec5SDimitry Andric       m_selected_tid() {
320b57cec5SDimitry Andric   // Use the assignment operator since it uses the mutex
330b57cec5SDimitry Andric   *this = rhs;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
370b57cec5SDimitry Andric   if (this != &rhs) {
380b57cec5SDimitry Andric     // Lock both mutexes to make sure neither side changes anyone on us while
390b57cec5SDimitry Andric     // the assignment occurs
400b57cec5SDimitry Andric     std::lock(GetMutex(), rhs.GetMutex());
410b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(GetMutex(), std::adopt_lock);
420b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex(),
430b57cec5SDimitry Andric                                                     std::adopt_lock);
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric     m_process = rhs.m_process;
460b57cec5SDimitry Andric     m_stop_id = rhs.m_stop_id;
470b57cec5SDimitry Andric     m_threads = rhs.m_threads;
480b57cec5SDimitry Andric     m_selected_tid = rhs.m_selected_tid;
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric   return *this;
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric ThreadList::~ThreadList() {
540b57cec5SDimitry Andric   // Clear the thread list. Clear will take the mutex lock which will ensure
550b57cec5SDimitry Andric   // that if anyone is using the list they won't get it removed while using it.
560b57cec5SDimitry Andric   Clear();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric lldb::ThreadSP ThreadList::GetExpressionExecutionThread() {
600b57cec5SDimitry Andric   if (m_expression_tid_stack.empty())
610b57cec5SDimitry Andric     return GetSelectedThread();
620b57cec5SDimitry Andric   ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back());
630b57cec5SDimitry Andric   if (expr_thread_sp)
640b57cec5SDimitry Andric     return expr_thread_sp;
650b57cec5SDimitry Andric   else
660b57cec5SDimitry Andric     return GetSelectedThread();
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) {
700b57cec5SDimitry Andric   m_expression_tid_stack.push_back(tid);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) {
740b57cec5SDimitry Andric   assert(m_expression_tid_stack.back() == tid);
750b57cec5SDimitry Andric   m_expression_tid_stack.pop_back();
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric uint32_t ThreadList::GetStopID() const { return m_stop_id; }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric uint32_t ThreadList::GetSize(bool can_update) {
830b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   if (can_update)
860b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
870b57cec5SDimitry Andric   return m_threads.size();
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) {
910b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   if (can_update)
940b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   ThreadSP thread_sp;
970b57cec5SDimitry Andric   if (idx < m_threads.size())
980b57cec5SDimitry Andric     thread_sp = m_threads[idx];
990b57cec5SDimitry Andric   return thread_sp;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) {
1030b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   if (can_update)
1060b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   ThreadSP thread_sp;
1090b57cec5SDimitry Andric   uint32_t idx = 0;
1100b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
1110b57cec5SDimitry Andric   for (idx = 0; idx < num_threads; ++idx) {
1120b57cec5SDimitry Andric     if (m_threads[idx]->GetID() == tid) {
1130b57cec5SDimitry Andric       thread_sp = m_threads[idx];
1140b57cec5SDimitry Andric       break;
1150b57cec5SDimitry Andric     }
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric   return thread_sp;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) {
1210b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   if (can_update)
1240b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   ThreadSP thread_sp;
1270b57cec5SDimitry Andric   uint32_t idx = 0;
1280b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
1290b57cec5SDimitry Andric   for (idx = 0; idx < num_threads; ++idx) {
1300b57cec5SDimitry Andric     if (m_threads[idx]->GetProtocolID() == tid) {
1310b57cec5SDimitry Andric       thread_sp = m_threads[idx];
1320b57cec5SDimitry Andric       break;
1330b57cec5SDimitry Andric     }
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric   return thread_sp;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) {
1390b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   if (can_update)
1420b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   ThreadSP thread_sp;
1450b57cec5SDimitry Andric   uint32_t idx = 0;
1460b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
1470b57cec5SDimitry Andric   for (idx = 0; idx < num_threads; ++idx) {
1480b57cec5SDimitry Andric     if (m_threads[idx]->GetID() == tid) {
1490b57cec5SDimitry Andric       thread_sp = m_threads[idx];
1500b57cec5SDimitry Andric       m_threads.erase(m_threads.begin() + idx);
1510b57cec5SDimitry Andric       break;
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric   return thread_sp;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid,
1580b57cec5SDimitry Andric                                               bool can_update) {
1590b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (can_update)
1620b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   ThreadSP thread_sp;
1650b57cec5SDimitry Andric   uint32_t idx = 0;
1660b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
1670b57cec5SDimitry Andric   for (idx = 0; idx < num_threads; ++idx) {
1680b57cec5SDimitry Andric     if (m_threads[idx]->GetProtocolID() == tid) {
1690b57cec5SDimitry Andric       thread_sp = m_threads[idx];
1700b57cec5SDimitry Andric       m_threads.erase(m_threads.begin() + idx);
1710b57cec5SDimitry Andric       break;
1720b57cec5SDimitry Andric     }
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric   return thread_sp;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
1780b57cec5SDimitry Andric   ThreadSP thread_sp;
1790b57cec5SDimitry Andric   if (thread_ptr) {
1800b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(GetMutex());
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     uint32_t idx = 0;
1830b57cec5SDimitry Andric     const uint32_t num_threads = m_threads.size();
1840b57cec5SDimitry Andric     for (idx = 0; idx < num_threads; ++idx) {
1850b57cec5SDimitry Andric       if (m_threads[idx].get() == thread_ptr) {
1860b57cec5SDimitry Andric         thread_sp = m_threads[idx];
1870b57cec5SDimitry Andric         break;
1880b57cec5SDimitry Andric       }
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric   return thread_sp;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) {
1950b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   ThreadSP thread_sp;
1980b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
1990b57cec5SDimitry Andric   for (uint32_t idx = 0; idx < num_threads; ++idx) {
2000b57cec5SDimitry Andric     if (m_threads[idx]->GetBackingThread() == real_thread) {
2010b57cec5SDimitry Andric       thread_sp = m_threads[idx];
2020b57cec5SDimitry Andric       break;
2030b57cec5SDimitry Andric     }
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric   return thread_sp;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
2090b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   if (can_update)
2120b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   ThreadSP thread_sp;
2150b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
2160b57cec5SDimitry Andric   for (uint32_t idx = 0; idx < num_threads; ++idx) {
2170b57cec5SDimitry Andric     if (m_threads[idx]->GetIndexID() == index_id) {
2180b57cec5SDimitry Andric       thread_sp = m_threads[idx];
2190b57cec5SDimitry Andric       break;
2200b57cec5SDimitry Andric     }
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric   return thread_sp;
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric bool ThreadList::ShouldStop(Event *event_ptr) {
2260b57cec5SDimitry Andric   // Running events should never stop, obviously...
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   // The ShouldStop method of the threads can do a whole lot of work, figuring
2310b57cec5SDimitry Andric   // out whether the thread plan conditions are met.  So we don't want to keep
2320b57cec5SDimitry Andric   // the ThreadList locked the whole time we are doing this.
2330b57cec5SDimitry Andric   // FIXME: It is possible that running code could cause new threads
2340b57cec5SDimitry Andric   // to be created.  If that happens, we will miss asking them whether they
2350b57cec5SDimitry Andric   // should stop.  This is not a big deal since we haven't had a chance to hang
2360b57cec5SDimitry Andric   // any interesting operations on those threads yet.
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   collection threads_copy;
2390b57cec5SDimitry Andric   {
2400b57cec5SDimitry Andric     // Scope for locker
2410b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(GetMutex());
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     m_process->UpdateThreadListIfNeeded();
2440b57cec5SDimitry Andric     for (lldb::ThreadSP thread_sp : m_threads) {
2450b57cec5SDimitry Andric       // This is an optimization...  If we didn't let a thread run in between
2460b57cec5SDimitry Andric       // the previous stop and this one, we shouldn't have to consult it for
2470b57cec5SDimitry Andric       // ShouldStop.  So just leave it off the list we are going to inspect. On
2480b57cec5SDimitry Andric       // Linux, if a thread-specific conditional breakpoint was hit, it won't
2490b57cec5SDimitry Andric       // necessarily be the thread that hit the breakpoint itself that
2500b57cec5SDimitry Andric       // evaluates the conditional expression, so the thread that hit the
2510b57cec5SDimitry Andric       // breakpoint could still be asked to stop, even though it hasn't been
2520b57cec5SDimitry Andric       // allowed to run since the previous stop.
2530b57cec5SDimitry Andric       if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
2540b57cec5SDimitry Andric           thread_sp->IsStillAtLastBreakpointHit())
2550b57cec5SDimitry Andric         threads_copy.push_back(thread_sp);
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     // It is possible the threads we were allowing to run all exited and then
2590b57cec5SDimitry Andric     // maybe the user interrupted or something, then fall back on looking at
2600b57cec5SDimitry Andric     // all threads:
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric     if (threads_copy.size() == 0)
2630b57cec5SDimitry Andric       threads_copy = m_threads;
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   collection::iterator pos, end = threads_copy.end();
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   if (log) {
2690b57cec5SDimitry Andric     log->PutCString("");
2709dba64beSDimitry Andric     LLDB_LOGF(log,
2719dba64beSDimitry Andric               "ThreadList::%s: %" PRIu64 " threads, %" PRIu64
2720b57cec5SDimitry Andric               " unsuspended threads",
2730b57cec5SDimitry Andric               __FUNCTION__, (uint64_t)m_threads.size(),
2740b57cec5SDimitry Andric               (uint64_t)threads_copy.size());
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   bool did_anybody_stop_for_a_reason = false;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // If the event is an Interrupt event, then we're going to stop no matter
2800b57cec5SDimitry Andric   // what.  Otherwise, presume we won't stop.
2810b57cec5SDimitry Andric   bool should_stop = false;
2820b57cec5SDimitry Andric   if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
2839dba64beSDimitry Andric     LLDB_LOGF(
2849dba64beSDimitry Andric         log, "ThreadList::%s handling interrupt event, should stop set to true",
2850b57cec5SDimitry Andric         __FUNCTION__);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric     should_stop = true;
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   // Now we run through all the threads and get their stop info's.  We want to
2910b57cec5SDimitry Andric   // make sure to do this first before we start running the ShouldStop, because
2920b57cec5SDimitry Andric   // one thread's ShouldStop could destroy information (like deleting a thread
2930b57cec5SDimitry Andric   // specific breakpoint another thread had stopped at) which could lead us to
2940b57cec5SDimitry Andric   // compute the StopInfo incorrectly. We don't need to use it here, we just
2950b57cec5SDimitry Andric   // want to make sure it gets computed.
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   for (pos = threads_copy.begin(); pos != end; ++pos) {
2980b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
2990b57cec5SDimitry Andric     thread_sp->GetStopInfo();
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   for (pos = threads_copy.begin(); pos != end; ++pos) {
3030b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric     // We should never get a stop for which no thread had a stop reason, but
3060b57cec5SDimitry Andric     // sometimes we do see this - for instance when we first connect to a
3070b57cec5SDimitry Andric     // remote stub.  In that case we should stop, since we can't figure out the
3080b57cec5SDimitry Andric     // right thing to do and stopping gives the user control over what to do in
3090b57cec5SDimitry Andric     // this instance.
3100b57cec5SDimitry Andric     //
3110b57cec5SDimitry Andric     // Note, this causes a problem when you have a thread specific breakpoint,
3120b57cec5SDimitry Andric     // and a bunch of threads hit the breakpoint, but not the thread which we
3130b57cec5SDimitry Andric     // are waiting for.  All the threads that are not "supposed" to hit the
3140b57cec5SDimitry Andric     // breakpoint are marked as having no stop reason, which is right, they
3150b57cec5SDimitry Andric     // should not show a stop reason.  But that triggers this code and causes
3160b57cec5SDimitry Andric     // us to stop seemingly for no reason.
3170b57cec5SDimitry Andric     //
3180b57cec5SDimitry Andric     // Since the only way we ever saw this error was on first attach, I'm only
3190b57cec5SDimitry Andric     // going to trigger set did_anybody_stop_for_a_reason to true unless this
3200b57cec5SDimitry Andric     // is the first stop.
3210b57cec5SDimitry Andric     //
3220b57cec5SDimitry Andric     // If this becomes a problem, we'll have to have another StopReason like
3230b57cec5SDimitry Andric     // "StopInfoHidden" which will look invalid everywhere but at this check.
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     if (thread_sp->GetProcess()->GetStopID() > 1)
3260b57cec5SDimitry Andric       did_anybody_stop_for_a_reason = true;
3270b57cec5SDimitry Andric     else
3280b57cec5SDimitry Andric       did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric     const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
3310b57cec5SDimitry Andric     if (thread_should_stop)
3320b57cec5SDimitry Andric       should_stop |= true;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   if (!should_stop && !did_anybody_stop_for_a_reason) {
3360b57cec5SDimitry Andric     should_stop = true;
3379dba64beSDimitry Andric     LLDB_LOGF(log,
3389dba64beSDimitry Andric               "ThreadList::%s we stopped but no threads had a stop reason, "
3390b57cec5SDimitry Andric               "overriding should_stop and stopping.",
3400b57cec5SDimitry Andric               __FUNCTION__);
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3439dba64beSDimitry Andric   LLDB_LOGF(log, "ThreadList::%s overall should_stop = %i", __FUNCTION__,
3440b57cec5SDimitry Andric             should_stop);
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   if (should_stop) {
3470b57cec5SDimitry Andric     for (pos = threads_copy.begin(); pos != end; ++pos) {
3480b57cec5SDimitry Andric       ThreadSP thread_sp(*pos);
3490b57cec5SDimitry Andric       thread_sp->WillStop();
3500b57cec5SDimitry Andric     }
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   return should_stop;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric Vote ThreadList::ShouldReportStop(Event *event_ptr) {
3570b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   Vote result = eVoteNoOpinion;
3600b57cec5SDimitry Andric   m_process->UpdateThreadListIfNeeded();
3610b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
3640b57cec5SDimitry Andric 
3659dba64beSDimitry Andric   LLDB_LOGF(log, "ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
3660b57cec5SDimitry Andric             (uint64_t)m_threads.size());
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   // Run through the threads and ask whether we should report this event. For
3690b57cec5SDimitry Andric   // stopping, a YES vote wins over everything.  A NO vote wins over NO
3700b57cec5SDimitry Andric   // opinion.
3710b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
3720b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
3730b57cec5SDimitry Andric     const Vote vote = thread_sp->ShouldReportStop(event_ptr);
3740b57cec5SDimitry Andric     switch (vote) {
3750b57cec5SDimitry Andric     case eVoteNoOpinion:
3760b57cec5SDimitry Andric       continue;
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     case eVoteYes:
3790b57cec5SDimitry Andric       result = eVoteYes;
3800b57cec5SDimitry Andric       break;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric     case eVoteNo:
3830b57cec5SDimitry Andric       if (result == eVoteNoOpinion) {
3840b57cec5SDimitry Andric         result = eVoteNo;
3850b57cec5SDimitry Andric       } else {
3860b57cec5SDimitry Andric         LLDB_LOG(log,
3870b57cec5SDimitry Andric           "Thread {0:x} voted {1}, but lost out because result was {2}",
3880b57cec5SDimitry Andric           thread_sp->GetID(), vote, result);
3890b57cec5SDimitry Andric       }
3900b57cec5SDimitry Andric       break;
3910b57cec5SDimitry Andric     }
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric   LLDB_LOG(log, "Returning {0}", result);
3940b57cec5SDimitry Andric   return result;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric void ThreadList::SetShouldReportStop(Vote vote) {
3980b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   m_process->UpdateThreadListIfNeeded();
4010b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
4020b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
4030b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
4040b57cec5SDimitry Andric     thread_sp->SetShouldReportStop(vote);
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric Vote ThreadList::ShouldReportRun(Event *event_ptr) {
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   Vote result = eVoteNoOpinion;
4130b57cec5SDimitry Andric   m_process->UpdateThreadListIfNeeded();
4140b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   // Run through the threads and ask whether we should report this event. The
4170b57cec5SDimitry Andric   // rule is NO vote wins over everything, a YES vote wins over no opinion.
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
4220b57cec5SDimitry Andric     if ((*pos)->GetResumeState() != eStateSuspended) {
4230b57cec5SDimitry Andric       switch ((*pos)->ShouldReportRun(event_ptr)) {
4240b57cec5SDimitry Andric       case eVoteNoOpinion:
4250b57cec5SDimitry Andric         continue;
4260b57cec5SDimitry Andric       case eVoteYes:
4270b57cec5SDimitry Andric         if (result == eVoteNoOpinion)
4280b57cec5SDimitry Andric           result = eVoteYes;
4290b57cec5SDimitry Andric         break;
4300b57cec5SDimitry Andric       case eVoteNo:
4319dba64beSDimitry Andric         LLDB_LOGF(log,
4329dba64beSDimitry Andric                   "ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64
4330b57cec5SDimitry Andric                   ") says don't report.",
4340b57cec5SDimitry Andric                   (*pos)->GetIndexID(), (*pos)->GetID());
4350b57cec5SDimitry Andric         result = eVoteNo;
4360b57cec5SDimitry Andric         break;
4370b57cec5SDimitry Andric       }
4380b57cec5SDimitry Andric     }
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric   return result;
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric void ThreadList::Clear() {
4440b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4450b57cec5SDimitry Andric   m_stop_id = 0;
4460b57cec5SDimitry Andric   m_threads.clear();
4470b57cec5SDimitry Andric   m_selected_tid = LLDB_INVALID_THREAD_ID;
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric void ThreadList::Destroy() {
4510b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4520b57cec5SDimitry Andric   const uint32_t num_threads = m_threads.size();
4530b57cec5SDimitry Andric   for (uint32_t idx = 0; idx < num_threads; ++idx) {
4540b57cec5SDimitry Andric     m_threads[idx]->DestroyThread();
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric void ThreadList::RefreshStateAfterStop() {
4590b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   m_process->UpdateThreadListIfNeeded();
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
4640b57cec5SDimitry Andric   if (log && log->GetVerbose())
4659dba64beSDimitry Andric     LLDB_LOGF(log,
4669dba64beSDimitry Andric               "Turning off notification of new threads while single stepping "
4670b57cec5SDimitry Andric               "a thread.");
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
4700b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos)
4710b57cec5SDimitry Andric     (*pos)->RefreshStateAfterStop();
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric void ThreadList::DiscardThreadPlans() {
4750b57cec5SDimitry Andric   // You don't need to update the thread list here, because only threads that
4760b57cec5SDimitry Andric   // you currently know about have any thread plans.
4770b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
4800b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos)
4810b57cec5SDimitry Andric     (*pos)->DiscardThreadPlans(true);
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric bool ThreadList::WillResume() {
4850b57cec5SDimitry Andric   // Run through the threads and perform their momentary actions. But we only
4860b57cec5SDimitry Andric   // do this for threads that are running, user suspended threads stay where
4870b57cec5SDimitry Andric   // they are.
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
4900b57cec5SDimitry Andric   m_process->UpdateThreadListIfNeeded();
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   // See if any thread wants to run stopping others.  If it does, then we won't
4950b57cec5SDimitry Andric   // setup the other threads for resume, since they aren't going to get a
4960b57cec5SDimitry Andric   // chance to run.  This is necessary because the SetupForResume might add
4970b57cec5SDimitry Andric   // "StopOthers" plans which would then get to be part of the who-gets-to-run
4980b57cec5SDimitry Andric   // negotiation, but they're coming in after the fact, and the threads that
4990b57cec5SDimitry Andric   // are already set up should take priority.
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   bool wants_solo_run = false;
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
5040b57cec5SDimitry Andric     lldbassert((*pos)->GetCurrentPlan() &&
5050b57cec5SDimitry Andric                "thread should not have null thread plan");
5060b57cec5SDimitry Andric     if ((*pos)->GetResumeState() != eStateSuspended &&
5070b57cec5SDimitry Andric         (*pos)->GetCurrentPlan()->StopOthers()) {
5080b57cec5SDimitry Andric       if ((*pos)->IsOperatingSystemPluginThread() &&
5090b57cec5SDimitry Andric           !(*pos)->GetBackingThread())
5100b57cec5SDimitry Andric         continue;
5110b57cec5SDimitry Andric       wants_solo_run = true;
5120b57cec5SDimitry Andric       break;
5130b57cec5SDimitry Andric     }
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   if (wants_solo_run) {
5170b57cec5SDimitry Andric     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
5180b57cec5SDimitry Andric     if (log && log->GetVerbose())
5199dba64beSDimitry Andric       LLDB_LOGF(log, "Turning on notification of new threads while single "
5200b57cec5SDimitry Andric                      "stepping a thread.");
5210b57cec5SDimitry Andric     m_process->StartNoticingNewThreads();
5220b57cec5SDimitry Andric   } else {
5230b57cec5SDimitry Andric     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
5240b57cec5SDimitry Andric     if (log && log->GetVerbose())
5259dba64beSDimitry Andric       LLDB_LOGF(log, "Turning off notification of new threads while single "
5260b57cec5SDimitry Andric                      "stepping a thread.");
5270b57cec5SDimitry Andric     m_process->StopNoticingNewThreads();
5280b57cec5SDimitry Andric   }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // Give all the threads that are likely to run a last chance to set up their
5310b57cec5SDimitry Andric   // state before we negotiate who is actually going to get a chance to run...
5320b57cec5SDimitry Andric   // Don't set to resume suspended threads, and if any thread wanted to stop
5330b57cec5SDimitry Andric   // others, only call setup on the threads that request StopOthers...
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
5360b57cec5SDimitry Andric     if ((*pos)->GetResumeState() != eStateSuspended &&
5370b57cec5SDimitry Andric         (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) {
5380b57cec5SDimitry Andric       if ((*pos)->IsOperatingSystemPluginThread() &&
5390b57cec5SDimitry Andric           !(*pos)->GetBackingThread())
5400b57cec5SDimitry Andric         continue;
5410b57cec5SDimitry Andric       (*pos)->SetupForResume();
5420b57cec5SDimitry Andric     }
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   // Now go through the threads and see if any thread wants to run just itself.
5460b57cec5SDimitry Andric   // if so then pick one and run it.
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   ThreadList run_me_only_list(m_process);
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   run_me_only_list.SetStopID(m_process->GetStopID());
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   bool run_only_current_thread = false;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
5550b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
5560b57cec5SDimitry Andric     if (thread_sp->GetResumeState() != eStateSuspended &&
5570b57cec5SDimitry Andric         thread_sp->GetCurrentPlan()->StopOthers()) {
5580b57cec5SDimitry Andric       if ((*pos)->IsOperatingSystemPluginThread() &&
5590b57cec5SDimitry Andric           !(*pos)->GetBackingThread())
5600b57cec5SDimitry Andric         continue;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric       // You can't say "stop others" and also want yourself to be suspended.
5630b57cec5SDimitry Andric       assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric       if (thread_sp == GetSelectedThread()) {
5660b57cec5SDimitry Andric         // If the currently selected thread wants to run on its own, always let
5670b57cec5SDimitry Andric         // it.
5680b57cec5SDimitry Andric         run_only_current_thread = true;
5690b57cec5SDimitry Andric         run_me_only_list.Clear();
5700b57cec5SDimitry Andric         run_me_only_list.AddThread(thread_sp);
5710b57cec5SDimitry Andric         break;
5720b57cec5SDimitry Andric       }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric       run_me_only_list.AddThread(thread_sp);
5750b57cec5SDimitry Andric     }
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   bool need_to_resume = true;
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   if (run_me_only_list.GetSize(false) == 0) {
5810b57cec5SDimitry Andric     // Everybody runs as they wish:
5820b57cec5SDimitry Andric     for (pos = m_threads.begin(); pos != end; ++pos) {
5830b57cec5SDimitry Andric       ThreadSP thread_sp(*pos);
5840b57cec5SDimitry Andric       StateType run_state;
5850b57cec5SDimitry Andric       if (thread_sp->GetResumeState() != eStateSuspended)
5860b57cec5SDimitry Andric         run_state = thread_sp->GetCurrentPlan()->RunState();
5870b57cec5SDimitry Andric       else
5880b57cec5SDimitry Andric         run_state = eStateSuspended;
5890b57cec5SDimitry Andric       if (!thread_sp->ShouldResume(run_state))
5900b57cec5SDimitry Andric         need_to_resume = false;
5910b57cec5SDimitry Andric     }
5920b57cec5SDimitry Andric   } else {
5930b57cec5SDimitry Andric     ThreadSP thread_to_run;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric     if (run_only_current_thread) {
5960b57cec5SDimitry Andric       thread_to_run = GetSelectedThread();
5970b57cec5SDimitry Andric     } else if (run_me_only_list.GetSize(false) == 1) {
5980b57cec5SDimitry Andric       thread_to_run = run_me_only_list.GetThreadAtIndex(0);
5990b57cec5SDimitry Andric     } else {
6000b57cec5SDimitry Andric       int random_thread =
6010b57cec5SDimitry Andric           (int)((run_me_only_list.GetSize(false) * (double)rand()) /
6020b57cec5SDimitry Andric                 (RAND_MAX + 1.0));
6030b57cec5SDimitry Andric       thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric     for (pos = m_threads.begin(); pos != end; ++pos) {
6070b57cec5SDimitry Andric       ThreadSP thread_sp(*pos);
6080b57cec5SDimitry Andric       if (thread_sp == thread_to_run) {
6090b57cec5SDimitry Andric         if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
6100b57cec5SDimitry Andric           need_to_resume = false;
6110b57cec5SDimitry Andric       } else
6120b57cec5SDimitry Andric         thread_sp->ShouldResume(eStateSuspended);
6130b57cec5SDimitry Andric     }
6140b57cec5SDimitry Andric   }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   return need_to_resume;
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric void ThreadList::DidResume() {
6200b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
6210b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
6220b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
6230b57cec5SDimitry Andric     // Don't clear out threads that aren't going to get a chance to run, rather
6240b57cec5SDimitry Andric     // leave their state for the next time around.
6250b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
6260b57cec5SDimitry Andric     if (thread_sp->GetResumeState() != eStateSuspended)
6270b57cec5SDimitry Andric       thread_sp->DidResume();
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric }
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric void ThreadList::DidStop() {
6320b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
6330b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
6340b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos) {
6350b57cec5SDimitry Andric     // Notify threads that the process just stopped. Note, this currently
6360b57cec5SDimitry Andric     // assumes that all threads in the list stop when the process stops.  In
6370b57cec5SDimitry Andric     // the future we will want to support a debugging model where some threads
6380b57cec5SDimitry Andric     // continue to run while others are stopped.  We either need to handle that
6390b57cec5SDimitry Andric     // somehow here or create a special thread list containing only threads
6400b57cec5SDimitry Andric     // which will stop in the code that calls this method (currently
6410b57cec5SDimitry Andric     // Process::SetPrivateState).
6420b57cec5SDimitry Andric     ThreadSP thread_sp(*pos);
6430b57cec5SDimitry Andric     if (StateIsRunningState(thread_sp->GetState()))
6440b57cec5SDimitry Andric       thread_sp->DidStop();
6450b57cec5SDimitry Andric   }
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric ThreadSP ThreadList::GetSelectedThread() {
6490b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
6500b57cec5SDimitry Andric   ThreadSP thread_sp = FindThreadByID(m_selected_tid);
6510b57cec5SDimitry Andric   if (!thread_sp.get()) {
6520b57cec5SDimitry Andric     if (m_threads.size() == 0)
6530b57cec5SDimitry Andric       return thread_sp;
6540b57cec5SDimitry Andric     m_selected_tid = m_threads[0]->GetID();
6550b57cec5SDimitry Andric     thread_sp = m_threads[0];
6560b57cec5SDimitry Andric   }
6570b57cec5SDimitry Andric   return thread_sp;
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) {
6610b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
6620b57cec5SDimitry Andric   ThreadSP selected_thread_sp(FindThreadByID(tid));
6630b57cec5SDimitry Andric   if (selected_thread_sp) {
6640b57cec5SDimitry Andric     m_selected_tid = tid;
6650b57cec5SDimitry Andric     selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
6660b57cec5SDimitry Andric   } else
6670b57cec5SDimitry Andric     m_selected_tid = LLDB_INVALID_THREAD_ID;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   if (notify)
6700b57cec5SDimitry Andric     NotifySelectedThreadChanged(m_selected_tid);
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   return m_selected_tid != LLDB_INVALID_THREAD_ID;
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) {
6760b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
6770b57cec5SDimitry Andric   ThreadSP selected_thread_sp(FindThreadByIndexID(index_id));
6780b57cec5SDimitry Andric   if (selected_thread_sp.get()) {
6790b57cec5SDimitry Andric     m_selected_tid = selected_thread_sp->GetID();
6800b57cec5SDimitry Andric     selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
6810b57cec5SDimitry Andric   } else
6820b57cec5SDimitry Andric     m_selected_tid = LLDB_INVALID_THREAD_ID;
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   if (notify)
6850b57cec5SDimitry Andric     NotifySelectedThreadChanged(m_selected_tid);
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   return m_selected_tid != LLDB_INVALID_THREAD_ID;
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
6910b57cec5SDimitry Andric   ThreadSP selected_thread_sp(FindThreadByID(tid));
6920b57cec5SDimitry Andric   if (selected_thread_sp->EventTypeHasListeners(
6930b57cec5SDimitry Andric           Thread::eBroadcastBitThreadSelected))
6940b57cec5SDimitry Andric     selected_thread_sp->BroadcastEvent(
6950b57cec5SDimitry Andric         Thread::eBroadcastBitThreadSelected,
6960b57cec5SDimitry Andric         new Thread::ThreadEventData(selected_thread_sp));
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric void ThreadList::Update(ThreadList &rhs) {
7000b57cec5SDimitry Andric   if (this != &rhs) {
7010b57cec5SDimitry Andric     // Lock both mutexes to make sure neither side changes anyone on us while
7020b57cec5SDimitry Andric     // the assignment occurs
7030b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(GetMutex());
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric     m_process = rhs.m_process;
7060b57cec5SDimitry Andric     m_stop_id = rhs.m_stop_id;
7070b57cec5SDimitry Andric     m_threads.swap(rhs.m_threads);
7080b57cec5SDimitry Andric     m_selected_tid = rhs.m_selected_tid;
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric     // Now we look for threads that we are done with and make sure to clear
7110b57cec5SDimitry Andric     // them up as much as possible so anyone with a shared pointer will still
7120b57cec5SDimitry Andric     // have a reference, but the thread won't be of much use. Using
7130b57cec5SDimitry Andric     // std::weak_ptr for all backward references (such as a thread to a
7140b57cec5SDimitry Andric     // process) will eventually solve this issue for us, but for now, we need
7150b57cec5SDimitry Andric     // to work around the issue
7160b57cec5SDimitry Andric     collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
7170b57cec5SDimitry Andric     for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
7185ffd83dbSDimitry Andric       // If this thread has already been destroyed, we don't need to look for
7195ffd83dbSDimitry Andric       // it to destroy it again.
7205ffd83dbSDimitry Andric       if (!(*rhs_pos)->IsValid())
7215ffd83dbSDimitry Andric         continue;
7225ffd83dbSDimitry Andric 
7230b57cec5SDimitry Andric       const lldb::tid_t tid = (*rhs_pos)->GetID();
7240b57cec5SDimitry Andric       bool thread_is_alive = false;
7250b57cec5SDimitry Andric       const uint32_t num_threads = m_threads.size();
7260b57cec5SDimitry Andric       for (uint32_t idx = 0; idx < num_threads; ++idx) {
7270b57cec5SDimitry Andric         ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
7280b57cec5SDimitry Andric         if (m_threads[idx]->GetID() == tid ||
7290b57cec5SDimitry Andric             (backing_thread && backing_thread->GetID() == tid)) {
7300b57cec5SDimitry Andric           thread_is_alive = true;
7310b57cec5SDimitry Andric           break;
7320b57cec5SDimitry Andric         }
7330b57cec5SDimitry Andric       }
7345ffd83dbSDimitry Andric       if (!thread_is_alive) {
7350b57cec5SDimitry Andric         (*rhs_pos)->DestroyThread();
7360b57cec5SDimitry Andric       }
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric   }
7395ffd83dbSDimitry Andric }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric void ThreadList::Flush() {
7420b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetMutex());
7430b57cec5SDimitry Andric   collection::iterator pos, end = m_threads.end();
7440b57cec5SDimitry Andric   for (pos = m_threads.begin(); pos != end; ++pos)
7450b57cec5SDimitry Andric     (*pos)->Flush();
7460b57cec5SDimitry Andric }
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric std::recursive_mutex &ThreadList::GetMutex() const {
7490b57cec5SDimitry Andric   return m_process->m_thread_mutex;
7500b57cec5SDimitry Andric }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher(
7530b57cec5SDimitry Andric     lldb::ThreadSP thread_sp)
7540b57cec5SDimitry Andric     : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) {
7550b57cec5SDimitry Andric   if (thread_sp) {
7560b57cec5SDimitry Andric     m_tid = thread_sp->GetID();
7570b57cec5SDimitry Andric     m_thread_list = &thread_sp->GetProcess()->GetThreadList();
7580b57cec5SDimitry Andric     m_thread_list->PushExpressionExecutionThread(m_tid);
7590b57cec5SDimitry Andric   }
7600b57cec5SDimitry Andric }
761