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