130fdc8d8SChris Lattner //===-- ThreadList.cpp ------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9e65b2cf2SEugene Zelenko 10e65b2cf2SEugene Zelenko // C Includes 1130fdc8d8SChris Lattner #include <stdlib.h> 1230fdc8d8SChris Lattner 13e65b2cf2SEugene Zelenko // C++ Includes 1430fdc8d8SChris Lattner #include <algorithm> 1530fdc8d8SChris Lattner 16e65b2cf2SEugene Zelenko // Other libraries and framework includes 17e65b2cf2SEugene Zelenko // Project includes 1829d65744SAndrew Kaylor #include "lldb/Core/State.h" 1930fdc8d8SChris Lattner #include "lldb/Target/Process.h" 20b9c1b51eSKate Stone #include "lldb/Target/RegisterContext.h" 21b9c1b51eSKate Stone #include "lldb/Target/Thread.h" 22b9c1b51eSKate Stone #include "lldb/Target/ThreadList.h" 23b9c1b51eSKate Stone #include "lldb/Target/ThreadPlan.h" 248f186f85SZachary Turner #include "lldb/Utility/LLDBAssert.h" 256f9e6901SZachary Turner #include "lldb/Utility/Log.h" 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner using namespace lldb; 2830fdc8d8SChris Lattner using namespace lldb_private; 2930fdc8d8SChris Lattner 30b9c1b51eSKate Stone ThreadList::ThreadList(Process *process) 31b9c1b51eSKate Stone : ThreadCollection(), m_process(process), m_stop_id(0), 32b9c1b51eSKate Stone m_selected_tid(LLDB_INVALID_THREAD_ID) {} 3330fdc8d8SChris Lattner 34b9c1b51eSKate Stone ThreadList::ThreadList(const ThreadList &rhs) 35b9c1b51eSKate Stone : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id), 36b9c1b51eSKate Stone m_selected_tid() { 3730fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 3830fdc8d8SChris Lattner *this = rhs; 3930fdc8d8SChris Lattner } 4030fdc8d8SChris Lattner 41b9c1b51eSKate Stone const ThreadList &ThreadList::operator=(const ThreadList &rhs) { 42b9c1b51eSKate Stone if (this != &rhs) { 4330fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 44e171da5cSBruce Mitchener // while the assignment occurs 45bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 46b5cd6e7bSGreg Clayton std::lock_guard<std::recursive_mutex> rhs_guard(rhs.GetMutex()); 47bb19a13cSSaleem Abdulrasool 4830fdc8d8SChris Lattner m_process = rhs.m_process; 4930fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5030fdc8d8SChris Lattner m_threads = rhs.m_threads; 512976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner return *this; 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner 56b9c1b51eSKate Stone ThreadList::~ThreadList() { 57ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 58ac358da5SGreg Clayton // which will ensure that if anyone is using the list 59ac358da5SGreg Clayton // they won't get it removed while using it. 60ac358da5SGreg Clayton Clear(); 6130fdc8d8SChris Lattner } 6230fdc8d8SChris Lattner 63b9c1b51eSKate Stone lldb::ThreadSP ThreadList::GetExpressionExecutionThread() { 648d94ba0fSJim Ingham if (m_expression_tid_stack.empty()) 658d94ba0fSJim Ingham return GetSelectedThread(); 668d94ba0fSJim Ingham ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back()); 678d94ba0fSJim Ingham if (expr_thread_sp) 688d94ba0fSJim Ingham return expr_thread_sp; 698d94ba0fSJim Ingham else 708d94ba0fSJim Ingham return GetSelectedThread(); 718d94ba0fSJim Ingham } 728d94ba0fSJim Ingham 73b9c1b51eSKate Stone void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) { 748d94ba0fSJim Ingham m_expression_tid_stack.push_back(tid); 758d94ba0fSJim Ingham } 768d94ba0fSJim Ingham 77b9c1b51eSKate Stone void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) { 788d94ba0fSJim Ingham assert(m_expression_tid_stack.back() == tid); 798d94ba0fSJim Ingham m_expression_tid_stack.pop_back(); 808d94ba0fSJim Ingham } 8130fdc8d8SChris Lattner 82b9c1b51eSKate Stone uint32_t ThreadList::GetStopID() const { return m_stop_id; } 8330fdc8d8SChris Lattner 84b9c1b51eSKate Stone void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; } 8530fdc8d8SChris Lattner 86b9c1b51eSKate Stone uint32_t ThreadList::GetSize(bool can_update) { 87bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 88bb19a13cSSaleem Abdulrasool 8930fdc8d8SChris Lattner if (can_update) 9030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9130fdc8d8SChris Lattner return m_threads.size(); 9230fdc8d8SChris Lattner } 9330fdc8d8SChris Lattner 94b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) { 95bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 96bb19a13cSSaleem Abdulrasool 9730fdc8d8SChris Lattner if (can_update) 9830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9930fdc8d8SChris Lattner 10030fdc8d8SChris Lattner ThreadSP thread_sp; 10130fdc8d8SChris Lattner if (idx < m_threads.size()) 10230fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10330fdc8d8SChris Lattner return thread_sp; 10430fdc8d8SChris Lattner } 10530fdc8d8SChris Lattner 106b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) { 107bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 10830fdc8d8SChris Lattner 10930fdc8d8SChris Lattner if (can_update) 11030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner ThreadSP thread_sp; 11330fdc8d8SChris Lattner uint32_t idx = 0; 11430fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 115b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 116b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid) { 11730fdc8d8SChris Lattner thread_sp = m_threads[idx]; 11830fdc8d8SChris Lattner break; 11930fdc8d8SChris Lattner } 12030fdc8d8SChris Lattner } 12130fdc8d8SChris Lattner return thread_sp; 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner 124b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) { 125bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 126160c9d81SGreg Clayton 127160c9d81SGreg Clayton if (can_update) 128160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 129160c9d81SGreg Clayton 130160c9d81SGreg Clayton ThreadSP thread_sp; 131160c9d81SGreg Clayton uint32_t idx = 0; 132160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 133b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 134b9c1b51eSKate Stone if (m_threads[idx]->GetProtocolID() == tid) { 135160c9d81SGreg Clayton thread_sp = m_threads[idx]; 136160c9d81SGreg Clayton break; 137160c9d81SGreg Clayton } 138160c9d81SGreg Clayton } 139160c9d81SGreg Clayton return thread_sp; 140160c9d81SGreg Clayton } 141160c9d81SGreg Clayton 142b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) { 143bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 144c2c423eaSHan Ming Ong 145c2c423eaSHan Ming Ong if (can_update) 146c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 147c2c423eaSHan Ming Ong 148c2c423eaSHan Ming Ong ThreadSP thread_sp; 149c2c423eaSHan Ming Ong uint32_t idx = 0; 150c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 151b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 152b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid) { 153c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 154c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin() + idx); 155c2c423eaSHan Ming Ong break; 156c2c423eaSHan Ming Ong } 157c2c423eaSHan Ming Ong } 158c2c423eaSHan Ming Ong return thread_sp; 159c2c423eaSHan Ming Ong } 160c2c423eaSHan Ming Ong 161b9c1b51eSKate Stone ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid, 162b9c1b51eSKate Stone bool can_update) { 163bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 164160c9d81SGreg Clayton 165160c9d81SGreg Clayton if (can_update) 166160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 167160c9d81SGreg Clayton 168160c9d81SGreg Clayton ThreadSP thread_sp; 169160c9d81SGreg Clayton uint32_t idx = 0; 170160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 171b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 172b9c1b51eSKate Stone if (m_threads[idx]->GetProtocolID() == tid) { 173160c9d81SGreg Clayton thread_sp = m_threads[idx]; 174160c9d81SGreg Clayton m_threads.erase(m_threads.begin() + idx); 175160c9d81SGreg Clayton break; 176160c9d81SGreg Clayton } 177160c9d81SGreg Clayton } 178160c9d81SGreg Clayton return thread_sp; 179160c9d81SGreg Clayton } 180160c9d81SGreg Clayton 181b9c1b51eSKate Stone ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) { 18230fdc8d8SChris Lattner ThreadSP thread_sp; 183b9c1b51eSKate Stone if (thread_ptr) { 184bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 18530fdc8d8SChris Lattner 18630fdc8d8SChris Lattner uint32_t idx = 0; 18730fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 188b9c1b51eSKate Stone for (idx = 0; idx < num_threads; ++idx) { 189b9c1b51eSKate Stone if (m_threads[idx].get() == thread_ptr) { 19030fdc8d8SChris Lattner thread_sp = m_threads[idx]; 19130fdc8d8SChris Lattner break; 19230fdc8d8SChris Lattner } 19330fdc8d8SChris Lattner } 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner return thread_sp; 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner 198*8db3f7edSJonas Devlieghere ThreadSP ThreadList::GetBackingThread(const ThreadSP &real_thread) { 199*8db3f7edSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(GetMutex()); 200*8db3f7edSJonas Devlieghere 201*8db3f7edSJonas Devlieghere ThreadSP thread_sp; 202*8db3f7edSJonas Devlieghere const uint32_t num_threads = m_threads.size(); 203*8db3f7edSJonas Devlieghere for (uint32_t idx = 0; idx < num_threads; ++idx) { 204*8db3f7edSJonas Devlieghere if (m_threads[idx]->GetBackingThread() == real_thread) { 205*8db3f7edSJonas Devlieghere thread_sp = m_threads[idx]; 206*8db3f7edSJonas Devlieghere break; 207*8db3f7edSJonas Devlieghere } 208*8db3f7edSJonas Devlieghere } 209*8db3f7edSJonas Devlieghere return thread_sp; 210*8db3f7edSJonas Devlieghere } 211*8db3f7edSJonas Devlieghere 212b9c1b51eSKate Stone ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) { 213bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 21430fdc8d8SChris Lattner 21530fdc8d8SChris Lattner if (can_update) 21630fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 21730fdc8d8SChris Lattner 21830fdc8d8SChris Lattner ThreadSP thread_sp; 21930fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 220b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 221b9c1b51eSKate Stone if (m_threads[idx]->GetIndexID() == index_id) { 22230fdc8d8SChris Lattner thread_sp = m_threads[idx]; 22330fdc8d8SChris Lattner break; 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner } 22630fdc8d8SChris Lattner return thread_sp; 22730fdc8d8SChris Lattner } 22830fdc8d8SChris Lattner 229b9c1b51eSKate Stone bool ThreadList::ShouldStop(Event *event_ptr) { 23030fdc8d8SChris Lattner // Running events should never stop, obviously... 23130fdc8d8SChris Lattner 2325160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 23330fdc8d8SChris Lattner 234b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 23535878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 236b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 237b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 2382f8e4c3bSAdrian McCarthy // to be created. If that happens, we will miss asking them whether 2392f8e4c3bSAdrian McCarthy // they should stop. This is not a big deal since we haven't had 240b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 24130fdc8d8SChris Lattner 242b42f3af3SJim Ingham collection threads_copy; 243b42f3af3SJim Ingham { 244b42f3af3SJim Ingham // Scope for locker 245bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 246b42f3af3SJim Ingham 247b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 248b9c1b51eSKate Stone for (lldb::ThreadSP thread_sp : m_threads) { 249b9c1b51eSKate Stone // This is an optimization... If we didn't let a thread run in between 250b9c1b51eSKate Stone // the previous stop and this 251b9c1b51eSKate Stone // one, we shouldn't have to consult it for ShouldStop. So just leave it 252b9c1b51eSKate Stone // off the list we are going to 253569aaf9eSJim Ingham // inspect. 254b9c1b51eSKate Stone // On Linux, if a thread-specific conditional breakpoint was hit, it won't 255b9c1b51eSKate Stone // necessarily be the thread 256b9c1b51eSKate Stone // that hit the breakpoint itself that evaluates the conditional 257b9c1b51eSKate Stone // expression, so the thread that hit 258b9c1b51eSKate Stone // the breakpoint could still be asked to stop, even though it hasn't been 259b9c1b51eSKate Stone // allowed to run since the 2606e8fbc6fSChaoren Lin // previous stop. 261b9c1b51eSKate Stone if (thread_sp->GetTemporaryResumeState() != eStateSuspended || 262b9c1b51eSKate Stone thread_sp->IsStillAtLastBreakpointHit()) 263569aaf9eSJim Ingham threads_copy.push_back(thread_sp); 264569aaf9eSJim Ingham } 265569aaf9eSJim Ingham 266b9c1b51eSKate Stone // It is possible the threads we were allowing to run all exited and then 267b9c1b51eSKate Stone // maybe the user interrupted 268569aaf9eSJim Ingham // or something, then fall back on looking at all threads: 269569aaf9eSJim Ingham 270569aaf9eSJim Ingham if (threads_copy.size() == 0) 271b42f3af3SJim Ingham threads_copy = m_threads; 272b42f3af3SJim Ingham } 273b42f3af3SJim Ingham 274b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 27530fdc8d8SChris Lattner 276b9c1b51eSKate Stone if (log) { 27710c4b249SJim Ingham log->PutCString(""); 278b9c1b51eSKate Stone log->Printf("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 279b9c1b51eSKate Stone " unsuspended threads", 280b9c1b51eSKate Stone __FUNCTION__, (uint64_t)m_threads.size(), 281569aaf9eSJim Ingham (uint64_t)threads_copy.size()); 28210c4b249SJim Ingham } 2832cad65a5SGreg Clayton 284a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 28535878c47SJim Ingham 286b9c1b51eSKate Stone // If the event is an Interrupt event, then we're going to stop no matter 287b9c1b51eSKate Stone // what. Otherwise, presume we won't stop. 288a0079044SJim Ingham bool should_stop = false; 289b9c1b51eSKate Stone if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { 29035878c47SJim Ingham if (log) 291b9c1b51eSKate Stone log->Printf( 292b9c1b51eSKate Stone "ThreadList::%s handling interrupt event, should stop set to true", 293b9c1b51eSKate Stone __FUNCTION__); 29435878c47SJim Ingham 29535878c47SJim Ingham should_stop = true; 29635878c47SJim Ingham } 2977bc3465fSJim Ingham 298b9c1b51eSKate Stone // Now we run through all the threads and get their stop info's. We want to 299b9c1b51eSKate Stone // make sure to do this first before 300b9c1b51eSKate Stone // we start running the ShouldStop, because one thread's ShouldStop could 301b9c1b51eSKate Stone // destroy information (like deleting a 302b9c1b51eSKate Stone // thread specific breakpoint another thread had stopped at) which could lead 303b9c1b51eSKate Stone // us to compute the StopInfo incorrectly. 3047bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 3057bc3465fSJim Ingham 306b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 3077bc3465fSJim Ingham ThreadSP thread_sp(*pos); 3087bc3465fSJim Ingham thread_sp->GetStopInfo(); 3097bc3465fSJim Ingham } 310a0079044SJim Ingham 311b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 31230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 3132cad65a5SGreg Clayton 314b9c1b51eSKate Stone // We should never get a stop for which no thread had a stop reason, but 315b9c1b51eSKate Stone // sometimes we do see this - 316b9c1b51eSKate Stone // for instance when we first connect to a remote stub. In that case we 317b9c1b51eSKate Stone // should stop, since we can't figure out 318b9c1b51eSKate Stone // the right thing to do and stopping gives the user control over what to do 319b9c1b51eSKate Stone // in this instance. 32039fdae7fSJim Ingham // 321b9c1b51eSKate Stone // Note, this causes a problem when you have a thread specific breakpoint, 322b9c1b51eSKate Stone // and a bunch of threads hit the breakpoint, 323b9c1b51eSKate Stone // but not the thread which we are waiting for. All the threads that are 324b9c1b51eSKate Stone // not "supposed" to hit the breakpoint 325b9c1b51eSKate Stone // are marked as having no stop reason, which is right, they should not show 326b9c1b51eSKate Stone // a stop reason. But that triggers this 32739fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 32839fdae7fSJim Ingham // 329b9c1b51eSKate Stone // Since the only way we ever saw this error was on first attach, I'm only 330b9c1b51eSKate Stone // going to trigger set did_anybody_stop_for_a_reason 33139fdae7fSJim Ingham // to true unless this is the first stop. 33239fdae7fSJim Ingham // 333b9c1b51eSKate Stone // If this becomes a problem, we'll have to have another StopReason like 334b9c1b51eSKate Stone // "StopInfoHidden" which will look invalid 33539fdae7fSJim Ingham // everywhere but at this check. 33639fdae7fSJim Ingham 33721afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 33839fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 33939fdae7fSJim Ingham else 340a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 341a0079044SJim Ingham 34210c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3432cad65a5SGreg Clayton if (thread_should_stop) 3442cad65a5SGreg Clayton should_stop |= true; 3452cad65a5SGreg Clayton } 3462cad65a5SGreg Clayton 347b9c1b51eSKate Stone if (!should_stop && !did_anybody_stop_for_a_reason) { 348a0079044SJim Ingham should_stop = true; 349a0079044SJim Ingham if (log) 350b9c1b51eSKate Stone log->Printf("ThreadList::%s we stopped but no threads had a stop reason, " 351b9c1b51eSKate Stone "overriding should_stop and stopping.", 352b9c1b51eSKate Stone __FUNCTION__); 353a0079044SJim Ingham } 354a0079044SJim Ingham 3552cad65a5SGreg Clayton if (log) 356b9c1b51eSKate Stone log->Printf("ThreadList::%s overall should_stop = %i", __FUNCTION__, 357b9c1b51eSKate Stone should_stop); 3582cad65a5SGreg Clayton 359b9c1b51eSKate Stone if (should_stop) { 360b9c1b51eSKate Stone for (pos = threads_copy.begin(); pos != end; ++pos) { 36130fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 36230fdc8d8SChris Lattner thread_sp->WillStop(); 36330fdc8d8SChris Lattner } 36430fdc8d8SChris Lattner } 36530fdc8d8SChris Lattner 36630fdc8d8SChris Lattner return should_stop; 36730fdc8d8SChris Lattner } 36830fdc8d8SChris Lattner 369b9c1b51eSKate Stone Vote ThreadList::ShouldReportStop(Event *event_ptr) { 370bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 3712cad65a5SGreg Clayton 37230fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 37330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 37430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 37530fdc8d8SChris Lattner 3765160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 3772cad65a5SGreg Clayton 3782cad65a5SGreg Clayton if (log) 379b9c1b51eSKate Stone log->Printf("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, 380b9c1b51eSKate Stone (uint64_t)m_threads.size()); 3812cad65a5SGreg Clayton 38230fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 383b9c1b51eSKate Stone // For stopping, a YES vote wins over everything. A NO vote wins over NO 384b9c1b51eSKate Stone // opinion. 385b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 38630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 387e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop(event_ptr); 388b9c1b51eSKate Stone switch (vote) { 38930fdc8d8SChris Lattner case eVoteNoOpinion: 39030fdc8d8SChris Lattner continue; 3912cad65a5SGreg Clayton 39230fdc8d8SChris Lattner case eVoteYes: 39330fdc8d8SChris Lattner result = eVoteYes; 39430fdc8d8SChris Lattner break; 3952cad65a5SGreg Clayton 39630fdc8d8SChris Lattner case eVoteNo: 397b9c1b51eSKate Stone if (result == eVoteNoOpinion) { 39830fdc8d8SChris Lattner result = eVoteNo; 399b9c1b51eSKate Stone } else { 400df44988bSZachary Turner LLDB_LOG(log, 401df44988bSZachary Turner "Thread {0:x} voted {1}, but lost out because result was {2}", 402df44988bSZachary Turner thread_sp->GetID(), vote, result); 4032cad65a5SGreg Clayton } 40430fdc8d8SChris Lattner break; 40530fdc8d8SChris Lattner } 40630fdc8d8SChris Lattner } 407df44988bSZachary Turner LLDB_LOG(log, "Returning {0}", result); 40830fdc8d8SChris Lattner return result; 40930fdc8d8SChris Lattner } 41030fdc8d8SChris Lattner 411b9c1b51eSKate Stone void ThreadList::SetShouldReportStop(Vote vote) { 412bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 413bb19a13cSSaleem Abdulrasool 414221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 415221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 416b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 417221d51cfSJim Ingham ThreadSP thread_sp(*pos); 418221d51cfSJim Ingham thread_sp->SetShouldReportStop(vote); 419221d51cfSJim Ingham } 420221d51cfSJim Ingham } 421221d51cfSJim Ingham 422b9c1b51eSKate Stone Vote ThreadList::ShouldReportRun(Event *event_ptr) { 4232cad65a5SGreg Clayton 424bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 4252cad65a5SGreg Clayton 42630fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 42730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 42830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 42930fdc8d8SChris Lattner 43030fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 43130fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 43230fdc8d8SChris Lattner 4335160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 434ce579839SJim Ingham 435b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 436b9c1b51eSKate Stone if ((*pos)->GetResumeState() != eStateSuspended) { 437b9c1b51eSKate Stone switch ((*pos)->ShouldReportRun(event_ptr)) { 43830fdc8d8SChris Lattner case eVoteNoOpinion: 43930fdc8d8SChris Lattner continue; 44030fdc8d8SChris Lattner case eVoteYes: 44130fdc8d8SChris Lattner if (result == eVoteNoOpinion) 44230fdc8d8SChris Lattner result = eVoteYes; 44330fdc8d8SChris Lattner break; 44430fdc8d8SChris Lattner case eVoteNo: 445abcbc8acSGreg Clayton if (log) 446b9c1b51eSKate Stone log->Printf("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 447b9c1b51eSKate Stone ") says don't report.", 448b9c1b51eSKate Stone (*pos)->GetIndexID(), (*pos)->GetID()); 44930fdc8d8SChris Lattner result = eVoteNo; 45030fdc8d8SChris Lattner break; 45130fdc8d8SChris Lattner } 45230fdc8d8SChris Lattner } 453ce579839SJim Ingham } 45430fdc8d8SChris Lattner return result; 45530fdc8d8SChris Lattner } 45630fdc8d8SChris Lattner 457b9c1b51eSKate Stone void ThreadList::Clear() { 458bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 45930fdc8d8SChris Lattner m_stop_id = 0; 46030fdc8d8SChris Lattner m_threads.clear(); 4612976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 46230fdc8d8SChris Lattner } 46330fdc8d8SChris Lattner 464b9c1b51eSKate Stone void ThreadList::Destroy() { 465bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 466e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 467b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 468e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 469e1cd1be6SGreg Clayton } 470e1cd1be6SGreg Clayton } 471e1cd1be6SGreg Clayton 472b9c1b51eSKate Stone void ThreadList::RefreshStateAfterStop() { 473bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 47430fdc8d8SChris Lattner 47530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 47630fdc8d8SChris Lattner 4775160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 47810c4b249SJim Ingham if (log && log->GetVerbose()) 479b9c1b51eSKate Stone log->Printf("Turning off notification of new threads while single stepping " 480b9c1b51eSKate Stone "a thread."); 4811c823b43SJim Ingham 48230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 48330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 48430fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop(); 48530fdc8d8SChris Lattner } 48630fdc8d8SChris Lattner 487b9c1b51eSKate Stone void ThreadList::DiscardThreadPlans() { 48830fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 48930fdc8d8SChris Lattner // that you currently know about have any thread plans. 490bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 49130fdc8d8SChris Lattner 49230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 49330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 49430fdc8d8SChris Lattner (*pos)->DiscardThreadPlans(true); 49530fdc8d8SChris Lattner } 49630fdc8d8SChris Lattner 497b9c1b51eSKate Stone bool ThreadList::WillResume() { 49830fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 49930fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 50030fdc8d8SChris Lattner // threads stay where they are. 50130fdc8d8SChris Lattner 502bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 50330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 50430fdc8d8SChris Lattner 50530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 50630fdc8d8SChris Lattner 507a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 508a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 509b9c1b51eSKate Stone // to run. This is necessary because the SetupForResume might add 510b9c1b51eSKate Stone // "StopOthers" 511b9c1b51eSKate Stone // plans which would then get to be part of the who-gets-to-run negotiation, 512b9c1b51eSKate Stone // but 513b9c1b51eSKate Stone // they're coming in after the fact, and the threads that are already set up 514b9c1b51eSKate Stone // should 515a3241c1bSJim Ingham // take priority. 516a3241c1bSJim Ingham 517a3241c1bSJim Ingham bool wants_solo_run = false; 51830fdc8d8SChris Lattner 519b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 520b9c1b51eSKate Stone lldbassert((*pos)->GetCurrentPlan() && 521b9c1b51eSKate Stone "thread should not have null thread plan"); 5228f186f85SZachary Turner if ((*pos)->GetResumeState() != eStateSuspended && 523b9c1b51eSKate Stone (*pos)->GetCurrentPlan()->StopOthers()) { 524b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 525b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5266e0ff1a3SGreg Clayton continue; 527a3241c1bSJim Ingham wants_solo_run = true; 528a3241c1bSJim Ingham break; 529a3241c1bSJim Ingham } 530a3241c1bSJim Ingham } 531a3241c1bSJim Ingham 532b9c1b51eSKate Stone if (wants_solo_run) { 5335160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 53410c4b249SJim Ingham if (log && log->GetVerbose()) 535b9c1b51eSKate Stone log->Printf("Turning on notification of new threads while single " 536b9c1b51eSKate Stone "stepping a thread."); 5371c823b43SJim Ingham m_process->StartNoticingNewThreads(); 538b9c1b51eSKate Stone } else { 5395160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 54010c4b249SJim Ingham if (log && log->GetVerbose()) 541b9c1b51eSKate Stone log->Printf("Turning off notification of new threads while single " 542b9c1b51eSKate Stone "stepping a thread."); 5431c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5441c823b43SJim Ingham } 545a3241c1bSJim Ingham 546b9c1b51eSKate Stone // Give all the threads that are likely to run a last chance to set up their 547b9c1b51eSKate Stone // state before we 548a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 549b9c1b51eSKate Stone // Don't set to resume suspended threads, and if any thread wanted to stop 550b9c1b51eSKate Stone // others, only 551a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 552a3241c1bSJim Ingham 553b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 554b9c1b51eSKate Stone if ((*pos)->GetResumeState() != eStateSuspended && 555b9c1b51eSKate Stone (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) { 556b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 557b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5586e0ff1a3SGreg Clayton continue; 55930fdc8d8SChris Lattner (*pos)->SetupForResume(); 560a3241c1bSJim Ingham } 561a3241c1bSJim Ingham } 56230fdc8d8SChris Lattner 56330fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 56430fdc8d8SChris Lattner // if so then pick one and run it. 565a3241c1bSJim Ingham 56630fdc8d8SChris Lattner ThreadList run_me_only_list(m_process); 56730fdc8d8SChris Lattner 56830fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 56930fdc8d8SChris Lattner 57030fdc8d8SChris Lattner bool run_only_current_thread = false; 57130fdc8d8SChris Lattner 572b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 57330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 574b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 575b9c1b51eSKate Stone thread_sp->GetCurrentPlan()->StopOthers()) { 576b9c1b51eSKate Stone if ((*pos)->IsOperatingSystemPluginThread() && 577b9c1b51eSKate Stone !(*pos)->GetBackingThread()) 5786e0ff1a3SGreg Clayton continue; 5796e0ff1a3SGreg Clayton 58030fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 58130fdc8d8SChris Lattner assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 58230fdc8d8SChris Lattner 583b9c1b51eSKate Stone if (thread_sp == GetSelectedThread()) { 584b9c1b51eSKate Stone // If the currently selected thread wants to run on its own, always let 585b9c1b51eSKate Stone // it. 58630fdc8d8SChris Lattner run_only_current_thread = true; 58730fdc8d8SChris Lattner run_me_only_list.Clear(); 58830fdc8d8SChris Lattner run_me_only_list.AddThread(thread_sp); 58930fdc8d8SChris Lattner break; 59030fdc8d8SChris Lattner } 59130fdc8d8SChris Lattner 59230fdc8d8SChris Lattner run_me_only_list.AddThread(thread_sp); 59330fdc8d8SChris Lattner } 59430fdc8d8SChris Lattner } 59530fdc8d8SChris Lattner 596513c6bb8SJim Ingham bool need_to_resume = true; 597513c6bb8SJim Ingham 598b9c1b51eSKate Stone if (run_me_only_list.GetSize(false) == 0) { 59930fdc8d8SChris Lattner // Everybody runs as they wish: 600b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 60130fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 602cb5d5a57SJim Ingham StateType run_state; 603cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 604cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 605cb5d5a57SJim Ingham else 606cb5d5a57SJim Ingham run_state = eStateSuspended; 607160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 608513c6bb8SJim Ingham need_to_resume = false; 60930fdc8d8SChris Lattner } 610b9c1b51eSKate Stone } else { 61130fdc8d8SChris Lattner ThreadSP thread_to_run; 61230fdc8d8SChris Lattner 613b9c1b51eSKate Stone if (run_only_current_thread) { 6142976d00aSJim Ingham thread_to_run = GetSelectedThread(); 615b9c1b51eSKate Stone } else if (run_me_only_list.GetSize(false) == 1) { 61630fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex(0); 617b9c1b51eSKate Stone } else { 618b9c1b51eSKate Stone int random_thread = 619b9c1b51eSKate Stone (int)((run_me_only_list.GetSize(false) * (double)rand()) / 620b9c1b51eSKate Stone (RAND_MAX + 1.0)); 62130fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread); 62230fdc8d8SChris Lattner } 62330fdc8d8SChris Lattner 624b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 62530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 626b9c1b51eSKate Stone if (thread_sp == thread_to_run) { 627160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 628513c6bb8SJim Ingham need_to_resume = false; 629b9c1b51eSKate Stone } else 630160c9d81SGreg Clayton thread_sp->ShouldResume(eStateSuspended); 63130fdc8d8SChris Lattner } 63230fdc8d8SChris Lattner } 63330fdc8d8SChris Lattner 634513c6bb8SJim Ingham return need_to_resume; 63530fdc8d8SChris Lattner } 63630fdc8d8SChris Lattner 637b9c1b51eSKate Stone void ThreadList::DidResume() { 638bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 63930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 640b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 64130fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 64230fdc8d8SChris Lattner // leave their state for the next time around. 64330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 64430fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 64530fdc8d8SChris Lattner thread_sp->DidResume(); 64630fdc8d8SChris Lattner } 64730fdc8d8SChris Lattner } 64830fdc8d8SChris Lattner 649b9c1b51eSKate Stone void ThreadList::DidStop() { 650bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 65129d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 652b9c1b51eSKate Stone for (pos = m_threads.begin(); pos != end; ++pos) { 65329d65744SAndrew Kaylor // Notify threads that the process just stopped. 65429d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 65529d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 65629d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 65729d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 65829d65744SAndrew Kaylor // create a special thread list containing only threads which will 65929d65744SAndrew Kaylor // stop in the code that calls this method (currently 66029d65744SAndrew Kaylor // Process::SetPrivateState). 66129d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 66229d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 66329d65744SAndrew Kaylor thread_sp->DidStop(); 66429d65744SAndrew Kaylor } 66529d65744SAndrew Kaylor } 66629d65744SAndrew Kaylor 667b9c1b51eSKate Stone ThreadSP ThreadList::GetSelectedThread() { 668bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 669943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 670b9c1b51eSKate Stone if (!thread_sp.get()) { 671354b9a65SJason Molenda if (m_threads.size() == 0) 672354b9a65SJason Molenda return thread_sp; 673943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 674943ddb73SJohnny Chen thread_sp = m_threads[0]; 675943ddb73SJohnny Chen } 676943ddb73SJohnny Chen return thread_sp; 67730fdc8d8SChris Lattner } 67830fdc8d8SChris Lattner 679b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) { 680bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 681b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 682b9c1b51eSKate Stone if (selected_thread_sp) { 6832976d00aSJim Ingham m_selected_tid = tid; 684b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 685b9c1b51eSKate Stone } else 6862976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 68730fdc8d8SChris Lattner 688c3faa195SJim Ingham if (notify) 689c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 690c3faa195SJim Ingham 6912976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 69230fdc8d8SChris Lattner } 69330fdc8d8SChris Lattner 694b9c1b51eSKate Stone bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) { 695bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 696b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByIndexID(index_id)); 697b9c1b51eSKate Stone if (selected_thread_sp.get()) { 698b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 699b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 700b9c1b51eSKate Stone } else 7012976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 70230fdc8d8SChris Lattner 703c3faa195SJim Ingham if (notify) 704c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 705c3faa195SJim Ingham 7062976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 70730fdc8d8SChris Lattner } 70830fdc8d8SChris Lattner 709b9c1b51eSKate Stone void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) { 710c3faa195SJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 711b9c1b51eSKate Stone if (selected_thread_sp->EventTypeHasListeners( 712b9c1b51eSKate Stone Thread::eBroadcastBitThreadSelected)) 713b9c1b51eSKate Stone selected_thread_sp->BroadcastEvent( 714b9c1b51eSKate Stone Thread::eBroadcastBitThreadSelected, 715c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 716c3faa195SJim Ingham } 717c3faa195SJim Ingham 718b9c1b51eSKate Stone void ThreadList::Update(ThreadList &rhs) { 719b9c1b51eSKate Stone if (this != &rhs) { 72056d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 721e171da5cSBruce Mitchener // while the assignment occurs 722bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 723bb19a13cSSaleem Abdulrasool 72456d9a1b3SGreg Clayton m_process = rhs.m_process; 72556d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 72656d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 72756d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 728e1cd1be6SGreg Clayton 729e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 730e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 731e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 732e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 733e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 734e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 735e1cd1be6SGreg Clayton // need to work around the issue 736e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 737b9c1b51eSKate Stone for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) { 738e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 739e1cd1be6SGreg Clayton bool thread_is_alive = false; 740e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 741b9c1b51eSKate Stone for (uint32_t idx = 0; idx < num_threads; ++idx) { 74265d4d5c3SRyan Brown ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); 743b9c1b51eSKate Stone if (m_threads[idx]->GetID() == tid || 744b9c1b51eSKate Stone (backing_thread && backing_thread->GetID() == tid)) { 745e1cd1be6SGreg Clayton thread_is_alive = true; 746e1cd1be6SGreg Clayton break; 747e1cd1be6SGreg Clayton } 748e1cd1be6SGreg Clayton } 749e1cd1be6SGreg Clayton if (!thread_is_alive) 750e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 751e1cd1be6SGreg Clayton } 75256d9a1b3SGreg Clayton } 75356d9a1b3SGreg Clayton } 75456d9a1b3SGreg Clayton 755b9c1b51eSKate Stone void ThreadList::Flush() { 756bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 757fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 758fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 759fa559e5cSGreg Clayton (*pos)->Flush(); 760fa559e5cSGreg Clayton } 76156d9a1b3SGreg Clayton 762b5cd6e7bSGreg Clayton std::recursive_mutex &ThreadList::GetMutex() const { 763ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 764ba4e61d3SAndrew Kaylor } 765ba4e61d3SAndrew Kaylor 766b9c1b51eSKate Stone ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher( 767b9c1b51eSKate Stone lldb::ThreadSP thread_sp) 768b9c1b51eSKate Stone : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) { 769b9c1b51eSKate Stone if (thread_sp) { 7708d94ba0fSJim Ingham m_tid = thread_sp->GetID(); 7718d94ba0fSJim Ingham m_thread_list = &thread_sp->GetProcess()->GetThreadList(); 7728d94ba0fSJim Ingham m_thread_list->PushExpressionExecutionThread(m_tid); 7738d94ba0fSJim Ingham } 7748d94ba0fSJim Ingham } 775