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" 202cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h" 2130fdc8d8SChris Lattner #include "lldb/Target/ThreadList.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2330fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Process.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 3130fdc8d8SChris Lattner ThreadList::ThreadList (Process *process) : 32e4d4801cSKuba Brecka ThreadCollection(), 3330fdc8d8SChris Lattner m_process (process), 3430fdc8d8SChris Lattner m_stop_id (0), 352976d00aSJim Ingham m_selected_tid (LLDB_INVALID_THREAD_ID) 3630fdc8d8SChris Lattner { 3730fdc8d8SChris Lattner } 3830fdc8d8SChris Lattner 3930fdc8d8SChris Lattner ThreadList::ThreadList (const ThreadList &rhs) : 40e4d4801cSKuba Brecka ThreadCollection(), 41ba4e61d3SAndrew Kaylor m_process (rhs.m_process), 42ba4e61d3SAndrew Kaylor m_stop_id (rhs.m_stop_id), 432976d00aSJim Ingham m_selected_tid () 4430fdc8d8SChris Lattner { 4530fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 4630fdc8d8SChris Lattner *this = rhs; 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 4930fdc8d8SChris Lattner const ThreadList& 5030fdc8d8SChris Lattner ThreadList::operator = (const ThreadList& rhs) 5130fdc8d8SChris Lattner { 5230fdc8d8SChris Lattner if (this != &rhs) 5330fdc8d8SChris Lattner { 5430fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 55e171da5cSBruce Mitchener // while the assignment occurs 56*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 57*bb19a13cSSaleem Abdulrasool 5830fdc8d8SChris Lattner m_process = rhs.m_process; 5930fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 6030fdc8d8SChris Lattner m_threads = rhs.m_threads; 612976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 6230fdc8d8SChris Lattner } 6330fdc8d8SChris Lattner return *this; 6430fdc8d8SChris Lattner } 6530fdc8d8SChris Lattner 6630fdc8d8SChris Lattner 6730fdc8d8SChris Lattner ThreadList::~ThreadList() 6830fdc8d8SChris Lattner { 69ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 70ac358da5SGreg Clayton // which will ensure that if anyone is using the list 71ac358da5SGreg Clayton // they won't get it removed while using it. 72ac358da5SGreg Clayton Clear(); 7330fdc8d8SChris Lattner } 7430fdc8d8SChris Lattner 758d94ba0fSJim Ingham lldb::ThreadSP 768d94ba0fSJim Ingham ThreadList::GetExpressionExecutionThread() 778d94ba0fSJim Ingham { 788d94ba0fSJim Ingham if (m_expression_tid_stack.empty()) 798d94ba0fSJim Ingham return GetSelectedThread(); 808d94ba0fSJim Ingham ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back()); 818d94ba0fSJim Ingham if (expr_thread_sp) 828d94ba0fSJim Ingham return expr_thread_sp; 838d94ba0fSJim Ingham else 848d94ba0fSJim Ingham return GetSelectedThread(); 858d94ba0fSJim Ingham } 868d94ba0fSJim Ingham 878d94ba0fSJim Ingham void 888d94ba0fSJim Ingham ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) 898d94ba0fSJim Ingham { 908d94ba0fSJim Ingham m_expression_tid_stack.push_back(tid); 918d94ba0fSJim Ingham } 928d94ba0fSJim Ingham 938d94ba0fSJim Ingham void 948d94ba0fSJim Ingham ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) 958d94ba0fSJim Ingham { 968d94ba0fSJim Ingham assert(m_expression_tid_stack.back() == tid); 978d94ba0fSJim Ingham m_expression_tid_stack.pop_back(); 988d94ba0fSJim Ingham } 9930fdc8d8SChris Lattner 10030fdc8d8SChris Lattner uint32_t 10130fdc8d8SChris Lattner ThreadList::GetStopID () const 10230fdc8d8SChris Lattner { 10330fdc8d8SChris Lattner return m_stop_id; 10430fdc8d8SChris Lattner } 10530fdc8d8SChris Lattner 10630fdc8d8SChris Lattner void 10730fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 10830fdc8d8SChris Lattner { 10930fdc8d8SChris Lattner m_stop_id = stop_id; 11030fdc8d8SChris Lattner } 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner uint32_t 11330fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 11430fdc8d8SChris Lattner { 115*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 116*bb19a13cSSaleem Abdulrasool 11730fdc8d8SChris Lattner if (can_update) 11830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11930fdc8d8SChris Lattner return m_threads.size(); 12030fdc8d8SChris Lattner } 12130fdc8d8SChris Lattner 12230fdc8d8SChris Lattner ThreadSP 12330fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 12430fdc8d8SChris Lattner { 125*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 126*bb19a13cSSaleem Abdulrasool 12730fdc8d8SChris Lattner if (can_update) 12830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 12930fdc8d8SChris Lattner 13030fdc8d8SChris Lattner ThreadSP thread_sp; 13130fdc8d8SChris Lattner if (idx < m_threads.size()) 13230fdc8d8SChris Lattner thread_sp = m_threads[idx]; 13330fdc8d8SChris Lattner return thread_sp; 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 13630fdc8d8SChris Lattner ThreadSP 13730fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 13830fdc8d8SChris Lattner { 139*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 14030fdc8d8SChris Lattner 14130fdc8d8SChris Lattner if (can_update) 14230fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 14330fdc8d8SChris Lattner 14430fdc8d8SChris Lattner ThreadSP thread_sp; 14530fdc8d8SChris Lattner uint32_t idx = 0; 14630fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 14730fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 14830fdc8d8SChris Lattner { 14930fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 15030fdc8d8SChris Lattner { 15130fdc8d8SChris Lattner thread_sp = m_threads[idx]; 15230fdc8d8SChris Lattner break; 15330fdc8d8SChris Lattner } 15430fdc8d8SChris Lattner } 15530fdc8d8SChris Lattner return thread_sp; 15630fdc8d8SChris Lattner } 15730fdc8d8SChris Lattner 15830fdc8d8SChris Lattner ThreadSP 159160c9d81SGreg Clayton ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) 160160c9d81SGreg Clayton { 161*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 162160c9d81SGreg Clayton 163160c9d81SGreg Clayton if (can_update) 164160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 165160c9d81SGreg Clayton 166160c9d81SGreg Clayton ThreadSP thread_sp; 167160c9d81SGreg Clayton uint32_t idx = 0; 168160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 169160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 170160c9d81SGreg Clayton { 171160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 172160c9d81SGreg Clayton { 173160c9d81SGreg Clayton thread_sp = m_threads[idx]; 174160c9d81SGreg Clayton break; 175160c9d81SGreg Clayton } 176160c9d81SGreg Clayton } 177160c9d81SGreg Clayton return thread_sp; 178160c9d81SGreg Clayton } 179160c9d81SGreg Clayton 180160c9d81SGreg Clayton 181160c9d81SGreg Clayton ThreadSP 182c2c423eaSHan Ming Ong ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) 183c2c423eaSHan Ming Ong { 184*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 185c2c423eaSHan Ming Ong 186c2c423eaSHan Ming Ong if (can_update) 187c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 188c2c423eaSHan Ming Ong 189c2c423eaSHan Ming Ong ThreadSP thread_sp; 190c2c423eaSHan Ming Ong uint32_t idx = 0; 191c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 192c2c423eaSHan Ming Ong for (idx = 0; idx < num_threads; ++idx) 193c2c423eaSHan Ming Ong { 194c2c423eaSHan Ming Ong if (m_threads[idx]->GetID() == tid) 195c2c423eaSHan Ming Ong { 196c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 197c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin()+idx); 198c2c423eaSHan Ming Ong break; 199c2c423eaSHan Ming Ong } 200c2c423eaSHan Ming Ong } 201c2c423eaSHan Ming Ong return thread_sp; 202c2c423eaSHan Ming Ong } 203c2c423eaSHan Ming Ong 204c2c423eaSHan Ming Ong ThreadSP 205160c9d81SGreg Clayton ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) 206160c9d81SGreg Clayton { 207*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 208160c9d81SGreg Clayton 209160c9d81SGreg Clayton if (can_update) 210160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 211160c9d81SGreg Clayton 212160c9d81SGreg Clayton ThreadSP thread_sp; 213160c9d81SGreg Clayton uint32_t idx = 0; 214160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 215160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 216160c9d81SGreg Clayton { 217160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 218160c9d81SGreg Clayton { 219160c9d81SGreg Clayton thread_sp = m_threads[idx]; 220160c9d81SGreg Clayton m_threads.erase(m_threads.begin()+idx); 221160c9d81SGreg Clayton break; 222160c9d81SGreg Clayton } 223160c9d81SGreg Clayton } 224160c9d81SGreg Clayton return thread_sp; 225160c9d81SGreg Clayton } 226160c9d81SGreg Clayton 227160c9d81SGreg Clayton ThreadSP 22830fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 22930fdc8d8SChris Lattner { 23030fdc8d8SChris Lattner ThreadSP thread_sp; 23130fdc8d8SChris Lattner if (thread_ptr) 23230fdc8d8SChris Lattner { 233*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 23430fdc8d8SChris Lattner 23530fdc8d8SChris Lattner uint32_t idx = 0; 23630fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 23730fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 23830fdc8d8SChris Lattner { 23930fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 24030fdc8d8SChris Lattner { 24130fdc8d8SChris Lattner thread_sp = m_threads[idx]; 24230fdc8d8SChris Lattner break; 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner } 24530fdc8d8SChris Lattner } 24630fdc8d8SChris Lattner return thread_sp; 24730fdc8d8SChris Lattner } 24830fdc8d8SChris Lattner 24930fdc8d8SChris Lattner 25030fdc8d8SChris Lattner 25130fdc8d8SChris Lattner ThreadSP 25230fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 25330fdc8d8SChris Lattner { 254*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 25530fdc8d8SChris Lattner 25630fdc8d8SChris Lattner if (can_update) 25730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 25830fdc8d8SChris Lattner 25930fdc8d8SChris Lattner ThreadSP thread_sp; 26030fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 26130fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 26230fdc8d8SChris Lattner { 26330fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 26430fdc8d8SChris Lattner { 26530fdc8d8SChris Lattner thread_sp = m_threads[idx]; 26630fdc8d8SChris Lattner break; 26730fdc8d8SChris Lattner } 26830fdc8d8SChris Lattner } 26930fdc8d8SChris Lattner return thread_sp; 27030fdc8d8SChris Lattner } 27130fdc8d8SChris Lattner 27230fdc8d8SChris Lattner bool 27330fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 27430fdc8d8SChris Lattner { 27530fdc8d8SChris Lattner // Running events should never stop, obviously... 27630fdc8d8SChris Lattner 2775160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 27830fdc8d8SChris Lattner 279b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 28035878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 281b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 282b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 2832f8e4c3bSAdrian McCarthy // to be created. If that happens, we will miss asking them whether 2842f8e4c3bSAdrian McCarthy // they should stop. This is not a big deal since we haven't had 285b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 28630fdc8d8SChris Lattner 287b42f3af3SJim Ingham collection threads_copy; 288b42f3af3SJim Ingham { 289b42f3af3SJim Ingham // Scope for locker 290*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 291b42f3af3SJim Ingham 292b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 293569aaf9eSJim Ingham for (lldb::ThreadSP thread_sp : m_threads) 294569aaf9eSJim Ingham { 295569aaf9eSJim Ingham // This is an optimization... If we didn't let a thread run in between the previous stop and this 296569aaf9eSJim Ingham // one, we shouldn't have to consult it for ShouldStop. So just leave it off the list we are going to 297569aaf9eSJim Ingham // inspect. 2986e8fbc6fSChaoren Lin // On Linux, if a thread-specific conditional breakpoint was hit, it won't necessarily be the thread 2996e8fbc6fSChaoren Lin // that hit the breakpoint itself that evaluates the conditional expression, so the thread that hit 3006e8fbc6fSChaoren Lin // the breakpoint could still be asked to stop, even though it hasn't been allowed to run since the 3016e8fbc6fSChaoren Lin // previous stop. 3026e8fbc6fSChaoren Lin if (thread_sp->GetTemporaryResumeState () != eStateSuspended || thread_sp->IsStillAtLastBreakpointHit()) 303569aaf9eSJim Ingham threads_copy.push_back(thread_sp); 304569aaf9eSJim Ingham } 305569aaf9eSJim Ingham 306569aaf9eSJim Ingham // It is possible the threads we were allowing to run all exited and then maybe the user interrupted 307569aaf9eSJim Ingham // or something, then fall back on looking at all threads: 308569aaf9eSJim Ingham 309569aaf9eSJim Ingham if (threads_copy.size() == 0) 310b42f3af3SJim Ingham threads_copy = m_threads; 311b42f3af3SJim Ingham } 312b42f3af3SJim Ingham 313b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 31430fdc8d8SChris Lattner 3152cad65a5SGreg Clayton if (log) 31610c4b249SJim Ingham { 31710c4b249SJim Ingham log->PutCString(""); 318569aaf9eSJim Ingham log->Printf ("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 " unsuspended threads", 319569aaf9eSJim Ingham __FUNCTION__, 320569aaf9eSJim Ingham (uint64_t)m_threads.size(), 321569aaf9eSJim Ingham (uint64_t)threads_copy.size()); 32210c4b249SJim Ingham } 3232cad65a5SGreg Clayton 324a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 32535878c47SJim Ingham 32635878c47SJim Ingham // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop. 327a0079044SJim Ingham bool should_stop = false; 32835878c47SJim Ingham if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) 32935878c47SJim Ingham { 33035878c47SJim Ingham if (log) 33135878c47SJim Ingham log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__); 33235878c47SJim Ingham 33335878c47SJim Ingham should_stop = true; 33435878c47SJim Ingham } 3357bc3465fSJim Ingham 3367bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 3377bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 3387bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 3397bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 3407bc3465fSJim Ingham 3417bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 3427bc3465fSJim Ingham { 3437bc3465fSJim Ingham ThreadSP thread_sp(*pos); 3447bc3465fSJim Ingham thread_sp->GetStopInfo(); 3457bc3465fSJim Ingham } 346a0079044SJim Ingham 347b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 34830fdc8d8SChris Lattner { 34930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 3502cad65a5SGreg Clayton 35139fdae7fSJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 35239fdae7fSJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 35339fdae7fSJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 35439fdae7fSJim Ingham // 35539fdae7fSJim Ingham // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint, 35639fdae7fSJim Ingham // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint 35739fdae7fSJim Ingham // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this 35839fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 35939fdae7fSJim Ingham // 36039fdae7fSJim Ingham // Since the only way we ever saw this error was on first attach, I'm only going to trigger set did_anybody_stop_for_a_reason 36139fdae7fSJim Ingham // to true unless this is the first stop. 36239fdae7fSJim Ingham // 36339fdae7fSJim Ingham // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid 36439fdae7fSJim Ingham // everywhere but at this check. 36539fdae7fSJim Ingham 36621afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 36739fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 36839fdae7fSJim Ingham else 369a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 370a0079044SJim Ingham 37110c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3722cad65a5SGreg Clayton if (thread_should_stop) 3732cad65a5SGreg Clayton should_stop |= true; 3742cad65a5SGreg Clayton } 3752cad65a5SGreg Clayton 376a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 377a0079044SJim Ingham { 378a0079044SJim Ingham should_stop = true; 379a0079044SJim Ingham if (log) 380a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 381a0079044SJim Ingham } 382a0079044SJim Ingham 3832cad65a5SGreg Clayton if (log) 38410c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 3852cad65a5SGreg Clayton 38630fdc8d8SChris Lattner if (should_stop) 38730fdc8d8SChris Lattner { 388b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 38930fdc8d8SChris Lattner { 39030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 39130fdc8d8SChris Lattner thread_sp->WillStop (); 39230fdc8d8SChris Lattner } 39330fdc8d8SChris Lattner } 39430fdc8d8SChris Lattner 39530fdc8d8SChris Lattner return should_stop; 39630fdc8d8SChris Lattner } 39730fdc8d8SChris Lattner 39830fdc8d8SChris Lattner Vote 39930fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 40030fdc8d8SChris Lattner { 401*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 4022cad65a5SGreg Clayton 40330fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 40430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 40530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 40630fdc8d8SChris Lattner 4075160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 4082cad65a5SGreg Clayton 4092cad65a5SGreg Clayton if (log) 410d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 4112cad65a5SGreg Clayton 41230fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 41330fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 41430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 41530fdc8d8SChris Lattner { 41630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 417e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 4182cad65a5SGreg Clayton switch (vote) 41930fdc8d8SChris Lattner { 42030fdc8d8SChris Lattner case eVoteNoOpinion: 42130fdc8d8SChris Lattner continue; 4222cad65a5SGreg Clayton 42330fdc8d8SChris Lattner case eVoteYes: 42430fdc8d8SChris Lattner result = eVoteYes; 42530fdc8d8SChris Lattner break; 4262cad65a5SGreg Clayton 42730fdc8d8SChris Lattner case eVoteNo: 42830fdc8d8SChris Lattner if (result == eVoteNoOpinion) 4292cad65a5SGreg Clayton { 43030fdc8d8SChris Lattner result = eVoteNo; 4312cad65a5SGreg Clayton } 4322cad65a5SGreg Clayton else 4332cad65a5SGreg Clayton { 4342cad65a5SGreg Clayton if (log) 435d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 4362cad65a5SGreg Clayton __FUNCTION__, 4372cad65a5SGreg Clayton thread_sp->GetID (), 4382cad65a5SGreg Clayton GetVoteAsCString (vote), 4392cad65a5SGreg Clayton GetVoteAsCString (result)); 4402cad65a5SGreg Clayton } 44130fdc8d8SChris Lattner break; 44230fdc8d8SChris Lattner } 44330fdc8d8SChris Lattner } 4442cad65a5SGreg Clayton if (log) 44510c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 44630fdc8d8SChris Lattner return result; 44730fdc8d8SChris Lattner } 44830fdc8d8SChris Lattner 449221d51cfSJim Ingham void 450221d51cfSJim Ingham ThreadList::SetShouldReportStop (Vote vote) 451221d51cfSJim Ingham { 452*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 453*bb19a13cSSaleem Abdulrasool 454221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 455221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 456221d51cfSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 457221d51cfSJim Ingham { 458221d51cfSJim Ingham ThreadSP thread_sp(*pos); 459221d51cfSJim Ingham thread_sp->SetShouldReportStop (vote); 460221d51cfSJim Ingham } 461221d51cfSJim Ingham } 462221d51cfSJim Ingham 46330fdc8d8SChris Lattner Vote 46430fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 46530fdc8d8SChris Lattner { 4662cad65a5SGreg Clayton 467*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 4682cad65a5SGreg Clayton 46930fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 47030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 47130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 47230fdc8d8SChris Lattner 47330fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 47430fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 47530fdc8d8SChris Lattner 4765160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 477ce579839SJim Ingham 47830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 47930fdc8d8SChris Lattner { 480ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 481ce579839SJim Ingham { 482ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 48330fdc8d8SChris Lattner { 48430fdc8d8SChris Lattner case eVoteNoOpinion: 48530fdc8d8SChris Lattner continue; 48630fdc8d8SChris Lattner case eVoteYes: 48730fdc8d8SChris Lattner if (result == eVoteNoOpinion) 48830fdc8d8SChris Lattner result = eVoteYes; 48930fdc8d8SChris Lattner break; 49030fdc8d8SChris Lattner case eVoteNo: 491abcbc8acSGreg Clayton if (log) 492d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 493ce579839SJim Ingham (*pos)->GetIndexID(), 494ce579839SJim Ingham (*pos)->GetID()); 49530fdc8d8SChris Lattner result = eVoteNo; 49630fdc8d8SChris Lattner break; 49730fdc8d8SChris Lattner } 49830fdc8d8SChris Lattner } 499ce579839SJim Ingham } 50030fdc8d8SChris Lattner return result; 50130fdc8d8SChris Lattner } 50230fdc8d8SChris Lattner 50330fdc8d8SChris Lattner void 50430fdc8d8SChris Lattner ThreadList::Clear() 50530fdc8d8SChris Lattner { 506*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 50730fdc8d8SChris Lattner m_stop_id = 0; 50830fdc8d8SChris Lattner m_threads.clear(); 5092976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 51030fdc8d8SChris Lattner } 51130fdc8d8SChris Lattner 51230fdc8d8SChris Lattner void 513e1cd1be6SGreg Clayton ThreadList::Destroy() 514e1cd1be6SGreg Clayton { 515*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 516e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 517e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 518e1cd1be6SGreg Clayton { 519e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 520e1cd1be6SGreg Clayton } 521e1cd1be6SGreg Clayton } 522e1cd1be6SGreg Clayton 523e1cd1be6SGreg Clayton void 52430fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 52530fdc8d8SChris Lattner { 526*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 52730fdc8d8SChris Lattner 52830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 52930fdc8d8SChris Lattner 5305160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 53110c4b249SJim Ingham if (log && log->GetVerbose()) 5321c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5331c823b43SJim Ingham 53430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 53530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 53630fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 53730fdc8d8SChris Lattner } 53830fdc8d8SChris Lattner 53930fdc8d8SChris Lattner void 54030fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 54130fdc8d8SChris Lattner { 54230fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 54330fdc8d8SChris Lattner // that you currently know about have any thread plans. 544*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 54530fdc8d8SChris Lattner 54630fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 54730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 54830fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 54930fdc8d8SChris Lattner 55030fdc8d8SChris Lattner } 55130fdc8d8SChris Lattner 55230fdc8d8SChris Lattner bool 55330fdc8d8SChris Lattner ThreadList::WillResume () 55430fdc8d8SChris Lattner { 55530fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 55630fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 55730fdc8d8SChris Lattner // threads stay where they are. 55830fdc8d8SChris Lattner 559*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 56030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 56130fdc8d8SChris Lattner 56230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 56330fdc8d8SChris Lattner 564a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 565a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 566a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 567a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 568a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 569a3241c1bSJim Ingham // take priority. 570a3241c1bSJim Ingham 571a3241c1bSJim Ingham bool wants_solo_run = false; 57230fdc8d8SChris Lattner 57330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 574a3241c1bSJim Ingham { 5758f186f85SZachary Turner lldbassert((*pos)->GetCurrentPlan() && "thread should not have null thread plan"); 5768f186f85SZachary Turner if ((*pos)->GetResumeState() != eStateSuspended && 577a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 578a3241c1bSJim Ingham { 5796e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5806e0ff1a3SGreg Clayton continue; 581a3241c1bSJim Ingham wants_solo_run = true; 582a3241c1bSJim Ingham break; 583a3241c1bSJim Ingham } 584a3241c1bSJim Ingham } 585a3241c1bSJim Ingham 5861c823b43SJim Ingham if (wants_solo_run) 5871c823b43SJim Ingham { 5885160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 58910c4b249SJim Ingham if (log && log->GetVerbose()) 5901c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5911c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5921c823b43SJim Ingham } 5931c823b43SJim Ingham else 5941c823b43SJim Ingham { 5955160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 59610c4b249SJim Ingham if (log && log->GetVerbose()) 5971c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5981c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5991c823b43SJim Ingham } 600a3241c1bSJim Ingham 601a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 602a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 603a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 604a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 605a3241c1bSJim Ingham 606a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 607a3241c1bSJim Ingham { 608a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 609a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 610a3241c1bSJim Ingham { 6116e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 6126e0ff1a3SGreg Clayton continue; 61330fdc8d8SChris Lattner (*pos)->SetupForResume (); 614a3241c1bSJim Ingham } 615a3241c1bSJim Ingham } 61630fdc8d8SChris Lattner 61730fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 61830fdc8d8SChris Lattner // if so then pick one and run it. 619a3241c1bSJim Ingham 62030fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 62130fdc8d8SChris Lattner 62230fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 62330fdc8d8SChris Lattner 62430fdc8d8SChris Lattner bool run_only_current_thread = false; 62530fdc8d8SChris Lattner 62630fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 62730fdc8d8SChris Lattner { 62830fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 629b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 63030fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 63130fdc8d8SChris Lattner { 6326e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 6336e0ff1a3SGreg Clayton continue; 6346e0ff1a3SGreg Clayton 63530fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 63630fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 63730fdc8d8SChris Lattner 6382976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 63930fdc8d8SChris Lattner { 640acbea8fbSJim Ingham // If the currently selected thread wants to run on its own, always let it. 64130fdc8d8SChris Lattner run_only_current_thread = true; 64230fdc8d8SChris Lattner run_me_only_list.Clear(); 64330fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 64430fdc8d8SChris Lattner break; 64530fdc8d8SChris Lattner } 64630fdc8d8SChris Lattner 64730fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 64830fdc8d8SChris Lattner } 64930fdc8d8SChris Lattner 65030fdc8d8SChris Lattner } 65130fdc8d8SChris Lattner 652513c6bb8SJim Ingham bool need_to_resume = true; 653513c6bb8SJim Ingham 6546e0ff1a3SGreg Clayton if (run_me_only_list.GetSize (false) == 0) 65530fdc8d8SChris Lattner { 65630fdc8d8SChris Lattner // Everybody runs as they wish: 65730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 65830fdc8d8SChris Lattner { 65930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 660cb5d5a57SJim Ingham StateType run_state; 661cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 662cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 663cb5d5a57SJim Ingham else 664cb5d5a57SJim Ingham run_state = eStateSuspended; 665160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 666513c6bb8SJim Ingham need_to_resume = false; 66730fdc8d8SChris Lattner } 66830fdc8d8SChris Lattner } 66930fdc8d8SChris Lattner else 67030fdc8d8SChris Lattner { 67130fdc8d8SChris Lattner ThreadSP thread_to_run; 67230fdc8d8SChris Lattner 67330fdc8d8SChris Lattner if (run_only_current_thread) 67430fdc8d8SChris Lattner { 6752976d00aSJim Ingham thread_to_run = GetSelectedThread(); 67630fdc8d8SChris Lattner } 67730fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 67830fdc8d8SChris Lattner { 67930fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 68030fdc8d8SChris Lattner } 68130fdc8d8SChris Lattner else 68230fdc8d8SChris Lattner { 68330fdc8d8SChris Lattner int random_thread = (int) 68430fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 68530fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 68630fdc8d8SChris Lattner } 68730fdc8d8SChris Lattner 68830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 68930fdc8d8SChris Lattner { 69030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 69130fdc8d8SChris Lattner if (thread_sp == thread_to_run) 692513c6bb8SJim Ingham { 693160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 694513c6bb8SJim Ingham need_to_resume = false; 695513c6bb8SJim Ingham } 69630fdc8d8SChris Lattner else 697160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 69830fdc8d8SChris Lattner } 69930fdc8d8SChris Lattner } 70030fdc8d8SChris Lattner 701513c6bb8SJim Ingham return need_to_resume; 70230fdc8d8SChris Lattner } 70330fdc8d8SChris Lattner 70430fdc8d8SChris Lattner void 70530fdc8d8SChris Lattner ThreadList::DidResume () 70630fdc8d8SChris Lattner { 707*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 70830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 70930fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 71030fdc8d8SChris Lattner { 71130fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 71230fdc8d8SChris Lattner // leave their state for the next time around. 71330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 71430fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 71530fdc8d8SChris Lattner thread_sp->DidResume (); 71630fdc8d8SChris Lattner } 71730fdc8d8SChris Lattner } 71830fdc8d8SChris Lattner 71929d65744SAndrew Kaylor void 72029d65744SAndrew Kaylor ThreadList::DidStop () 72129d65744SAndrew Kaylor { 722*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 72329d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 72429d65744SAndrew Kaylor for (pos = m_threads.begin(); pos != end; ++pos) 72529d65744SAndrew Kaylor { 72629d65744SAndrew Kaylor // Notify threads that the process just stopped. 72729d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 72829d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 72929d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 73029d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 73129d65744SAndrew Kaylor // create a special thread list containing only threads which will 73229d65744SAndrew Kaylor // stop in the code that calls this method (currently 73329d65744SAndrew Kaylor // Process::SetPrivateState). 73429d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 73529d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 73629d65744SAndrew Kaylor thread_sp->DidStop (); 73729d65744SAndrew Kaylor } 73829d65744SAndrew Kaylor } 73929d65744SAndrew Kaylor 74030fdc8d8SChris Lattner ThreadSP 7412976d00aSJim Ingham ThreadList::GetSelectedThread () 74230fdc8d8SChris Lattner { 743*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 744943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 745943ddb73SJohnny Chen if (!thread_sp.get()) 746943ddb73SJohnny Chen { 747354b9a65SJason Molenda if (m_threads.size() == 0) 748354b9a65SJason Molenda return thread_sp; 749943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 750943ddb73SJohnny Chen thread_sp = m_threads[0]; 751943ddb73SJohnny Chen } 752943ddb73SJohnny Chen return thread_sp; 75330fdc8d8SChris Lattner } 75430fdc8d8SChris Lattner 75530fdc8d8SChris Lattner bool 756c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 75730fdc8d8SChris Lattner { 758*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 759b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 760b7f6b2faSJim Ingham if (selected_thread_sp) 761b7f6b2faSJim Ingham { 7622976d00aSJim Ingham m_selected_tid = tid; 763b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 764b7f6b2faSJim Ingham } 76530fdc8d8SChris Lattner else 7662976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 76730fdc8d8SChris Lattner 768c3faa195SJim Ingham if (notify) 769c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 770c3faa195SJim Ingham 7712976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 77230fdc8d8SChris Lattner } 77330fdc8d8SChris Lattner 77430fdc8d8SChris Lattner bool 775c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 77630fdc8d8SChris Lattner { 777*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 778b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 779b7f6b2faSJim Ingham if (selected_thread_sp.get()) 780b7f6b2faSJim Ingham { 781b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 782b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 783b7f6b2faSJim Ingham } 78430fdc8d8SChris Lattner else 7852976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 78630fdc8d8SChris Lattner 787c3faa195SJim Ingham if (notify) 788c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 789c3faa195SJim Ingham 7902976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 79130fdc8d8SChris Lattner } 79230fdc8d8SChris Lattner 79356d9a1b3SGreg Clayton void 794c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 795c3faa195SJim Ingham { 796c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 797c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 798c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 799c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 800c3faa195SJim Ingham } 801c3faa195SJim Ingham 802c3faa195SJim Ingham void 80356d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 80456d9a1b3SGreg Clayton { 80556d9a1b3SGreg Clayton if (this != &rhs) 80656d9a1b3SGreg Clayton { 80756d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 808e171da5cSBruce Mitchener // while the assignment occurs 809*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 810*bb19a13cSSaleem Abdulrasool 81156d9a1b3SGreg Clayton m_process = rhs.m_process; 81256d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 81356d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 81456d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 815e1cd1be6SGreg Clayton 816e1cd1be6SGreg Clayton 817e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 818e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 819e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 820e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 821e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 822e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 823e1cd1be6SGreg Clayton // need to work around the issue 824e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 825e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 826e1cd1be6SGreg Clayton { 827e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 828e1cd1be6SGreg Clayton bool thread_is_alive = false; 829e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 830e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 831e1cd1be6SGreg Clayton { 83265d4d5c3SRyan Brown ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); 83365d4d5c3SRyan Brown if (m_threads[idx]->GetID() == tid || (backing_thread && backing_thread->GetID() == tid)) 834e1cd1be6SGreg Clayton { 835e1cd1be6SGreg Clayton thread_is_alive = true; 836e1cd1be6SGreg Clayton break; 837e1cd1be6SGreg Clayton } 838e1cd1be6SGreg Clayton } 839e1cd1be6SGreg Clayton if (!thread_is_alive) 840e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 841e1cd1be6SGreg Clayton } 84256d9a1b3SGreg Clayton } 84356d9a1b3SGreg Clayton } 84456d9a1b3SGreg Clayton 845fa559e5cSGreg Clayton void 846fa559e5cSGreg Clayton ThreadList::Flush () 847fa559e5cSGreg Clayton { 848*bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(GetMutex()); 849fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 850fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 851fa559e5cSGreg Clayton (*pos)->Flush (); 852fa559e5cSGreg Clayton } 85356d9a1b3SGreg Clayton 854*bb19a13cSSaleem Abdulrasool std::recursive_mutex & 855ba4e61d3SAndrew Kaylor ThreadList::GetMutex() 856ba4e61d3SAndrew Kaylor { 857ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 858ba4e61d3SAndrew Kaylor } 859ba4e61d3SAndrew Kaylor 8608d94ba0fSJim Ingham ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher (lldb::ThreadSP thread_sp) : 8618d94ba0fSJim Ingham m_thread_list(nullptr), 8628d94ba0fSJim Ingham m_tid(LLDB_INVALID_THREAD_ID) 8638d94ba0fSJim Ingham { 8648d94ba0fSJim Ingham if (thread_sp) 8658d94ba0fSJim Ingham { 8668d94ba0fSJim Ingham m_tid = thread_sp->GetID(); 8678d94ba0fSJim Ingham m_thread_list = &thread_sp->GetProcess()->GetThreadList(); 8688d94ba0fSJim Ingham m_thread_list->PushExpressionExecutionThread(m_tid); 8698d94ba0fSJim Ingham } 8708d94ba0fSJim Ingham } 8718d94ba0fSJim Ingham 8728d94ba0fSJim Ingham 873