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" 2030fdc8d8SChris Lattner 2130fdc8d8SChris Lattner using namespace lldb; 2230fdc8d8SChris Lattner using namespace lldb_private; 2330fdc8d8SChris Lattner 2430fdc8d8SChris Lattner ThreadList::ThreadList (Process *process) : 25*e4d4801cSKuba Brecka ThreadCollection(), 2630fdc8d8SChris Lattner m_process (process), 2730fdc8d8SChris Lattner m_stop_id (0), 282976d00aSJim Ingham m_selected_tid (LLDB_INVALID_THREAD_ID) 2930fdc8d8SChris Lattner { 3030fdc8d8SChris Lattner } 3130fdc8d8SChris Lattner 3230fdc8d8SChris Lattner ThreadList::ThreadList (const ThreadList &rhs) : 33*e4d4801cSKuba Brecka ThreadCollection(), 34ba4e61d3SAndrew Kaylor m_process (rhs.m_process), 35ba4e61d3SAndrew Kaylor m_stop_id (rhs.m_stop_id), 362976d00aSJim Ingham m_selected_tid () 3730fdc8d8SChris Lattner { 3830fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 3930fdc8d8SChris Lattner *this = rhs; 4030fdc8d8SChris Lattner } 4130fdc8d8SChris Lattner 4230fdc8d8SChris Lattner const ThreadList& 4330fdc8d8SChris Lattner ThreadList::operator = (const ThreadList& rhs) 4430fdc8d8SChris Lattner { 4530fdc8d8SChris Lattner if (this != &rhs) 4630fdc8d8SChris Lattner { 4730fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 4830fdc8d8SChris Lattner // while the assignement occurs 49ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 5030fdc8d8SChris Lattner m_process = rhs.m_process; 5130fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5230fdc8d8SChris Lattner m_threads = rhs.m_threads; 532976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner return *this; 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner 5930fdc8d8SChris Lattner ThreadList::~ThreadList() 6030fdc8d8SChris Lattner { 61ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 62ac358da5SGreg Clayton // which will ensure that if anyone is using the list 63ac358da5SGreg Clayton // they won't get it removed while using it. 64ac358da5SGreg Clayton Clear(); 6530fdc8d8SChris Lattner } 6630fdc8d8SChris Lattner 6730fdc8d8SChris Lattner 6830fdc8d8SChris Lattner uint32_t 6930fdc8d8SChris Lattner ThreadList::GetStopID () const 7030fdc8d8SChris Lattner { 7130fdc8d8SChris Lattner return m_stop_id; 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner 7430fdc8d8SChris Lattner void 7530fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 7630fdc8d8SChris Lattner { 7730fdc8d8SChris Lattner m_stop_id = stop_id; 7830fdc8d8SChris Lattner } 7930fdc8d8SChris Lattner 8030fdc8d8SChris Lattner uint32_t 8130fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 8230fdc8d8SChris Lattner { 83ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 8430fdc8d8SChris Lattner if (can_update) 8530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 8630fdc8d8SChris Lattner return m_threads.size(); 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 8930fdc8d8SChris Lattner ThreadSP 9030fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 9130fdc8d8SChris Lattner { 92ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 9330fdc8d8SChris Lattner if (can_update) 9430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9530fdc8d8SChris Lattner 9630fdc8d8SChris Lattner ThreadSP thread_sp; 9730fdc8d8SChris Lattner if (idx < m_threads.size()) 9830fdc8d8SChris Lattner thread_sp = m_threads[idx]; 9930fdc8d8SChris Lattner return thread_sp; 10030fdc8d8SChris Lattner } 10130fdc8d8SChris Lattner 10230fdc8d8SChris Lattner ThreadSP 10330fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 10430fdc8d8SChris Lattner { 105ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 10630fdc8d8SChris Lattner 10730fdc8d8SChris Lattner if (can_update) 10830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner ThreadSP thread_sp; 11130fdc8d8SChris Lattner uint32_t idx = 0; 11230fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 11330fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 11430fdc8d8SChris Lattner { 11530fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 11630fdc8d8SChris Lattner { 11730fdc8d8SChris Lattner thread_sp = m_threads[idx]; 11830fdc8d8SChris Lattner break; 11930fdc8d8SChris Lattner } 12030fdc8d8SChris Lattner } 12130fdc8d8SChris Lattner return thread_sp; 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner ThreadSP 125160c9d81SGreg Clayton ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) 126160c9d81SGreg Clayton { 127ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 128160c9d81SGreg Clayton 129160c9d81SGreg Clayton if (can_update) 130160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 131160c9d81SGreg Clayton 132160c9d81SGreg Clayton ThreadSP thread_sp; 133160c9d81SGreg Clayton uint32_t idx = 0; 134160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 135160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 136160c9d81SGreg Clayton { 137160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 138160c9d81SGreg Clayton { 139160c9d81SGreg Clayton thread_sp = m_threads[idx]; 140160c9d81SGreg Clayton break; 141160c9d81SGreg Clayton } 142160c9d81SGreg Clayton } 143160c9d81SGreg Clayton return thread_sp; 144160c9d81SGreg Clayton } 145160c9d81SGreg Clayton 146160c9d81SGreg Clayton 147160c9d81SGreg Clayton ThreadSP 148c2c423eaSHan Ming Ong ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) 149c2c423eaSHan Ming Ong { 150ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 151c2c423eaSHan Ming Ong 152c2c423eaSHan Ming Ong if (can_update) 153c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 154c2c423eaSHan Ming Ong 155c2c423eaSHan Ming Ong ThreadSP thread_sp; 156c2c423eaSHan Ming Ong uint32_t idx = 0; 157c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 158c2c423eaSHan Ming Ong for (idx = 0; idx < num_threads; ++idx) 159c2c423eaSHan Ming Ong { 160c2c423eaSHan Ming Ong if (m_threads[idx]->GetID() == tid) 161c2c423eaSHan Ming Ong { 162c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 163c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin()+idx); 164c2c423eaSHan Ming Ong break; 165c2c423eaSHan Ming Ong } 166c2c423eaSHan Ming Ong } 167c2c423eaSHan Ming Ong return thread_sp; 168c2c423eaSHan Ming Ong } 169c2c423eaSHan Ming Ong 170c2c423eaSHan Ming Ong ThreadSP 171160c9d81SGreg Clayton ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) 172160c9d81SGreg Clayton { 173ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 174160c9d81SGreg Clayton 175160c9d81SGreg Clayton if (can_update) 176160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 177160c9d81SGreg Clayton 178160c9d81SGreg Clayton ThreadSP thread_sp; 179160c9d81SGreg Clayton uint32_t idx = 0; 180160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 181160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 182160c9d81SGreg Clayton { 183160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 184160c9d81SGreg Clayton { 185160c9d81SGreg Clayton thread_sp = m_threads[idx]; 186160c9d81SGreg Clayton m_threads.erase(m_threads.begin()+idx); 187160c9d81SGreg Clayton break; 188160c9d81SGreg Clayton } 189160c9d81SGreg Clayton } 190160c9d81SGreg Clayton return thread_sp; 191160c9d81SGreg Clayton } 192160c9d81SGreg Clayton 193160c9d81SGreg Clayton ThreadSP 19430fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 19530fdc8d8SChris Lattner { 19630fdc8d8SChris Lattner ThreadSP thread_sp; 19730fdc8d8SChris Lattner if (thread_ptr) 19830fdc8d8SChris Lattner { 199ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 20030fdc8d8SChris Lattner 20130fdc8d8SChris Lattner uint32_t idx = 0; 20230fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 20330fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 20430fdc8d8SChris Lattner { 20530fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 20630fdc8d8SChris Lattner { 20730fdc8d8SChris Lattner thread_sp = m_threads[idx]; 20830fdc8d8SChris Lattner break; 20930fdc8d8SChris Lattner } 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner return thread_sp; 21330fdc8d8SChris Lattner } 21430fdc8d8SChris Lattner 21530fdc8d8SChris Lattner 21630fdc8d8SChris Lattner 21730fdc8d8SChris Lattner ThreadSP 21830fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 21930fdc8d8SChris Lattner { 220ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 22130fdc8d8SChris Lattner 22230fdc8d8SChris Lattner if (can_update) 22330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 22430fdc8d8SChris Lattner 22530fdc8d8SChris Lattner ThreadSP thread_sp; 22630fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 22730fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 22830fdc8d8SChris Lattner { 22930fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 23030fdc8d8SChris Lattner { 23130fdc8d8SChris Lattner thread_sp = m_threads[idx]; 23230fdc8d8SChris Lattner break; 23330fdc8d8SChris Lattner } 23430fdc8d8SChris Lattner } 23530fdc8d8SChris Lattner return thread_sp; 23630fdc8d8SChris Lattner } 23730fdc8d8SChris Lattner 23830fdc8d8SChris Lattner bool 23930fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 24030fdc8d8SChris Lattner { 24130fdc8d8SChris Lattner // Running events should never stop, obviously... 24230fdc8d8SChris Lattner 2435160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 24430fdc8d8SChris Lattner 245b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 24635878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 247b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 248b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 249b42f3af3SJim Ingham // to be created. If that happens we will miss asking them whether 250b42f3af3SJim Ingham // then should stop. This is not a big deal, since we haven't had 251b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 25230fdc8d8SChris Lattner 253b42f3af3SJim Ingham collection threads_copy; 254b42f3af3SJim Ingham { 255b42f3af3SJim Ingham // Scope for locker 256ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 257b42f3af3SJim Ingham 258b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 259b42f3af3SJim Ingham threads_copy = m_threads; 260b42f3af3SJim Ingham } 261b42f3af3SJim Ingham 262b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 26330fdc8d8SChris Lattner 2642cad65a5SGreg Clayton if (log) 26510c4b249SJim Ingham { 26610c4b249SJim Ingham log->PutCString(""); 267d01b2953SDaniel Malea log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 26810c4b249SJim Ingham } 2692cad65a5SGreg Clayton 270a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 27135878c47SJim Ingham 27235878c47SJim Ingham // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop. 273a0079044SJim Ingham bool should_stop = false; 27435878c47SJim Ingham if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) 27535878c47SJim Ingham { 27635878c47SJim Ingham if (log) 27735878c47SJim Ingham log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__); 27835878c47SJim Ingham 27935878c47SJim Ingham should_stop = true; 28035878c47SJim Ingham } 2817bc3465fSJim Ingham 2827bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 2837bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 2847bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 2857bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 2867bc3465fSJim Ingham 2877bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 2887bc3465fSJim Ingham { 2897bc3465fSJim Ingham ThreadSP thread_sp(*pos); 2907bc3465fSJim Ingham thread_sp->GetStopInfo(); 2917bc3465fSJim Ingham } 292a0079044SJim Ingham 293b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 29430fdc8d8SChris Lattner { 29530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 2962cad65a5SGreg Clayton 29739fdae7fSJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 29839fdae7fSJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 29939fdae7fSJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 30039fdae7fSJim Ingham // 30139fdae7fSJim Ingham // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint, 30239fdae7fSJim Ingham // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint 30339fdae7fSJim Ingham // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this 30439fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 30539fdae7fSJim Ingham // 30639fdae7fSJim 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 30739fdae7fSJim Ingham // to true unless this is the first stop. 30839fdae7fSJim Ingham // 30939fdae7fSJim Ingham // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid 31039fdae7fSJim Ingham // everywhere but at this check. 31139fdae7fSJim Ingham 31221afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 31339fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 31439fdae7fSJim Ingham else 315a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 316a0079044SJim Ingham 31710c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3182cad65a5SGreg Clayton if (thread_should_stop) 3192cad65a5SGreg Clayton should_stop |= true; 3202cad65a5SGreg Clayton } 3212cad65a5SGreg Clayton 322a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 323a0079044SJim Ingham { 324a0079044SJim Ingham should_stop = true; 325a0079044SJim Ingham if (log) 326a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 327a0079044SJim Ingham } 328a0079044SJim Ingham 3292cad65a5SGreg Clayton if (log) 33010c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 3312cad65a5SGreg Clayton 33230fdc8d8SChris Lattner if (should_stop) 33330fdc8d8SChris Lattner { 334b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 33530fdc8d8SChris Lattner { 33630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 33730fdc8d8SChris Lattner thread_sp->WillStop (); 33830fdc8d8SChris Lattner } 33930fdc8d8SChris Lattner } 34030fdc8d8SChris Lattner 34130fdc8d8SChris Lattner return should_stop; 34230fdc8d8SChris Lattner } 34330fdc8d8SChris Lattner 34430fdc8d8SChris Lattner Vote 34530fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 34630fdc8d8SChris Lattner { 347ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3482cad65a5SGreg Clayton 34930fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 35030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 35130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 35230fdc8d8SChris Lattner 3535160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3542cad65a5SGreg Clayton 3552cad65a5SGreg Clayton if (log) 356d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 3572cad65a5SGreg Clayton 35830fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 35930fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 36030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 36130fdc8d8SChris Lattner { 36230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 363e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 3642cad65a5SGreg Clayton switch (vote) 36530fdc8d8SChris Lattner { 36630fdc8d8SChris Lattner case eVoteNoOpinion: 36730fdc8d8SChris Lattner continue; 3682cad65a5SGreg Clayton 36930fdc8d8SChris Lattner case eVoteYes: 37030fdc8d8SChris Lattner result = eVoteYes; 37130fdc8d8SChris Lattner break; 3722cad65a5SGreg Clayton 37330fdc8d8SChris Lattner case eVoteNo: 37430fdc8d8SChris Lattner if (result == eVoteNoOpinion) 3752cad65a5SGreg Clayton { 37630fdc8d8SChris Lattner result = eVoteNo; 3772cad65a5SGreg Clayton } 3782cad65a5SGreg Clayton else 3792cad65a5SGreg Clayton { 3802cad65a5SGreg Clayton if (log) 381d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 3822cad65a5SGreg Clayton __FUNCTION__, 3832cad65a5SGreg Clayton thread_sp->GetID (), 3842cad65a5SGreg Clayton GetVoteAsCString (vote), 3852cad65a5SGreg Clayton GetVoteAsCString (result)); 3862cad65a5SGreg Clayton } 38730fdc8d8SChris Lattner break; 38830fdc8d8SChris Lattner } 38930fdc8d8SChris Lattner } 3902cad65a5SGreg Clayton if (log) 39110c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 39230fdc8d8SChris Lattner return result; 39330fdc8d8SChris Lattner } 39430fdc8d8SChris Lattner 395221d51cfSJim Ingham void 396221d51cfSJim Ingham ThreadList::SetShouldReportStop (Vote vote) 397221d51cfSJim Ingham { 398221d51cfSJim Ingham Mutex::Locker locker(GetMutex()); 399221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 400221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 401221d51cfSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 402221d51cfSJim Ingham { 403221d51cfSJim Ingham ThreadSP thread_sp(*pos); 404221d51cfSJim Ingham thread_sp->SetShouldReportStop (vote); 405221d51cfSJim Ingham } 406221d51cfSJim Ingham } 407221d51cfSJim Ingham 40830fdc8d8SChris Lattner Vote 40930fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 41030fdc8d8SChris Lattner { 4112cad65a5SGreg Clayton 412ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 4132cad65a5SGreg Clayton 41430fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 41530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 41630fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 41730fdc8d8SChris Lattner 41830fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 41930fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 42030fdc8d8SChris Lattner 4215160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 422ce579839SJim Ingham 42330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 42430fdc8d8SChris Lattner { 425ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 426ce579839SJim Ingham { 427ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 42830fdc8d8SChris Lattner { 42930fdc8d8SChris Lattner case eVoteNoOpinion: 43030fdc8d8SChris Lattner continue; 43130fdc8d8SChris Lattner case eVoteYes: 43230fdc8d8SChris Lattner if (result == eVoteNoOpinion) 43330fdc8d8SChris Lattner result = eVoteYes; 43430fdc8d8SChris Lattner break; 43530fdc8d8SChris Lattner case eVoteNo: 436abcbc8acSGreg Clayton if (log) 437d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 438ce579839SJim Ingham (*pos)->GetIndexID(), 439ce579839SJim Ingham (*pos)->GetID()); 44030fdc8d8SChris Lattner result = eVoteNo; 44130fdc8d8SChris Lattner break; 44230fdc8d8SChris Lattner } 44330fdc8d8SChris Lattner } 444ce579839SJim Ingham } 44530fdc8d8SChris Lattner return result; 44630fdc8d8SChris Lattner } 44730fdc8d8SChris Lattner 44830fdc8d8SChris Lattner void 44930fdc8d8SChris Lattner ThreadList::Clear() 45030fdc8d8SChris Lattner { 451ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 45230fdc8d8SChris Lattner m_stop_id = 0; 45330fdc8d8SChris Lattner m_threads.clear(); 4542976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 45530fdc8d8SChris Lattner } 45630fdc8d8SChris Lattner 45730fdc8d8SChris Lattner void 458e1cd1be6SGreg Clayton ThreadList::Destroy() 459e1cd1be6SGreg Clayton { 460ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 461e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 462e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 463e1cd1be6SGreg Clayton { 464e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 465e1cd1be6SGreg Clayton } 466e1cd1be6SGreg Clayton } 467e1cd1be6SGreg Clayton 468e1cd1be6SGreg Clayton void 46930fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 47030fdc8d8SChris Lattner { 471ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 47230fdc8d8SChris Lattner 47330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 47430fdc8d8SChris Lattner 4755160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 47610c4b249SJim Ingham if (log && log->GetVerbose()) 4771c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4781c823b43SJim Ingham 47930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 48030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 48130fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 48230fdc8d8SChris Lattner } 48330fdc8d8SChris Lattner 48430fdc8d8SChris Lattner void 48530fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 48630fdc8d8SChris Lattner { 48730fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 48830fdc8d8SChris Lattner // that you currently know about have any thread plans. 489ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 49030fdc8d8SChris Lattner 49130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 49230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 49330fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner } 49630fdc8d8SChris Lattner 49730fdc8d8SChris Lattner bool 49830fdc8d8SChris Lattner ThreadList::WillResume () 49930fdc8d8SChris Lattner { 50030fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 50130fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 50230fdc8d8SChris Lattner // threads stay where they are. 50330fdc8d8SChris Lattner 504ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 50530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 50630fdc8d8SChris Lattner 50730fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 50830fdc8d8SChris Lattner 509a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 510a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 511a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 512a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 513a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 514a3241c1bSJim Ingham // take priority. 515a3241c1bSJim Ingham 516a3241c1bSJim Ingham bool wants_solo_run = false; 51730fdc8d8SChris Lattner 51830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 519a3241c1bSJim Ingham { 520a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended && 521a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 522a3241c1bSJim Ingham { 5236e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5246e0ff1a3SGreg Clayton continue; 525a3241c1bSJim Ingham wants_solo_run = true; 526a3241c1bSJim Ingham break; 527a3241c1bSJim Ingham } 528a3241c1bSJim Ingham } 529a3241c1bSJim Ingham 5301c823b43SJim Ingham if (wants_solo_run) 5311c823b43SJim Ingham { 5325160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 53310c4b249SJim Ingham if (log && log->GetVerbose()) 5341c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5351c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5361c823b43SJim Ingham } 5371c823b43SJim Ingham else 5381c823b43SJim Ingham { 5395160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 54010c4b249SJim Ingham if (log && log->GetVerbose()) 5411c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5421c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5431c823b43SJim Ingham } 544a3241c1bSJim Ingham 545a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 546a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 547a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 548a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 549a3241c1bSJim Ingham 550a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 551a3241c1bSJim Ingham { 552a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 553a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 554a3241c1bSJim Ingham { 5556e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5566e0ff1a3SGreg Clayton continue; 55730fdc8d8SChris Lattner (*pos)->SetupForResume (); 558a3241c1bSJim Ingham } 559a3241c1bSJim Ingham } 56030fdc8d8SChris Lattner 56130fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 56230fdc8d8SChris Lattner // if so then pick one and run it. 563a3241c1bSJim Ingham 56430fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 56530fdc8d8SChris Lattner 56630fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 56730fdc8d8SChris Lattner 56830fdc8d8SChris Lattner bool run_only_current_thread = false; 56930fdc8d8SChris Lattner 57030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 57130fdc8d8SChris Lattner { 57230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 573b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 57430fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 57530fdc8d8SChris Lattner { 5766e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5776e0ff1a3SGreg Clayton continue; 5786e0ff1a3SGreg Clayton 57930fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 58030fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 58130fdc8d8SChris Lattner 5822976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 58330fdc8d8SChris Lattner { 58430fdc8d8SChris Lattner run_only_current_thread = true; 58530fdc8d8SChris Lattner run_me_only_list.Clear(); 58630fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 58730fdc8d8SChris Lattner break; 58830fdc8d8SChris Lattner } 58930fdc8d8SChris Lattner 59030fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 59130fdc8d8SChris Lattner } 59230fdc8d8SChris Lattner 59330fdc8d8SChris Lattner } 59430fdc8d8SChris Lattner 595513c6bb8SJim Ingham bool need_to_resume = true; 596513c6bb8SJim Ingham 5976e0ff1a3SGreg Clayton if (run_me_only_list.GetSize (false) == 0) 59830fdc8d8SChris Lattner { 59930fdc8d8SChris Lattner // Everybody runs as they wish: 60030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 60130fdc8d8SChris Lattner { 60230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 603cb5d5a57SJim Ingham StateType run_state; 604cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 605cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 606cb5d5a57SJim Ingham else 607cb5d5a57SJim Ingham run_state = eStateSuspended; 608160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 609513c6bb8SJim Ingham need_to_resume = false; 61030fdc8d8SChris Lattner } 61130fdc8d8SChris Lattner } 61230fdc8d8SChris Lattner else 61330fdc8d8SChris Lattner { 61430fdc8d8SChris Lattner ThreadSP thread_to_run; 61530fdc8d8SChris Lattner 61630fdc8d8SChris Lattner if (run_only_current_thread) 61730fdc8d8SChris Lattner { 6182976d00aSJim Ingham thread_to_run = GetSelectedThread(); 61930fdc8d8SChris Lattner } 62030fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 62130fdc8d8SChris Lattner { 62230fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 62330fdc8d8SChris Lattner } 62430fdc8d8SChris Lattner else 62530fdc8d8SChris Lattner { 62630fdc8d8SChris Lattner int random_thread = (int) 62730fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 62830fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 62930fdc8d8SChris Lattner } 63030fdc8d8SChris Lattner 63130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 63230fdc8d8SChris Lattner { 63330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 63430fdc8d8SChris Lattner if (thread_sp == thread_to_run) 635513c6bb8SJim Ingham { 636160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 637513c6bb8SJim Ingham need_to_resume = false; 638513c6bb8SJim Ingham } 63930fdc8d8SChris Lattner else 640160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 64130fdc8d8SChris Lattner } 64230fdc8d8SChris Lattner } 64330fdc8d8SChris Lattner 644513c6bb8SJim Ingham return need_to_resume; 64530fdc8d8SChris Lattner } 64630fdc8d8SChris Lattner 64730fdc8d8SChris Lattner void 64830fdc8d8SChris Lattner ThreadList::DidResume () 64930fdc8d8SChris Lattner { 650ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 65130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 65230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 65330fdc8d8SChris Lattner { 65430fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 65530fdc8d8SChris Lattner // leave their state for the next time around. 65630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 65730fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 65830fdc8d8SChris Lattner thread_sp->DidResume (); 65930fdc8d8SChris Lattner } 66030fdc8d8SChris Lattner } 66130fdc8d8SChris Lattner 66229d65744SAndrew Kaylor void 66329d65744SAndrew Kaylor ThreadList::DidStop () 66429d65744SAndrew Kaylor { 66529d65744SAndrew Kaylor Mutex::Locker locker(GetMutex()); 66629d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 66729d65744SAndrew Kaylor for (pos = m_threads.begin(); pos != end; ++pos) 66829d65744SAndrew Kaylor { 66929d65744SAndrew Kaylor // Notify threads that the process just stopped. 67029d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 67129d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 67229d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 67329d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 67429d65744SAndrew Kaylor // create a special thread list containing only threads which will 67529d65744SAndrew Kaylor // stop in the code that calls this method (currently 67629d65744SAndrew Kaylor // Process::SetPrivateState). 67729d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 67829d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 67929d65744SAndrew Kaylor thread_sp->DidStop (); 68029d65744SAndrew Kaylor } 68129d65744SAndrew Kaylor } 68229d65744SAndrew Kaylor 68330fdc8d8SChris Lattner ThreadSP 6842976d00aSJim Ingham ThreadList::GetSelectedThread () 68530fdc8d8SChris Lattner { 686ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 687943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 688943ddb73SJohnny Chen if (!thread_sp.get()) 689943ddb73SJohnny Chen { 690354b9a65SJason Molenda if (m_threads.size() == 0) 691354b9a65SJason Molenda return thread_sp; 692943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 693943ddb73SJohnny Chen thread_sp = m_threads[0]; 694943ddb73SJohnny Chen } 695943ddb73SJohnny Chen return thread_sp; 69630fdc8d8SChris Lattner } 69730fdc8d8SChris Lattner 69830fdc8d8SChris Lattner bool 699c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 70030fdc8d8SChris Lattner { 701ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 702b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 703b7f6b2faSJim Ingham if (selected_thread_sp) 704b7f6b2faSJim Ingham { 7052976d00aSJim Ingham m_selected_tid = tid; 706b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 707b7f6b2faSJim Ingham } 70830fdc8d8SChris Lattner else 7092976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 71030fdc8d8SChris Lattner 711c3faa195SJim Ingham if (notify) 712c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 713c3faa195SJim Ingham 7142976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 71530fdc8d8SChris Lattner } 71630fdc8d8SChris Lattner 71730fdc8d8SChris Lattner bool 718c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 71930fdc8d8SChris Lattner { 720ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 721b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 722b7f6b2faSJim Ingham if (selected_thread_sp.get()) 723b7f6b2faSJim Ingham { 724b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 725b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 726b7f6b2faSJim Ingham } 72730fdc8d8SChris Lattner else 7282976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 72930fdc8d8SChris Lattner 730c3faa195SJim Ingham if (notify) 731c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 732c3faa195SJim Ingham 7332976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 73430fdc8d8SChris Lattner } 73530fdc8d8SChris Lattner 73656d9a1b3SGreg Clayton void 737c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 738c3faa195SJim Ingham { 739c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 740c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 741c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 742c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 743c3faa195SJim Ingham } 744c3faa195SJim Ingham 745c3faa195SJim Ingham void 74656d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 74756d9a1b3SGreg Clayton { 74856d9a1b3SGreg Clayton if (this != &rhs) 74956d9a1b3SGreg Clayton { 75056d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 75156d9a1b3SGreg Clayton // while the assignement occurs 752ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 75356d9a1b3SGreg Clayton m_process = rhs.m_process; 75456d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 75556d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 75656d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 757e1cd1be6SGreg Clayton 758e1cd1be6SGreg Clayton 759e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 760e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 761e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 762e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 763e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 764e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 765e1cd1be6SGreg Clayton // need to work around the issue 766e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 767e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 768e1cd1be6SGreg Clayton { 769e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 770e1cd1be6SGreg Clayton bool thread_is_alive = false; 771e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 772e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 773e1cd1be6SGreg Clayton { 774e1cd1be6SGreg Clayton if (m_threads[idx]->GetID() == tid) 775e1cd1be6SGreg Clayton { 776e1cd1be6SGreg Clayton thread_is_alive = true; 777e1cd1be6SGreg Clayton break; 778e1cd1be6SGreg Clayton } 779e1cd1be6SGreg Clayton } 780e1cd1be6SGreg Clayton if (!thread_is_alive) 781e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 782e1cd1be6SGreg Clayton } 78356d9a1b3SGreg Clayton } 78456d9a1b3SGreg Clayton } 78556d9a1b3SGreg Clayton 786fa559e5cSGreg Clayton void 787fa559e5cSGreg Clayton ThreadList::Flush () 788fa559e5cSGreg Clayton { 789ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 790fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 791fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 792fa559e5cSGreg Clayton (*pos)->Flush (); 793fa559e5cSGreg Clayton } 79456d9a1b3SGreg Clayton 795ba4e61d3SAndrew Kaylor Mutex & 796ba4e61d3SAndrew Kaylor ThreadList::GetMutex () 797ba4e61d3SAndrew Kaylor { 798ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 799ba4e61d3SAndrew Kaylor } 800ba4e61d3SAndrew Kaylor 801