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 182cad65a5SGreg Clayton #include "lldb/Core/Log.h" 1929d65744SAndrew Kaylor #include "lldb/Core/State.h" 2030fdc8d8SChris Lattner #include "lldb/Target/Process.h" 21b9c1b51eSKate Stone #include "lldb/Target/RegisterContext.h" 22b9c1b51eSKate Stone #include "lldb/Target/Thread.h" 23b9c1b51eSKate Stone #include "lldb/Target/ThreadList.h" 24b9c1b51eSKate Stone #include "lldb/Target/ThreadPlan.h" 255023257fSZachary Turner #include "lldb/Utility/ConvertEnum.h" 268f186f85SZachary Turner #include "lldb/Utility/LLDBAssert.h" 2730fdc8d8SChris Lattner 2830fdc8d8SChris Lattner using namespace lldb; 2930fdc8d8SChris Lattner using namespace lldb_private; 3030fdc8d8SChris Lattner 31b9c1b51eSKate Stone ThreadList::ThreadList(Process *process) 32b9c1b51eSKate Stone : ThreadCollection(), m_process(process), m_stop_id(0), 33b9c1b51eSKate Stone m_selected_tid(LLDB_INVALID_THREAD_ID) {} 3430fdc8d8SChris Lattner 35b9c1b51eSKate Stone ThreadList::ThreadList(const ThreadList &rhs) 36b9c1b51eSKate Stone : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id), 37b9c1b51eSKate Stone m_selected_tid() { 3830fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 3930fdc8d8SChris Lattner *this = rhs; 4030fdc8d8SChris Lattner } 4130fdc8d8SChris Lattner 42b9c1b51eSKate Stone const ThreadList &ThreadList::operator=(const ThreadList &rhs) { 43b9c1b51eSKate Stone if (this != &rhs) { 4430fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 45e171da5cSBruce Mitchener // while the assignment occurs 46bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 47*b5cd6e7bSGreg Clayton std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex()); 48bb19a13cSSaleem Abdulrasool 4930fdc8d8SChris Lattner m_process = rhs.m_process; 5030fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5130fdc8d8SChris Lattner m_threads = rhs.m_threads; 522976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 5330fdc8d8SChris Lattner } 5430fdc8d8SChris Lattner return *this; 5530fdc8d8SChris Lattner } 5630fdc8d8SChris Lattner 57b9c1b51eSKate Stone ThreadList::~ThreadList() { 58ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 59ac358da5SGreg Clayton // which will ensure that if anyone is using the list 60ac358da5SGreg Clayton // they won't get it removed while using it. 61ac358da5SGreg Clayton Clear(); 6230fdc8d8SChris Lattner } 6330fdc8d8SChris Lattner 64b9c1b51eSKate Stone lldb::ThreadSP ThreadList::GetExpressionExecutionThread() { 658d94ba0fSJim Ingham if (m_expression_tid_stack.empty()) 668d94ba0fSJim Ingham return GetSelectedThread(); 678d94ba0fSJim Ingham ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back()); 688d94ba0fSJim Ingham if (expr_thread_sp) 698d94ba0fSJim Ingham return expr_thread_sp; 708d94ba0fSJim Ingham else 718d94ba0fSJim Ingham return GetSelectedThread(); 728d94ba0fSJim Ingham } 738d94ba0fSJim Ingham 74b9c1b51eSKate Stone void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) { 758d94ba0fSJim Ingham m_expression_tid_stack.push_back(tid); 768d94ba0fSJim Ingham } 778d94ba0fSJim Ingham 78b9c1b51eSKate Stone void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) { 798d94ba0fSJim Ingham assert(m_expression_tid_stack.back() == tid); 808d94ba0fSJim Ingham m_expression_tid_stack.pop_back(); 818d94ba0fSJim Ingham } 8230fdc8d8SChris Lattner 83b9c1b51eSKate Stone uint32_t ThreadList::GetStopID() const { return m_stop_id; } 8430fdc8d8SChris Lattner 85b9c1b51eSKate Stone void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; } 8630fdc8d8SChris Lattner 87b9c1b51eSKate Stone uint32_t ThreadList::GetSize(bool can_update) { 88bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 89bb19a13cSSaleem Abdulrasool 9030fdc8d8SChris Lattner if (can_update) 9130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9230fdc8d8SChris Lattner return m_threads.size(); 9330fdc8d8SChris Lattner } 9430fdc8d8SChris Lattner 95b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) { 96bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 97bb19a13cSSaleem Abdulrasool 9830fdc8d8SChris Lattner if (can_update) 9930fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 10030fdc8d8SChris Lattner 10130fdc8d8SChris Lattner ThreadSP thread_sp; 10230fdc8d8SChris Lattner if (idx < m_threads.size()) 10330fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10430fdc8d8SChris Lattner return thread_sp; 10530fdc8d8SChris Lattner } 10630fdc8d8SChris Lattner 107b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) { 108bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner if (can_update) 11130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11230fdc8d8SChris Lattner 11330fdc8d8SChris Lattner ThreadSP thread_sp; 11430fdc8d8SChris Lattner uint32_t idx = 0; 11530fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 116b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 117b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid) { 11830fdc8d8SChris Lattner thread_sp = m_threads[idx]; 11930fdc8d8SChris Lattner break; 12030fdc8d8SChris Lattner } 12130fdc8d8SChris Lattner } 12230fdc8d8SChris Lattner return thread_sp; 12330fdc8d8SChris Lattner } 12430fdc8d8SChris Lattner 125b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) { 126bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 127160c9d81SGreg Clayton 128160c9d81SGreg Clayton if (can_update) 129160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 130160c9d81SGreg Clayton 131160c9d81SGreg Clayton ThreadSP thread_sp; 132160c9d81SGreg Clayton uint32_t idx = 0; 133160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 134b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 135b9c1b51eSKate Stone if (m_threads[idx]->GetProtocolID() == tid) { 136160c9d81SGreg Clayton thread_sp = m_threads[idx]; 137160c9d81SGreg Clayton break; 138160c9d81SGreg Clayton } 139160c9d81SGreg Clayton } 140160c9d81SGreg Clayton return thread_sp; 141160c9d81SGreg Clayton } 142160c9d81SGreg Clayton 143b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) { 144bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 145c2c423eaSHan Ming Ong 146c2c423eaSHan Ming Ong if (can_update) 147c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 148c2c423eaSHan Ming Ong 149c2c423eaSHan Ming Ong ThreadSP thread_sp; 150c2c423eaSHan Ming Ong uint32_t idx = 0; 151c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 152b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 153b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid) { 154c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 155c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin() + idx); 156c2c423eaSHan Ming Ong break; 157c2c423eaSHan Ming Ong } 158c2c423eaSHan Ming Ong } 159c2c423eaSHan Ming Ong return thread_sp; 160c2c423eaSHan Ming Ong } 161c2c423eaSHan Ming Ong 162b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid, 163b9c1b51eSKate Stone bool can_update) { 164bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 165160c9d81SGreg Clayton 166160c9d81SGreg Clayton if (can_update) 167160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 168160c9d81SGreg Clayton 169160c9d81SGreg Clayton ThreadSP thread_sp; 170160c9d81SGreg Clayton uint32_t idx = 0; 171160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 172b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 173b9c1b51eSKate Stone if (m_threads[idx]->GetProtocolID() == tid) { 174160c9d81SGreg Clayton thread_sp = m_threads[idx]; 175160c9d81SGreg Clayton m_threads.erase(m_threads.begin() + idx); 176160c9d81SGreg Clayton break; 177160c9d81SGreg Clayton } 178160c9d81SGreg Clayton } 179160c9d81SGreg Clayton return thread_sp; 180160c9d81SGreg Clayton } 181160c9d81SGreg Clayton 182b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) { 18330fdc8d8SChris Lattner ThreadSP thread_sp; 184b9c1b51eSKate Stone if (thread_ptr) { 185bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 18630fdc8d8SChris Lattner 18730fdc8d8SChris Lattner uint32_t idx = 0; 18830fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 189b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 190b9c1b51eSKate Stone if (m_threads[idx].get() == thread_ptr) { 19130fdc8d8SChris Lattner thread_sp = m_threads[idx]; 19230fdc8d8SChris Lattner break; 19330fdc8d8SChris Lattner } 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner } 19630fdc8d8SChris Lattner return thread_sp; 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner 199b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) { 200bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 20130fdc8d8SChris Lattner 20230fdc8d8SChris Lattner if (can_update) 20330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 20430fdc8d8SChris Lattner 20530fdc8d8SChris Lattner ThreadSP thread_sp; 20630fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 207b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 208b9c1b51eSKate Stone if (m_threads[idx]->GetIndexID() == index_id) { 20930fdc8d8SChris Lattner thread_sp = m_threads[idx]; 21030fdc8d8SChris Lattner break; 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner return thread_sp; 21430fdc8d8SChris Lattner } 21530fdc8d8SChris Lattner 216b9c1b51eSKate Stone bool ThreadList::ShouldStop(Event *event_ptr) { 21730fdc8d8SChris Lattner // Running events should never stop, obviously... 21830fdc8d8SChris Lattner 2195160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 22030fdc8d8SChris Lattner 221b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 22235878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 223b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 224b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 2252f8e4c3bSAdrian McCarthy // to be created. If that happens, we will miss asking them whether 2262f8e4c3bSAdrian McCarthy // they should stop. This is not a big deal since we haven't had 227b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 22830fdc8d8SChris Lattner 229b42f3af3SJim Ingham collection threads_copy; 230b42f3af3SJim Ingham { 231b42f3af3SJim Ingham // Scope for locker 232bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 233b42f3af3SJim Ingham 234b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 235b9c1b51eSKate Stone for (lldb::ThreadSP thread_sp : m_threads) { 236b9c1b51eSKate Stone // This is an optimization... If we didn't let a thread run in between 237b9c1b51eSKate Stone // the previous stop and this 238b9c1b51eSKate Stone // one, we shouldn't have to consult it for ShouldStop. So just leave it 239b9c1b51eSKate Stone // off the list we are going to 240569aaf9eSJim Ingham // inspect. 241b9c1b51eSKate Stone // On Linux, if a thread-specific conditional breakpoint was hit, it won't 242b9c1b51eSKate Stone // necessarily be the thread 243b9c1b51eSKate Stone // that hit the breakpoint itself that evaluates the conditional 244b9c1b51eSKate Stone // expression, so the thread that hit 245b9c1b51eSKate Stone // the breakpoint could still be asked to stop, even though it hasn't been 246b9c1b51eSKate Stone // allowed to run since the 2476e8fbc6fSChaoren Lin // previous stop. 248b9c1b51eSKate Stone if (thread_sp->GetTemporaryResumeState() != eStateSuspended || 249b9c1b51eSKate Stone thread_sp->IsStillAtLastBreakpointHit()) 250569aaf9eSJim Ingham threads_copy.push_back(thread_sp); 251569aaf9eSJim Ingham } 252569aaf9eSJim Ingham 253b9c1b51eSKate Stone // It is possible the threads we were allowing to run all exited and then 254b9c1b51eSKate Stone // maybe the user interrupted 255569aaf9eSJim Ingham // or something, then fall back on looking at all threads: 256569aaf9eSJim Ingham 257569aaf9eSJim Ingham if (threads_copy.size() == 0) 258b42f3af3SJim Ingham threads_copy = m_threads; 259b42f3af3SJim Ingham } 260b42f3af3SJim Ingham 261b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 26230fdc8d8SChris Lattner 263b9c1b51eSKate Stone if (log) { 26410c4b249SJim Ingham log->PutCString(""); 265b9c1b51eSKate Stone log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 266b9c1b51eSKate Stone " unsuspended threads", 267b9c1b51eSKate Stone __FUNCTION__, (uint64_t)m_threads.size(), 268569aaf9eSJim Ingham (uint64_t)threads_copy.size()); 26910c4b249SJim Ingham } 2702cad65a5SGreg Clayton 271a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 27235878c47SJim Ingham 273b9c1b51eSKate Stone // If the event is an Interrupt event, then we're going to stop no matter 274b9c1b51eSKate Stone // what. Otherwise, presume we won't stop. 275a0079044SJim Ingham bool should_stop = false; 276b9c1b51eSKate Stone if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { 27735878c47SJim Ingham if (log) 278b9c1b51eSKate Stone log->Printf( 279b9c1b51eSKate Stone "ThreadList::%s handling interrupt event, should stop set to true", 280b9c1b51eSKate Stone __FUNCTION__); 28135878c47SJim Ingham 28235878c47SJim Ingham should_stop = true; 28335878c47SJim Ingham } 2847bc3465fSJim Ingham 285b9c1b51eSKate Stone // Now we run through all the threads and get their stop info's. We want to 286b9c1b51eSKate Stone // make sure to do this first before 287b9c1b51eSKate Stone // we start running the ShouldStop, because one thread's ShouldStop could 288b9c1b51eSKate Stone // destroy information (like deleting a 289b9c1b51eSKate Stone // thread specific breakpoint another thread had stopped at) which could lead 290b9c1b51eSKate Stone // us to compute the StopInfo incorrectly. 2917bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 2927bc3465fSJim Ingham 293b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 2947bc3465fSJim Ingham ThreadSP thread_sp(*pos); 2957bc3465fSJim Ingham thread_sp->GetStopInfo(); 2967bc3465fSJim Ingham } 297a0079044SJim Ingham 298b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 29930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 3002cad65a5SGreg Clayton 301b9c1b51eSKate Stone // We should never get a stop for which no thread had a stop reason, but 302b9c1b51eSKate Stone // sometimes we do see this - 303b9c1b51eSKate Stone // for instance when we first connect to a remote stub. In that case we 304b9c1b51eSKate Stone // should stop, since we can't figure out 305b9c1b51eSKate Stone // the right thing to do and stopping gives the user control over what to do 306b9c1b51eSKate Stone // in this instance. 30739fdae7fSJim Ingham // 308b9c1b51eSKate Stone // Note, this causes a problem when you have a thread specific breakpoint, 309b9c1b51eSKate Stone // and a bunch of threads hit the breakpoint, 310b9c1b51eSKate Stone // but not the thread which we are waiting for. All the threads that are 311b9c1b51eSKate Stone // not "supposed" to hit the breakpoint 312b9c1b51eSKate Stone // are marked as having no stop reason, which is right, they should not show 313b9c1b51eSKate Stone // a stop reason. But that triggers this 31439fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 31539fdae7fSJim Ingham // 316b9c1b51eSKate Stone // Since the only way we ever saw this error was on first attach, I'm only 317b9c1b51eSKate Stone // going to trigger set did_anybody_stop_for_a_reason 31839fdae7fSJim Ingham // to true unless this is the first stop. 31939fdae7fSJim Ingham // 320b9c1b51eSKate Stone // If this becomes a problem, we'll have to have another StopReason like 321b9c1b51eSKate Stone // "StopInfoHidden" which will look invalid 32239fdae7fSJim Ingham // everywhere but at this check. 32339fdae7fSJim Ingham 32421afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 32539fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 32639fdae7fSJim Ingham else 327a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 328a0079044SJim Ingham 32910c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3302cad65a5SGreg Clayton if (thread_should_stop) 3312cad65a5SGreg Clayton should_stop |= true; 3322cad65a5SGreg Clayton } 3332cad65a5SGreg Clayton 334b9c1b51eSKate Stone if (!should_stop && !did_anybody_stop_for_a_reason) { 335a0079044SJim Ingham should_stop = true; 336a0079044SJim Ingham if (log) 337b9c1b51eSKate Stone log->Printf("ThreadList::%s we stopped but no threads had a stop reason, " 338b9c1b51eSKate Stone "overriding should_stop and stopping.", 339b9c1b51eSKate Stone __FUNCTION__); 340a0079044SJim Ingham } 341a0079044SJim Ingham 3422cad65a5SGreg Clayton if (log) 343b9c1b51eSKate Stone log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__, 344b9c1b51eSKate Stone should_stop); 3452cad65a5SGreg Clayton 346b9c1b51eSKate Stone if (should_stop) { 347b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 34830fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 34930fdc8d8SChris Lattner thread_sp->WillStop(); 35030fdc8d8SChris Lattner } 35130fdc8d8SChris Lattner } 35230fdc8d8SChris Lattner 35330fdc8d8SChris Lattner return should_stop; 35430fdc8d8SChris Lattner } 35530fdc8d8SChris Lattner 356b9c1b51eSKate Stone Vote ThreadList::ShouldReportStop(Event *event_ptr) { 357bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 3582cad65a5SGreg Clayton 35930fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 36030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 36130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 36230fdc8d8SChris Lattner 3635160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 3642cad65a5SGreg Clayton 3652cad65a5SGreg Clayton if (log) 366b9c1b51eSKate Stone log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, 367b9c1b51eSKate Stone (uint64_t)m_threads.size()); 3682cad65a5SGreg Clayton 36930fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 370b9c1b51eSKate Stone // For stopping, a YES vote wins over everything. A NO vote wins over NO 371b9c1b51eSKate Stone // opinion. 372b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 37330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 374e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop(event_ptr); 375b9c1b51eSKate Stone switch (vote) { 37630fdc8d8SChris Lattner case eVoteNoOpinion: 37730fdc8d8SChris Lattner continue; 3782cad65a5SGreg Clayton 37930fdc8d8SChris Lattner case eVoteYes: 38030fdc8d8SChris Lattner result = eVoteYes; 38130fdc8d8SChris Lattner break; 3822cad65a5SGreg Clayton 38330fdc8d8SChris Lattner case eVoteNo: 384b9c1b51eSKate Stone if (result == eVoteNoOpinion) { 38530fdc8d8SChris Lattner result = eVoteNo; 386b9c1b51eSKate Stone } else { 3872cad65a5SGreg Clayton if (log) 388b9c1b51eSKate Stone log->Printf("ThreadList::%s thread 0x%4.4" PRIx64 389b9c1b51eSKate Stone ": voted %s, but lost out because result was %s", 390b9c1b51eSKate Stone __FUNCTION__, thread_sp->GetID(), GetVoteAsCString(vote), 3912cad65a5SGreg Clayton GetVoteAsCString(result)); 3922cad65a5SGreg Clayton } 39330fdc8d8SChris Lattner break; 39430fdc8d8SChris Lattner } 39530fdc8d8SChris Lattner } 3962cad65a5SGreg Clayton if (log) 397b9c1b51eSKate Stone log->Printf("ThreadList::%s returning %s", __FUNCTION__, 398b9c1b51eSKate Stone GetVoteAsCString(result)); 39930fdc8d8SChris Lattner return result; 40030fdc8d8SChris Lattner } 40130fdc8d8SChris Lattner 402b9c1b51eSKate Stone void ThreadList::SetShouldReportStop(Vote vote) { 403bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 404bb19a13cSSaleem Abdulrasool 405221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 406221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 407b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 408221d51cfSJim Ingham ThreadSP thread_sp(*pos); 409221d51cfSJim Ingham thread_sp->SetShouldReportStop(vote); 410221d51cfSJim Ingham } 411221d51cfSJim Ingham } 412221d51cfSJim Ingham 413b9c1b51eSKate Stone Vote ThreadList::ShouldReportRun(Event *event_ptr) { 4142cad65a5SGreg Clayton 415bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 4162cad65a5SGreg Clayton 41730fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 41830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 41930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 42030fdc8d8SChris Lattner 42130fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 42230fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 42330fdc8d8SChris Lattner 4245160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 425ce579839SJim Ingham 426b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 427b9c1b51eSKate Stone if ((*pos)->GetResumeState() != eStateSuspended) { 428b9c1b51eSKate Stone switch ((*pos)->ShouldReportRun(event_ptr)) { 42930fdc8d8SChris Lattner case eVoteNoOpinion: 43030fdc8d8SChris Lattner continue; 43130fdc8d8SChris Lattner case eVoteYes: 43230fdc8d8SChris Lattner if (result == eVoteNoOpinion) 43330fdc8d8SChris Lattner result = eVoteYes; 43430fdc8d8SChris Lattner break; 43530fdc8d8SChris Lattner case eVoteNo: 436abcbc8acSGreg Clayton if (log) 437b9c1b51eSKate Stone log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 438b9c1b51eSKate Stone ") says don't report.", 439b9c1b51eSKate Stone (*pos)->GetIndexID(), (*pos)->GetID()); 44030fdc8d8SChris Lattner result = eVoteNo; 44130fdc8d8SChris Lattner break; 44230fdc8d8SChris Lattner } 44330fdc8d8SChris Lattner } 444ce579839SJim Ingham } 44530fdc8d8SChris Lattner return result; 44630fdc8d8SChris Lattner } 44730fdc8d8SChris Lattner 448b9c1b51eSKate Stone void ThreadList::Clear() { 449bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 45030fdc8d8SChris Lattner m_stop_id = 0; 45130fdc8d8SChris Lattner m_threads.clear(); 4522976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 45330fdc8d8SChris Lattner } 45430fdc8d8SChris Lattner 455b9c1b51eSKate Stone void ThreadList::Destroy() { 456bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 457e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 458b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 459e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 460e1cd1be6SGreg Clayton } 461e1cd1be6SGreg Clayton } 462e1cd1be6SGreg Clayton 463b9c1b51eSKate Stone void ThreadList::RefreshStateAfterStop() { 464bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 46530fdc8d8SChris Lattner 46630fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 46730fdc8d8SChris Lattner 4685160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 46910c4b249SJim Ingham if (log && log->GetVerbose()) 470b9c1b51eSKate Stone log->Printf("Turning off notification of new threads while single stepping " 471b9c1b51eSKate Stone "a thread."); 4721c823b43SJim Ingham 47330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 47430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 47530fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop(); 47630fdc8d8SChris Lattner } 47730fdc8d8SChris Lattner 478b9c1b51eSKate Stone void ThreadList::DiscardThreadPlans() { 47930fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 48030fdc8d8SChris Lattner // that you currently know about have any thread plans. 481bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 48230fdc8d8SChris Lattner 48330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 48430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 48530fdc8d8SChris Lattner (*pos)->DiscardThreadPlans(true); 48630fdc8d8SChris Lattner } 48730fdc8d8SChris Lattner 488b9c1b51eSKate Stone bool ThreadList::WillResume() { 48930fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 49030fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 49130fdc8d8SChris Lattner // threads stay where they are. 49230fdc8d8SChris Lattner 493bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 49430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 49530fdc8d8SChris Lattner 49630fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 49730fdc8d8SChris Lattner 498a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 499a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 500b9c1b51eSKate Stone // to run. This is necessary because the SetupForResume might add 501b9c1b51eSKate Stone // "StopOthers" 502b9c1b51eSKate Stone // plans which would then get to be part of the who-gets-to-run negotiation, 503b9c1b51eSKate Stone // but 504b9c1b51eSKate Stone // they're coming in after the fact, and the threads that are already set up 505b9c1b51eSKate Stone // should 506a3241c1bSJim Ingham // take priority. 507a3241c1bSJim Ingham 508a3241c1bSJim Ingham bool wants_solo_run = false; 50930fdc8d8SChris Lattner 510b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 511b9c1b51eSKate Stone lldbassert((*pos)->GetCurrentPlan() && 512b9c1b51eSKate Stone "thread should not have null thread plan"); 5138f186f85SZachary Turner if ((*pos)->GetResumeState() != eStateSuspended && 514b9c1b51eSKate Stone (*pos)->GetCurrentPlan()->StopOthers()) { 515b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 516b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5176e0ff1a3SGreg Clayton continue; 518a3241c1bSJim Ingham wants_solo_run = true; 519a3241c1bSJim Ingham break; 520a3241c1bSJim Ingham } 521a3241c1bSJim Ingham } 522a3241c1bSJim Ingham 523b9c1b51eSKate Stone if (wants_solo_run) { 5245160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 52510c4b249SJim Ingham if (log && log->GetVerbose()) 526b9c1b51eSKate Stone log->Printf("Turning on notification of new threads while single " 527b9c1b51eSKate Stone "stepping a thread."); 5281c823b43SJim Ingham m_process->StartNoticingNewThreads(); 529b9c1b51eSKate Stone } else { 5305160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 53110c4b249SJim Ingham if (log && log->GetVerbose()) 532b9c1b51eSKate Stone log->Printf("Turning off notification of new threads while single " 533b9c1b51eSKate Stone "stepping a thread."); 5341c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5351c823b43SJim Ingham } 536a3241c1bSJim Ingham 537b9c1b51eSKate Stone // Give all the threads that are likely to run a last chance to set up their 538b9c1b51eSKate Stone // state before we 539a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 540b9c1b51eSKate Stone // Don't set to resume suspended threads, and if any thread wanted to stop 541b9c1b51eSKate Stone // others, only 542a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 543a3241c1bSJim Ingham 544b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 545b9c1b51eSKate Stone if ((*pos)->GetResumeState() != eStateSuspended && 546b9c1b51eSKate Stone (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) { 547b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 548b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5496e0ff1a3SGreg Clayton continue; 55030fdc8d8SChris Lattner (*pos)->SetupForResume(); 551a3241c1bSJim Ingham } 552a3241c1bSJim Ingham } 55330fdc8d8SChris Lattner 55430fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 55530fdc8d8SChris Lattner // if so then pick one and run it. 556a3241c1bSJim Ingham 55730fdc8d8SChris Lattner ThreadList run_me_only_list(m_process); 55830fdc8d8SChris Lattner 55930fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 56030fdc8d8SChris Lattner 56130fdc8d8SChris Lattner bool run_only_current_thread = false; 56230fdc8d8SChris Lattner 563b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 56430fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 565b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 566b9c1b51eSKate Stone thread_sp->GetCurrentPlan()->StopOthers()) { 567b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 568b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5696e0ff1a3SGreg Clayton continue; 5706e0ff1a3SGreg Clayton 57130fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 57230fdc8d8SChris Lattner assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 57330fdc8d8SChris Lattner 574b9c1b51eSKate Stone if (thread_sp == GetSelectedThread()) { 575b9c1b51eSKate Stone // If the currently selected thread wants to run on its own, always let 576b9c1b51eSKate Stone // it. 57730fdc8d8SChris Lattner run_only_current_thread = true; 57830fdc8d8SChris Lattner run_me_only_list.Clear(); 57930fdc8d8SChris Lattner run_me_only_list.AddThread(thread_sp); 58030fdc8d8SChris Lattner break; 58130fdc8d8SChris Lattner } 58230fdc8d8SChris Lattner 58330fdc8d8SChris Lattner run_me_only_list.AddThread(thread_sp); 58430fdc8d8SChris Lattner } 58530fdc8d8SChris Lattner } 58630fdc8d8SChris Lattner 587513c6bb8SJim Ingham bool need_to_resume = true; 588513c6bb8SJim Ingham 589b9c1b51eSKate Stone if (run_me_only_list.GetSize(false) == 0) { 59030fdc8d8SChris Lattner // Everybody runs as they wish: 591b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 59230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 593cb5d5a57SJim Ingham StateType run_state; 594cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 595cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 596cb5d5a57SJim Ingham else 597cb5d5a57SJim Ingham run_state = eStateSuspended; 598160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 599513c6bb8SJim Ingham need_to_resume = false; 60030fdc8d8SChris Lattner } 601b9c1b51eSKate Stone } else { 60230fdc8d8SChris Lattner ThreadSP thread_to_run; 60330fdc8d8SChris Lattner 604b9c1b51eSKate Stone if (run_only_current_thread) { 6052976d00aSJim Ingham thread_to_run = GetSelectedThread(); 606b9c1b51eSKate Stone } else if (run_me_only_list.GetSize(false) == 1) { 60730fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex(0); 608b9c1b51eSKate Stone } else { 609b9c1b51eSKate Stone int random_thread = 610b9c1b51eSKate Stone (int)((run_me_only_list.GetSize(false) * (double)rand()) / 611b9c1b51eSKate Stone (RAND_MAX + 1.0)); 61230fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread); 61330fdc8d8SChris Lattner } 61430fdc8d8SChris Lattner 615b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 61630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 617b9c1b51eSKate Stone if (thread_sp == thread_to_run) { 618160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 619513c6bb8SJim Ingham need_to_resume = false; 620b9c1b51eSKate Stone } else 621160c9d81SGreg Clayton thread_sp->ShouldResume(eStateSuspended); 62230fdc8d8SChris Lattner } 62330fdc8d8SChris Lattner } 62430fdc8d8SChris Lattner 625513c6bb8SJim Ingham return need_to_resume; 62630fdc8d8SChris Lattner } 62730fdc8d8SChris Lattner 628b9c1b51eSKate Stone void ThreadList::DidResume() { 629bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 63030fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 631b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 63230fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 63330fdc8d8SChris Lattner // leave their state for the next time around. 63430fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 63530fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 63630fdc8d8SChris Lattner thread_sp->DidResume(); 63730fdc8d8SChris Lattner } 63830fdc8d8SChris Lattner } 63930fdc8d8SChris Lattner 640b9c1b51eSKate Stone void ThreadList::DidStop() { 641bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 64229d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 643b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 64429d65744SAndrew Kaylor // Notify threads that the process just stopped. 64529d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 64629d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 64729d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 64829d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 64929d65744SAndrew Kaylor // create a special thread list containing only threads which will 65029d65744SAndrew Kaylor // stop in the code that calls this method (currently 65129d65744SAndrew Kaylor // Process::SetPrivateState). 65229d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 65329d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 65429d65744SAndrew Kaylor thread_sp->DidStop(); 65529d65744SAndrew Kaylor } 65629d65744SAndrew Kaylor } 65729d65744SAndrew Kaylor 658b9c1b51eSKate Stone ThreadSP ThreadList::GetSelectedThread() { 659bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 660943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 661b9c1b51eSKate Stone if (!thread_sp.get()) { 662354b9a65SJason Molenda if (m_threads.size() == 0) 663354b9a65SJason Molenda return thread_sp; 664943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 665943ddb73SJohnny Chen thread_sp = m_threads[0]; 666943ddb73SJohnny Chen } 667943ddb73SJohnny Chen return thread_sp; 66830fdc8d8SChris Lattner } 66930fdc8d8SChris Lattner 670b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) { 671bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 672b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 673b9c1b51eSKate Stone if (selected_thread_sp) { 6742976d00aSJim Ingham m_selected_tid = tid; 675b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 676b9c1b51eSKate Stone } else 6772976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 67830fdc8d8SChris Lattner 679c3faa195SJim Ingham if (notify) 680c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 681c3faa195SJim Ingham 6822976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 68330fdc8d8SChris Lattner } 68430fdc8d8SChris Lattner 685b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) { 686bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 687b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByIndexID(index_id)); 688b9c1b51eSKate Stone if (selected_thread_sp.get()) { 689b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 690b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 691b9c1b51eSKate Stone } else 6922976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 69330fdc8d8SChris Lattner 694c3faa195SJim Ingham if (notify) 695c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 696c3faa195SJim Ingham 6972976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 69830fdc8d8SChris Lattner } 69930fdc8d8SChris Lattner 700b9c1b51eSKate Stone void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) { 701c3faa195SJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 702b9c1b51eSKate Stone if (selected_thread_sp->EventTypeHasListeners( 703b9c1b51eSKate Stone Thread::eBroadcastBitThreadSelected)) 704b9c1b51eSKate Stone selected_thread_sp->BroadcastEvent( 705b9c1b51eSKate Stone Thread::eBroadcastBitThreadSelected, 706c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 707c3faa195SJim Ingham } 708c3faa195SJim Ingham 709b9c1b51eSKate Stone void ThreadList::Update(ThreadList &rhs) { 710b9c1b51eSKate Stone if (this != &rhs) { 71156d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 712e171da5cSBruce Mitchener // while the assignment occurs 713bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 714bb19a13cSSaleem Abdulrasool 71556d9a1b3SGreg Clayton m_process = rhs.m_process; 71656d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 71756d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 71856d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 719e1cd1be6SGreg Clayton 720e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 721e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 722e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 723e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 724e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 725e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 726e1cd1be6SGreg Clayton // need to work around the issue 727e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 728b9c1b51eSKate Stone for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) { 729e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 730e1cd1be6SGreg Clayton bool thread_is_alive = false; 731e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 732b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 73365d4d5c3SRyan Brown ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); 734b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid || 735b9c1b51eSKate Stone (backing_thread && backing_thread->GetID() == tid)) { 736e1cd1be6SGreg Clayton thread_is_alive = true; 737e1cd1be6SGreg Clayton break; 738e1cd1be6SGreg Clayton } 739e1cd1be6SGreg Clayton } 740e1cd1be6SGreg Clayton if (!thread_is_alive) 741e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 742e1cd1be6SGreg Clayton } 74356d9a1b3SGreg Clayton } 74456d9a1b3SGreg Clayton } 74556d9a1b3SGreg Clayton 746b9c1b51eSKate Stone void ThreadList::Flush() { 747bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 748fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 749fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 750fa559e5cSGreg Clayton (*pos)->Flush(); 751fa559e5cSGreg Clayton } 75256d9a1b3SGreg Clayton 753*b5cd6e7bSGreg Clayton std::recursive_mutex &ThreadList::GetMutex() const { 754ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 755ba4e61d3SAndrew Kaylor } 756ba4e61d3SAndrew Kaylor 757b9c1b51eSKate Stone ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher( 758b9c1b51eSKate Stone lldb::ThreadSP thread_sp) 759b9c1b51eSKate Stone : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) { 760b9c1b51eSKate Stone if (thread_sp) { 7618d94ba0fSJim Ingham m_tid = thread_sp->GetID(); 7628d94ba0fSJim Ingham m_thread_list = &thread_sp->GetProcess()->GetThreadList(); 7638d94ba0fSJim Ingham m_thread_list->PushExpressionExecutionThread(m_tid); 7648d94ba0fSJim Ingham } 7658d94ba0fSJim Ingham } 766