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 //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner #include <stdlib.h> 1030fdc8d8SChris Lattner 1130fdc8d8SChris Lattner #include <algorithm> 1230fdc8d8SChris Lattner 132cad65a5SGreg Clayton #include "lldb/Core/Log.h" 1429d65744SAndrew Kaylor #include "lldb/Core/State.h" 152cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h" 1630fdc8d8SChris Lattner #include "lldb/Target/ThreadList.h" 1730fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 1830fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h" 1930fdc8d8SChris Lattner #include "lldb/Target/Process.h" 205023257fSZachary Turner #include "lldb/Utility/ConvertEnum.h" 21*8f186f85SZachary Turner #include "lldb/Utility/LLDBAssert.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb; 2430fdc8d8SChris Lattner using namespace lldb_private; 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner ThreadList::ThreadList (Process *process) : 27e4d4801cSKuba Brecka ThreadCollection(), 2830fdc8d8SChris Lattner m_process (process), 2930fdc8d8SChris Lattner m_stop_id (0), 302976d00aSJim Ingham m_selected_tid (LLDB_INVALID_THREAD_ID) 3130fdc8d8SChris Lattner { 3230fdc8d8SChris Lattner } 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner ThreadList::ThreadList (const ThreadList &rhs) : 35e4d4801cSKuba Brecka ThreadCollection(), 36ba4e61d3SAndrew Kaylor m_process (rhs.m_process), 37ba4e61d3SAndrew Kaylor m_stop_id (rhs.m_stop_id), 382976d00aSJim Ingham m_selected_tid () 3930fdc8d8SChris Lattner { 4030fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 4130fdc8d8SChris Lattner *this = rhs; 4230fdc8d8SChris Lattner } 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner const ThreadList& 4530fdc8d8SChris Lattner ThreadList::operator = (const ThreadList& rhs) 4630fdc8d8SChris Lattner { 4730fdc8d8SChris Lattner if (this != &rhs) 4830fdc8d8SChris Lattner { 4930fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 50e171da5cSBruce Mitchener // while the assignment occurs 51ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 5230fdc8d8SChris Lattner m_process = rhs.m_process; 5330fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5430fdc8d8SChris Lattner m_threads = rhs.m_threads; 552976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner return *this; 5830fdc8d8SChris Lattner } 5930fdc8d8SChris Lattner 6030fdc8d8SChris Lattner 6130fdc8d8SChris Lattner ThreadList::~ThreadList() 6230fdc8d8SChris Lattner { 63ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 64ac358da5SGreg Clayton // which will ensure that if anyone is using the list 65ac358da5SGreg Clayton // they won't get it removed while using it. 66ac358da5SGreg Clayton Clear(); 6730fdc8d8SChris Lattner } 6830fdc8d8SChris Lattner 6930fdc8d8SChris Lattner 7030fdc8d8SChris Lattner uint32_t 7130fdc8d8SChris Lattner ThreadList::GetStopID () const 7230fdc8d8SChris Lattner { 7330fdc8d8SChris Lattner return m_stop_id; 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner 7630fdc8d8SChris Lattner void 7730fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 7830fdc8d8SChris Lattner { 7930fdc8d8SChris Lattner m_stop_id = stop_id; 8030fdc8d8SChris Lattner } 8130fdc8d8SChris Lattner 8230fdc8d8SChris Lattner uint32_t 8330fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 8430fdc8d8SChris Lattner { 85ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 8630fdc8d8SChris Lattner if (can_update) 8730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 8830fdc8d8SChris Lattner return m_threads.size(); 8930fdc8d8SChris Lattner } 9030fdc8d8SChris Lattner 9130fdc8d8SChris Lattner ThreadSP 9230fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 9330fdc8d8SChris Lattner { 94ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 9530fdc8d8SChris Lattner if (can_update) 9630fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9730fdc8d8SChris Lattner 9830fdc8d8SChris Lattner ThreadSP thread_sp; 9930fdc8d8SChris Lattner if (idx < m_threads.size()) 10030fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10130fdc8d8SChris Lattner return thread_sp; 10230fdc8d8SChris Lattner } 10330fdc8d8SChris Lattner 10430fdc8d8SChris Lattner ThreadSP 10530fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 10630fdc8d8SChris Lattner { 107ba4e61d3SAndrew Kaylor Mutex::Locker locker(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(); 11530fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 11630fdc8d8SChris Lattner { 11730fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 11830fdc8d8SChris Lattner { 11930fdc8d8SChris Lattner thread_sp = m_threads[idx]; 12030fdc8d8SChris Lattner break; 12130fdc8d8SChris Lattner } 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner return thread_sp; 12430fdc8d8SChris Lattner } 12530fdc8d8SChris Lattner 12630fdc8d8SChris Lattner ThreadSP 127160c9d81SGreg Clayton ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) 128160c9d81SGreg Clayton { 129ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 130160c9d81SGreg Clayton 131160c9d81SGreg Clayton if (can_update) 132160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 133160c9d81SGreg Clayton 134160c9d81SGreg Clayton ThreadSP thread_sp; 135160c9d81SGreg Clayton uint32_t idx = 0; 136160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 137160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 138160c9d81SGreg Clayton { 139160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 140160c9d81SGreg Clayton { 141160c9d81SGreg Clayton thread_sp = m_threads[idx]; 142160c9d81SGreg Clayton break; 143160c9d81SGreg Clayton } 144160c9d81SGreg Clayton } 145160c9d81SGreg Clayton return thread_sp; 146160c9d81SGreg Clayton } 147160c9d81SGreg Clayton 148160c9d81SGreg Clayton 149160c9d81SGreg Clayton ThreadSP 150c2c423eaSHan Ming Ong ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) 151c2c423eaSHan Ming Ong { 152ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 153c2c423eaSHan Ming Ong 154c2c423eaSHan Ming Ong if (can_update) 155c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 156c2c423eaSHan Ming Ong 157c2c423eaSHan Ming Ong ThreadSP thread_sp; 158c2c423eaSHan Ming Ong uint32_t idx = 0; 159c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 160c2c423eaSHan Ming Ong for (idx = 0; idx < num_threads; ++idx) 161c2c423eaSHan Ming Ong { 162c2c423eaSHan Ming Ong if (m_threads[idx]->GetID() == tid) 163c2c423eaSHan Ming Ong { 164c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 165c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin()+idx); 166c2c423eaSHan Ming Ong break; 167c2c423eaSHan Ming Ong } 168c2c423eaSHan Ming Ong } 169c2c423eaSHan Ming Ong return thread_sp; 170c2c423eaSHan Ming Ong } 171c2c423eaSHan Ming Ong 172c2c423eaSHan Ming Ong ThreadSP 173160c9d81SGreg Clayton ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) 174160c9d81SGreg Clayton { 175ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 176160c9d81SGreg Clayton 177160c9d81SGreg Clayton if (can_update) 178160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 179160c9d81SGreg Clayton 180160c9d81SGreg Clayton ThreadSP thread_sp; 181160c9d81SGreg Clayton uint32_t idx = 0; 182160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 183160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 184160c9d81SGreg Clayton { 185160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 186160c9d81SGreg Clayton { 187160c9d81SGreg Clayton thread_sp = m_threads[idx]; 188160c9d81SGreg Clayton m_threads.erase(m_threads.begin()+idx); 189160c9d81SGreg Clayton break; 190160c9d81SGreg Clayton } 191160c9d81SGreg Clayton } 192160c9d81SGreg Clayton return thread_sp; 193160c9d81SGreg Clayton } 194160c9d81SGreg Clayton 195160c9d81SGreg Clayton ThreadSP 19630fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 19730fdc8d8SChris Lattner { 19830fdc8d8SChris Lattner ThreadSP thread_sp; 19930fdc8d8SChris Lattner if (thread_ptr) 20030fdc8d8SChris Lattner { 201ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 20230fdc8d8SChris Lattner 20330fdc8d8SChris Lattner uint32_t idx = 0; 20430fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 20530fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 20630fdc8d8SChris Lattner { 20730fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 20830fdc8d8SChris Lattner { 20930fdc8d8SChris Lattner thread_sp = m_threads[idx]; 21030fdc8d8SChris Lattner break; 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner } 21430fdc8d8SChris Lattner return thread_sp; 21530fdc8d8SChris Lattner } 21630fdc8d8SChris Lattner 21730fdc8d8SChris Lattner 21830fdc8d8SChris Lattner 21930fdc8d8SChris Lattner ThreadSP 22030fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 22130fdc8d8SChris Lattner { 222ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 22330fdc8d8SChris Lattner 22430fdc8d8SChris Lattner if (can_update) 22530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 22630fdc8d8SChris Lattner 22730fdc8d8SChris Lattner ThreadSP thread_sp; 22830fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 22930fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 23030fdc8d8SChris Lattner { 23130fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner thread_sp = m_threads[idx]; 23430fdc8d8SChris Lattner break; 23530fdc8d8SChris Lattner } 23630fdc8d8SChris Lattner } 23730fdc8d8SChris Lattner return thread_sp; 23830fdc8d8SChris Lattner } 23930fdc8d8SChris Lattner 24030fdc8d8SChris Lattner bool 24130fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 24230fdc8d8SChris Lattner { 24330fdc8d8SChris Lattner // Running events should never stop, obviously... 24430fdc8d8SChris Lattner 2455160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 24630fdc8d8SChris Lattner 247b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 24835878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 249b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 250b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 2512f8e4c3bSAdrian McCarthy // to be created. If that happens, we will miss asking them whether 2522f8e4c3bSAdrian McCarthy // they should stop. This is not a big deal since we haven't had 253b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 25430fdc8d8SChris Lattner 255b42f3af3SJim Ingham collection threads_copy; 256b42f3af3SJim Ingham { 257b42f3af3SJim Ingham // Scope for locker 258ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 259b42f3af3SJim Ingham 260b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 261569aaf9eSJim Ingham for (lldb::ThreadSP thread_sp : m_threads) 262569aaf9eSJim Ingham { 263569aaf9eSJim Ingham // This is an optimization... If we didn't let a thread run in between the previous stop and this 264569aaf9eSJim Ingham // one, we shouldn't have to consult it for ShouldStop. So just leave it off the list we are going to 265569aaf9eSJim Ingham // inspect. 2666e8fbc6fSChaoren Lin // On Linux, if a thread-specific conditional breakpoint was hit, it won't necessarily be the thread 2676e8fbc6fSChaoren Lin // that hit the breakpoint itself that evaluates the conditional expression, so the thread that hit 2686e8fbc6fSChaoren Lin // the breakpoint could still be asked to stop, even though it hasn't been allowed to run since the 2696e8fbc6fSChaoren Lin // previous stop. 2706e8fbc6fSChaoren Lin if (thread_sp->GetTemporaryResumeState () != eStateSuspended || thread_sp->IsStillAtLastBreakpointHit()) 271569aaf9eSJim Ingham threads_copy.push_back(thread_sp); 272569aaf9eSJim Ingham } 273569aaf9eSJim Ingham 274569aaf9eSJim Ingham // It is possible the threads we were allowing to run all exited and then maybe the user interrupted 275569aaf9eSJim Ingham // or something, then fall back on looking at all threads: 276569aaf9eSJim Ingham 277569aaf9eSJim Ingham if (threads_copy.size() == 0) 278b42f3af3SJim Ingham threads_copy = m_threads; 279b42f3af3SJim Ingham } 280b42f3af3SJim Ingham 281b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 28230fdc8d8SChris Lattner 2832cad65a5SGreg Clayton if (log) 28410c4b249SJim Ingham { 28510c4b249SJim Ingham log->PutCString(""); 286569aaf9eSJim Ingham log->Printf ("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 " unsuspended threads", 287569aaf9eSJim Ingham __FUNCTION__, 288569aaf9eSJim Ingham (uint64_t)m_threads.size(), 289569aaf9eSJim Ingham (uint64_t)threads_copy.size()); 29010c4b249SJim Ingham } 2912cad65a5SGreg Clayton 292a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 29335878c47SJim Ingham 29435878c47SJim Ingham // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop. 295a0079044SJim Ingham bool should_stop = false; 29635878c47SJim Ingham if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) 29735878c47SJim Ingham { 29835878c47SJim Ingham if (log) 29935878c47SJim Ingham log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__); 30035878c47SJim Ingham 30135878c47SJim Ingham should_stop = true; 30235878c47SJim Ingham } 3037bc3465fSJim Ingham 3047bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 3057bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 3067bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 3077bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 3087bc3465fSJim Ingham 3097bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 3107bc3465fSJim Ingham { 3117bc3465fSJim Ingham ThreadSP thread_sp(*pos); 3127bc3465fSJim Ingham thread_sp->GetStopInfo(); 3137bc3465fSJim Ingham } 314a0079044SJim Ingham 315b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 31630fdc8d8SChris Lattner { 31730fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 3182cad65a5SGreg Clayton 31939fdae7fSJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 32039fdae7fSJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 32139fdae7fSJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 32239fdae7fSJim Ingham // 32339fdae7fSJim Ingham // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint, 32439fdae7fSJim Ingham // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint 32539fdae7fSJim Ingham // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this 32639fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 32739fdae7fSJim Ingham // 32839fdae7fSJim 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 32939fdae7fSJim Ingham // to true unless this is the first stop. 33039fdae7fSJim Ingham // 33139fdae7fSJim Ingham // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid 33239fdae7fSJim Ingham // everywhere but at this check. 33339fdae7fSJim Ingham 33421afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 33539fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 33639fdae7fSJim Ingham else 337a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 338a0079044SJim Ingham 33910c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3402cad65a5SGreg Clayton if (thread_should_stop) 3412cad65a5SGreg Clayton should_stop |= true; 3422cad65a5SGreg Clayton } 3432cad65a5SGreg Clayton 344a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 345a0079044SJim Ingham { 346a0079044SJim Ingham should_stop = true; 347a0079044SJim Ingham if (log) 348a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 349a0079044SJim Ingham } 350a0079044SJim Ingham 3512cad65a5SGreg Clayton if (log) 35210c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 3532cad65a5SGreg Clayton 35430fdc8d8SChris Lattner if (should_stop) 35530fdc8d8SChris Lattner { 356b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 35730fdc8d8SChris Lattner { 35830fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 35930fdc8d8SChris Lattner thread_sp->WillStop (); 36030fdc8d8SChris Lattner } 36130fdc8d8SChris Lattner } 36230fdc8d8SChris Lattner 36330fdc8d8SChris Lattner return should_stop; 36430fdc8d8SChris Lattner } 36530fdc8d8SChris Lattner 36630fdc8d8SChris Lattner Vote 36730fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 36830fdc8d8SChris Lattner { 369ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3702cad65a5SGreg Clayton 37130fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 37230fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 37330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 37430fdc8d8SChris Lattner 3755160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3762cad65a5SGreg Clayton 3772cad65a5SGreg Clayton if (log) 378d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 3792cad65a5SGreg Clayton 38030fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 38130fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 38230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 38330fdc8d8SChris Lattner { 38430fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 385e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 3862cad65a5SGreg Clayton switch (vote) 38730fdc8d8SChris Lattner { 38830fdc8d8SChris Lattner case eVoteNoOpinion: 38930fdc8d8SChris Lattner continue; 3902cad65a5SGreg Clayton 39130fdc8d8SChris Lattner case eVoteYes: 39230fdc8d8SChris Lattner result = eVoteYes; 39330fdc8d8SChris Lattner break; 3942cad65a5SGreg Clayton 39530fdc8d8SChris Lattner case eVoteNo: 39630fdc8d8SChris Lattner if (result == eVoteNoOpinion) 3972cad65a5SGreg Clayton { 39830fdc8d8SChris Lattner result = eVoteNo; 3992cad65a5SGreg Clayton } 4002cad65a5SGreg Clayton else 4012cad65a5SGreg Clayton { 4022cad65a5SGreg Clayton if (log) 403d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 4042cad65a5SGreg Clayton __FUNCTION__, 4052cad65a5SGreg Clayton thread_sp->GetID (), 4062cad65a5SGreg Clayton GetVoteAsCString (vote), 4072cad65a5SGreg Clayton GetVoteAsCString (result)); 4082cad65a5SGreg Clayton } 40930fdc8d8SChris Lattner break; 41030fdc8d8SChris Lattner } 41130fdc8d8SChris Lattner } 4122cad65a5SGreg Clayton if (log) 41310c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 41430fdc8d8SChris Lattner return result; 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner 417221d51cfSJim Ingham void 418221d51cfSJim Ingham ThreadList::SetShouldReportStop (Vote vote) 419221d51cfSJim Ingham { 420221d51cfSJim Ingham Mutex::Locker locker(GetMutex()); 421221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 422221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 423221d51cfSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 424221d51cfSJim Ingham { 425221d51cfSJim Ingham ThreadSP thread_sp(*pos); 426221d51cfSJim Ingham thread_sp->SetShouldReportStop (vote); 427221d51cfSJim Ingham } 428221d51cfSJim Ingham } 429221d51cfSJim Ingham 43030fdc8d8SChris Lattner Vote 43130fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 43230fdc8d8SChris Lattner { 4332cad65a5SGreg Clayton 434ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 4352cad65a5SGreg Clayton 43630fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 43730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 43830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 43930fdc8d8SChris Lattner 44030fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 44130fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 44230fdc8d8SChris Lattner 4435160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 444ce579839SJim Ingham 44530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 44630fdc8d8SChris Lattner { 447ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 448ce579839SJim Ingham { 449ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 45030fdc8d8SChris Lattner { 45130fdc8d8SChris Lattner case eVoteNoOpinion: 45230fdc8d8SChris Lattner continue; 45330fdc8d8SChris Lattner case eVoteYes: 45430fdc8d8SChris Lattner if (result == eVoteNoOpinion) 45530fdc8d8SChris Lattner result = eVoteYes; 45630fdc8d8SChris Lattner break; 45730fdc8d8SChris Lattner case eVoteNo: 458abcbc8acSGreg Clayton if (log) 459d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 460ce579839SJim Ingham (*pos)->GetIndexID(), 461ce579839SJim Ingham (*pos)->GetID()); 46230fdc8d8SChris Lattner result = eVoteNo; 46330fdc8d8SChris Lattner break; 46430fdc8d8SChris Lattner } 46530fdc8d8SChris Lattner } 466ce579839SJim Ingham } 46730fdc8d8SChris Lattner return result; 46830fdc8d8SChris Lattner } 46930fdc8d8SChris Lattner 47030fdc8d8SChris Lattner void 47130fdc8d8SChris Lattner ThreadList::Clear() 47230fdc8d8SChris Lattner { 473ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 47430fdc8d8SChris Lattner m_stop_id = 0; 47530fdc8d8SChris Lattner m_threads.clear(); 4762976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 47730fdc8d8SChris Lattner } 47830fdc8d8SChris Lattner 47930fdc8d8SChris Lattner void 480e1cd1be6SGreg Clayton ThreadList::Destroy() 481e1cd1be6SGreg Clayton { 482ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 483e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 484e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 485e1cd1be6SGreg Clayton { 486e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 487e1cd1be6SGreg Clayton } 488e1cd1be6SGreg Clayton } 489e1cd1be6SGreg Clayton 490e1cd1be6SGreg Clayton void 49130fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 49230fdc8d8SChris Lattner { 493ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 49630fdc8d8SChris Lattner 4975160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 49810c4b249SJim Ingham if (log && log->GetVerbose()) 4991c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5001c823b43SJim Ingham 50130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 50230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 50330fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 50430fdc8d8SChris Lattner } 50530fdc8d8SChris Lattner 50630fdc8d8SChris Lattner void 50730fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 50830fdc8d8SChris Lattner { 50930fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 51030fdc8d8SChris Lattner // that you currently know about have any thread plans. 511ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 51230fdc8d8SChris Lattner 51330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 51430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 51530fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 51630fdc8d8SChris Lattner 51730fdc8d8SChris Lattner } 51830fdc8d8SChris Lattner 51930fdc8d8SChris Lattner bool 52030fdc8d8SChris Lattner ThreadList::WillResume () 52130fdc8d8SChris Lattner { 52230fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 52330fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 52430fdc8d8SChris Lattner // threads stay where they are. 52530fdc8d8SChris Lattner 526ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 52730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 52830fdc8d8SChris Lattner 52930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 53030fdc8d8SChris Lattner 531a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 532a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 533a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 534a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 535a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 536a3241c1bSJim Ingham // take priority. 537a3241c1bSJim Ingham 538a3241c1bSJim Ingham bool wants_solo_run = false; 53930fdc8d8SChris Lattner 54030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 541a3241c1bSJim Ingham { 542*8f186f85SZachary Turner lldbassert((*pos)->GetCurrentPlan() && "thread should not have null thread plan"); 543*8f186f85SZachary Turner if ((*pos)->GetResumeState() != eStateSuspended && 544a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 545a3241c1bSJim Ingham { 5466e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5476e0ff1a3SGreg Clayton continue; 548a3241c1bSJim Ingham wants_solo_run = true; 549a3241c1bSJim Ingham break; 550a3241c1bSJim Ingham } 551a3241c1bSJim Ingham } 552a3241c1bSJim Ingham 5531c823b43SJim Ingham if (wants_solo_run) 5541c823b43SJim Ingham { 5555160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 55610c4b249SJim Ingham if (log && log->GetVerbose()) 5571c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5581c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5591c823b43SJim Ingham } 5601c823b43SJim Ingham else 5611c823b43SJim Ingham { 5625160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 56310c4b249SJim Ingham if (log && log->GetVerbose()) 5641c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5651c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5661c823b43SJim Ingham } 567a3241c1bSJim Ingham 568a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 569a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 570a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 571a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 572a3241c1bSJim Ingham 573a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 574a3241c1bSJim Ingham { 575a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 576a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 577a3241c1bSJim Ingham { 5786e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5796e0ff1a3SGreg Clayton continue; 58030fdc8d8SChris Lattner (*pos)->SetupForResume (); 581a3241c1bSJim Ingham } 582a3241c1bSJim Ingham } 58330fdc8d8SChris Lattner 58430fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 58530fdc8d8SChris Lattner // if so then pick one and run it. 586a3241c1bSJim Ingham 58730fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 58830fdc8d8SChris Lattner 58930fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 59030fdc8d8SChris Lattner 59130fdc8d8SChris Lattner bool run_only_current_thread = false; 59230fdc8d8SChris Lattner 59330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 59430fdc8d8SChris Lattner { 59530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 596b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 59730fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 59830fdc8d8SChris Lattner { 5996e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 6006e0ff1a3SGreg Clayton continue; 6016e0ff1a3SGreg Clayton 60230fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 60330fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 60430fdc8d8SChris Lattner 6052976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 60630fdc8d8SChris Lattner { 607acbea8fbSJim Ingham // If the currently selected thread wants to run on its own, always let it. 60830fdc8d8SChris Lattner run_only_current_thread = true; 60930fdc8d8SChris Lattner run_me_only_list.Clear(); 61030fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 61130fdc8d8SChris Lattner break; 61230fdc8d8SChris Lattner } 61330fdc8d8SChris Lattner 61430fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 61530fdc8d8SChris Lattner } 61630fdc8d8SChris Lattner 61730fdc8d8SChris Lattner } 61830fdc8d8SChris Lattner 619513c6bb8SJim Ingham bool need_to_resume = true; 620513c6bb8SJim Ingham 6216e0ff1a3SGreg Clayton if (run_me_only_list.GetSize (false) == 0) 62230fdc8d8SChris Lattner { 62330fdc8d8SChris Lattner // Everybody runs as they wish: 62430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 62530fdc8d8SChris Lattner { 62630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 627cb5d5a57SJim Ingham StateType run_state; 628cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 629cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 630cb5d5a57SJim Ingham else 631cb5d5a57SJim Ingham run_state = eStateSuspended; 632160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 633513c6bb8SJim Ingham need_to_resume = false; 63430fdc8d8SChris Lattner } 63530fdc8d8SChris Lattner } 63630fdc8d8SChris Lattner else 63730fdc8d8SChris Lattner { 63830fdc8d8SChris Lattner ThreadSP thread_to_run; 63930fdc8d8SChris Lattner 64030fdc8d8SChris Lattner if (run_only_current_thread) 64130fdc8d8SChris Lattner { 6422976d00aSJim Ingham thread_to_run = GetSelectedThread(); 64330fdc8d8SChris Lattner } 64430fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 64530fdc8d8SChris Lattner { 64630fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 64730fdc8d8SChris Lattner } 64830fdc8d8SChris Lattner else 64930fdc8d8SChris Lattner { 65030fdc8d8SChris Lattner int random_thread = (int) 65130fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 65230fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 65330fdc8d8SChris Lattner } 65430fdc8d8SChris Lattner 65530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 65630fdc8d8SChris Lattner { 65730fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 65830fdc8d8SChris Lattner if (thread_sp == thread_to_run) 659513c6bb8SJim Ingham { 660160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 661513c6bb8SJim Ingham need_to_resume = false; 662513c6bb8SJim Ingham } 66330fdc8d8SChris Lattner else 664160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 66530fdc8d8SChris Lattner } 66630fdc8d8SChris Lattner } 66730fdc8d8SChris Lattner 668513c6bb8SJim Ingham return need_to_resume; 66930fdc8d8SChris Lattner } 67030fdc8d8SChris Lattner 67130fdc8d8SChris Lattner void 67230fdc8d8SChris Lattner ThreadList::DidResume () 67330fdc8d8SChris Lattner { 674ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 67530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 67630fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 67730fdc8d8SChris Lattner { 67830fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 67930fdc8d8SChris Lattner // leave their state for the next time around. 68030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 68130fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 68230fdc8d8SChris Lattner thread_sp->DidResume (); 68330fdc8d8SChris Lattner } 68430fdc8d8SChris Lattner } 68530fdc8d8SChris Lattner 68629d65744SAndrew Kaylor void 68729d65744SAndrew Kaylor ThreadList::DidStop () 68829d65744SAndrew Kaylor { 68929d65744SAndrew Kaylor Mutex::Locker locker(GetMutex()); 69029d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 69129d65744SAndrew Kaylor for (pos = m_threads.begin(); pos != end; ++pos) 69229d65744SAndrew Kaylor { 69329d65744SAndrew Kaylor // Notify threads that the process just stopped. 69429d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 69529d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 69629d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 69729d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 69829d65744SAndrew Kaylor // create a special thread list containing only threads which will 69929d65744SAndrew Kaylor // stop in the code that calls this method (currently 70029d65744SAndrew Kaylor // Process::SetPrivateState). 70129d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 70229d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 70329d65744SAndrew Kaylor thread_sp->DidStop (); 70429d65744SAndrew Kaylor } 70529d65744SAndrew Kaylor } 70629d65744SAndrew Kaylor 70730fdc8d8SChris Lattner ThreadSP 7082976d00aSJim Ingham ThreadList::GetSelectedThread () 70930fdc8d8SChris Lattner { 710ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 711943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 712943ddb73SJohnny Chen if (!thread_sp.get()) 713943ddb73SJohnny Chen { 714354b9a65SJason Molenda if (m_threads.size() == 0) 715354b9a65SJason Molenda return thread_sp; 716943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 717943ddb73SJohnny Chen thread_sp = m_threads[0]; 718943ddb73SJohnny Chen } 719943ddb73SJohnny Chen return thread_sp; 72030fdc8d8SChris Lattner } 72130fdc8d8SChris Lattner 72230fdc8d8SChris Lattner bool 723c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 72430fdc8d8SChris Lattner { 725ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 726b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 727b7f6b2faSJim Ingham if (selected_thread_sp) 728b7f6b2faSJim Ingham { 7292976d00aSJim Ingham m_selected_tid = tid; 730b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 731b7f6b2faSJim Ingham } 73230fdc8d8SChris Lattner else 7332976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 73430fdc8d8SChris Lattner 735c3faa195SJim Ingham if (notify) 736c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 737c3faa195SJim Ingham 7382976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 73930fdc8d8SChris Lattner } 74030fdc8d8SChris Lattner 74130fdc8d8SChris Lattner bool 742c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 74330fdc8d8SChris Lattner { 744ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 745b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 746b7f6b2faSJim Ingham if (selected_thread_sp.get()) 747b7f6b2faSJim Ingham { 748b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 749b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 750b7f6b2faSJim Ingham } 75130fdc8d8SChris Lattner else 7522976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 75330fdc8d8SChris Lattner 754c3faa195SJim Ingham if (notify) 755c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 756c3faa195SJim Ingham 7572976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 75830fdc8d8SChris Lattner } 75930fdc8d8SChris Lattner 76056d9a1b3SGreg Clayton void 761c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 762c3faa195SJim Ingham { 763c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 764c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 765c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 766c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 767c3faa195SJim Ingham } 768c3faa195SJim Ingham 769c3faa195SJim Ingham void 77056d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 77156d9a1b3SGreg Clayton { 77256d9a1b3SGreg Clayton if (this != &rhs) 77356d9a1b3SGreg Clayton { 77456d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 775e171da5cSBruce Mitchener // while the assignment occurs 776ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 77756d9a1b3SGreg Clayton m_process = rhs.m_process; 77856d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 77956d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 78056d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 781e1cd1be6SGreg Clayton 782e1cd1be6SGreg Clayton 783e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 784e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 785e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 786e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 787e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 788e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 789e1cd1be6SGreg Clayton // need to work around the issue 790e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 791e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 792e1cd1be6SGreg Clayton { 793e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 794e1cd1be6SGreg Clayton bool thread_is_alive = false; 795e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 796e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 797e1cd1be6SGreg Clayton { 79865d4d5c3SRyan Brown ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); 79965d4d5c3SRyan Brown if (m_threads[idx]->GetID() == tid || (backing_thread && backing_thread->GetID() == tid)) 800e1cd1be6SGreg Clayton { 801e1cd1be6SGreg Clayton thread_is_alive = true; 802e1cd1be6SGreg Clayton break; 803e1cd1be6SGreg Clayton } 804e1cd1be6SGreg Clayton } 805e1cd1be6SGreg Clayton if (!thread_is_alive) 806e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 807e1cd1be6SGreg Clayton } 80856d9a1b3SGreg Clayton } 80956d9a1b3SGreg Clayton } 81056d9a1b3SGreg Clayton 811fa559e5cSGreg Clayton void 812fa559e5cSGreg Clayton ThreadList::Flush () 813fa559e5cSGreg Clayton { 814ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 815fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 816fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 817fa559e5cSGreg Clayton (*pos)->Flush (); 818fa559e5cSGreg Clayton } 81956d9a1b3SGreg Clayton 820ba4e61d3SAndrew Kaylor Mutex & 821ba4e61d3SAndrew Kaylor ThreadList::GetMutex () 822ba4e61d3SAndrew Kaylor { 823ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 824ba4e61d3SAndrew Kaylor } 825ba4e61d3SAndrew Kaylor 826