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 //===----------------------------------------------------------------------===// 9*e65b2cf2SEugene Zelenko 10*e65b2cf2SEugene Zelenko // C Includes 1130fdc8d8SChris Lattner #include <stdlib.h> 1230fdc8d8SChris Lattner 13*e65b2cf2SEugene Zelenko // C++ Includes 1430fdc8d8SChris Lattner #include <algorithm> 1530fdc8d8SChris Lattner 16*e65b2cf2SEugene Zelenko // Other libraries and framework includes 17*e65b2cf2SEugene 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 56ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 5730fdc8d8SChris Lattner m_process = rhs.m_process; 5830fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5930fdc8d8SChris Lattner m_threads = rhs.m_threads; 602976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 6130fdc8d8SChris Lattner } 6230fdc8d8SChris Lattner return *this; 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner 6630fdc8d8SChris Lattner ThreadList::~ThreadList() 6730fdc8d8SChris Lattner { 68ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 69ac358da5SGreg Clayton // which will ensure that if anyone is using the list 70ac358da5SGreg Clayton // they won't get it removed while using it. 71ac358da5SGreg Clayton Clear(); 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner uint32_t 7630fdc8d8SChris Lattner ThreadList::GetStopID () const 7730fdc8d8SChris Lattner { 7830fdc8d8SChris Lattner return m_stop_id; 7930fdc8d8SChris Lattner } 8030fdc8d8SChris Lattner 8130fdc8d8SChris Lattner void 8230fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 8330fdc8d8SChris Lattner { 8430fdc8d8SChris Lattner m_stop_id = stop_id; 8530fdc8d8SChris Lattner } 8630fdc8d8SChris Lattner 8730fdc8d8SChris Lattner uint32_t 8830fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 8930fdc8d8SChris Lattner { 90ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 9130fdc8d8SChris Lattner if (can_update) 9230fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9330fdc8d8SChris Lattner return m_threads.size(); 9430fdc8d8SChris Lattner } 9530fdc8d8SChris Lattner 9630fdc8d8SChris Lattner ThreadSP 9730fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 9830fdc8d8SChris Lattner { 99ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 10030fdc8d8SChris Lattner if (can_update) 10130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 10230fdc8d8SChris Lattner 10330fdc8d8SChris Lattner ThreadSP thread_sp; 10430fdc8d8SChris Lattner if (idx < m_threads.size()) 10530fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10630fdc8d8SChris Lattner return thread_sp; 10730fdc8d8SChris Lattner } 10830fdc8d8SChris Lattner 10930fdc8d8SChris Lattner ThreadSP 11030fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 11130fdc8d8SChris Lattner { 112ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 11330fdc8d8SChris Lattner 11430fdc8d8SChris Lattner if (can_update) 11530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner ThreadSP thread_sp; 11830fdc8d8SChris Lattner uint32_t idx = 0; 11930fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 12030fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 12130fdc8d8SChris Lattner { 12230fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 12330fdc8d8SChris Lattner { 12430fdc8d8SChris Lattner thread_sp = m_threads[idx]; 12530fdc8d8SChris Lattner break; 12630fdc8d8SChris Lattner } 12730fdc8d8SChris Lattner } 12830fdc8d8SChris Lattner return thread_sp; 12930fdc8d8SChris Lattner } 13030fdc8d8SChris Lattner 13130fdc8d8SChris Lattner ThreadSP 132160c9d81SGreg Clayton ThreadList::FindThreadByProtocolID (lldb::tid_t tid, bool can_update) 133160c9d81SGreg Clayton { 134ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 135160c9d81SGreg Clayton 136160c9d81SGreg Clayton if (can_update) 137160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 138160c9d81SGreg Clayton 139160c9d81SGreg Clayton ThreadSP thread_sp; 140160c9d81SGreg Clayton uint32_t idx = 0; 141160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 142160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 143160c9d81SGreg Clayton { 144160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 145160c9d81SGreg Clayton { 146160c9d81SGreg Clayton thread_sp = m_threads[idx]; 147160c9d81SGreg Clayton break; 148160c9d81SGreg Clayton } 149160c9d81SGreg Clayton } 150160c9d81SGreg Clayton return thread_sp; 151160c9d81SGreg Clayton } 152160c9d81SGreg Clayton 153160c9d81SGreg Clayton 154160c9d81SGreg Clayton ThreadSP 155c2c423eaSHan Ming Ong ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) 156c2c423eaSHan Ming Ong { 157ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 158c2c423eaSHan Ming Ong 159c2c423eaSHan Ming Ong if (can_update) 160c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 161c2c423eaSHan Ming Ong 162c2c423eaSHan Ming Ong ThreadSP thread_sp; 163c2c423eaSHan Ming Ong uint32_t idx = 0; 164c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 165c2c423eaSHan Ming Ong for (idx = 0; idx < num_threads; ++idx) 166c2c423eaSHan Ming Ong { 167c2c423eaSHan Ming Ong if (m_threads[idx]->GetID() == tid) 168c2c423eaSHan Ming Ong { 169c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 170c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin()+idx); 171c2c423eaSHan Ming Ong break; 172c2c423eaSHan Ming Ong } 173c2c423eaSHan Ming Ong } 174c2c423eaSHan Ming Ong return thread_sp; 175c2c423eaSHan Ming Ong } 176c2c423eaSHan Ming Ong 177c2c423eaSHan Ming Ong ThreadSP 178160c9d81SGreg Clayton ThreadList::RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update) 179160c9d81SGreg Clayton { 180ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 181160c9d81SGreg Clayton 182160c9d81SGreg Clayton if (can_update) 183160c9d81SGreg Clayton m_process->UpdateThreadListIfNeeded(); 184160c9d81SGreg Clayton 185160c9d81SGreg Clayton ThreadSP thread_sp; 186160c9d81SGreg Clayton uint32_t idx = 0; 187160c9d81SGreg Clayton const uint32_t num_threads = m_threads.size(); 188160c9d81SGreg Clayton for (idx = 0; idx < num_threads; ++idx) 189160c9d81SGreg Clayton { 190160c9d81SGreg Clayton if (m_threads[idx]->GetProtocolID() == tid) 191160c9d81SGreg Clayton { 192160c9d81SGreg Clayton thread_sp = m_threads[idx]; 193160c9d81SGreg Clayton m_threads.erase(m_threads.begin()+idx); 194160c9d81SGreg Clayton break; 195160c9d81SGreg Clayton } 196160c9d81SGreg Clayton } 197160c9d81SGreg Clayton return thread_sp; 198160c9d81SGreg Clayton } 199160c9d81SGreg Clayton 200160c9d81SGreg Clayton ThreadSP 20130fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 20230fdc8d8SChris Lattner { 20330fdc8d8SChris Lattner ThreadSP thread_sp; 20430fdc8d8SChris Lattner if (thread_ptr) 20530fdc8d8SChris Lattner { 206ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 20730fdc8d8SChris Lattner 20830fdc8d8SChris Lattner uint32_t idx = 0; 20930fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 21030fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 21130fdc8d8SChris Lattner { 21230fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 21330fdc8d8SChris Lattner { 21430fdc8d8SChris Lattner thread_sp = m_threads[idx]; 21530fdc8d8SChris Lattner break; 21630fdc8d8SChris Lattner } 21730fdc8d8SChris Lattner } 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner return thread_sp; 22030fdc8d8SChris Lattner } 22130fdc8d8SChris Lattner 22230fdc8d8SChris Lattner 22330fdc8d8SChris Lattner 22430fdc8d8SChris Lattner ThreadSP 22530fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 22630fdc8d8SChris Lattner { 227ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 22830fdc8d8SChris Lattner 22930fdc8d8SChris Lattner if (can_update) 23030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 23130fdc8d8SChris Lattner 23230fdc8d8SChris Lattner ThreadSP thread_sp; 23330fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 23430fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 23530fdc8d8SChris Lattner { 23630fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 23730fdc8d8SChris Lattner { 23830fdc8d8SChris Lattner thread_sp = m_threads[idx]; 23930fdc8d8SChris Lattner break; 24030fdc8d8SChris Lattner } 24130fdc8d8SChris Lattner } 24230fdc8d8SChris Lattner return thread_sp; 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner bool 24630fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 24730fdc8d8SChris Lattner { 24830fdc8d8SChris Lattner // Running events should never stop, obviously... 24930fdc8d8SChris Lattner 2505160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 25130fdc8d8SChris Lattner 252b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 25335878c47SJim Ingham // figuring out whether the thread plan conditions are met. So we don't want 254b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 255b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 2562f8e4c3bSAdrian McCarthy // to be created. If that happens, we will miss asking them whether 2572f8e4c3bSAdrian McCarthy // they should stop. This is not a big deal since we haven't had 258b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 25930fdc8d8SChris Lattner 260b42f3af3SJim Ingham collection threads_copy; 261b42f3af3SJim Ingham { 262b42f3af3SJim Ingham // Scope for locker 263ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 264b42f3af3SJim Ingham 265b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 266569aaf9eSJim Ingham for (lldb::ThreadSP thread_sp : m_threads) 267569aaf9eSJim Ingham { 268569aaf9eSJim Ingham // This is an optimization... If we didn't let a thread run in between the previous stop and this 269569aaf9eSJim Ingham // one, we shouldn't have to consult it for ShouldStop. So just leave it off the list we are going to 270569aaf9eSJim Ingham // inspect. 2716e8fbc6fSChaoren Lin // On Linux, if a thread-specific conditional breakpoint was hit, it won't necessarily be the thread 2726e8fbc6fSChaoren Lin // that hit the breakpoint itself that evaluates the conditional expression, so the thread that hit 2736e8fbc6fSChaoren Lin // the breakpoint could still be asked to stop, even though it hasn't been allowed to run since the 2746e8fbc6fSChaoren Lin // previous stop. 2756e8fbc6fSChaoren Lin if (thread_sp->GetTemporaryResumeState () != eStateSuspended || thread_sp->IsStillAtLastBreakpointHit()) 276569aaf9eSJim Ingham threads_copy.push_back(thread_sp); 277569aaf9eSJim Ingham } 278569aaf9eSJim Ingham 279569aaf9eSJim Ingham // It is possible the threads we were allowing to run all exited and then maybe the user interrupted 280569aaf9eSJim Ingham // or something, then fall back on looking at all threads: 281569aaf9eSJim Ingham 282569aaf9eSJim Ingham if (threads_copy.size() == 0) 283b42f3af3SJim Ingham threads_copy = m_threads; 284b42f3af3SJim Ingham } 285b42f3af3SJim Ingham 286b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 28730fdc8d8SChris Lattner 2882cad65a5SGreg Clayton if (log) 28910c4b249SJim Ingham { 29010c4b249SJim Ingham log->PutCString(""); 291569aaf9eSJim Ingham log->Printf ("ThreadList::%s: %" PRIu64 " threads, %" PRIu64 " unsuspended threads", 292569aaf9eSJim Ingham __FUNCTION__, 293569aaf9eSJim Ingham (uint64_t)m_threads.size(), 294569aaf9eSJim Ingham (uint64_t)threads_copy.size()); 29510c4b249SJim Ingham } 2962cad65a5SGreg Clayton 297a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 29835878c47SJim Ingham 29935878c47SJim Ingham // If the event is an Interrupt event, then we're going to stop no matter what. Otherwise, presume we won't stop. 300a0079044SJim Ingham bool should_stop = false; 30135878c47SJim Ingham if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) 30235878c47SJim Ingham { 30335878c47SJim Ingham if (log) 30435878c47SJim Ingham log->Printf("ThreadList::%s handling interrupt event, should stop set to true", __FUNCTION__); 30535878c47SJim Ingham 30635878c47SJim Ingham should_stop = true; 30735878c47SJim Ingham } 3087bc3465fSJim Ingham 3097bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 3107bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 3117bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 3127bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 3137bc3465fSJim Ingham 3147bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 3157bc3465fSJim Ingham { 3167bc3465fSJim Ingham ThreadSP thread_sp(*pos); 3177bc3465fSJim Ingham thread_sp->GetStopInfo(); 3187bc3465fSJim Ingham } 319a0079044SJim Ingham 320b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 32130fdc8d8SChris Lattner { 32230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 3232cad65a5SGreg Clayton 32439fdae7fSJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 32539fdae7fSJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 32639fdae7fSJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 32739fdae7fSJim Ingham // 32839fdae7fSJim Ingham // Note, this causes a problem when you have a thread specific breakpoint, and a bunch of threads hit the breakpoint, 32939fdae7fSJim Ingham // but not the thread which we are waiting for. All the threads that are not "supposed" to hit the breakpoint 33039fdae7fSJim Ingham // are marked as having no stop reason, which is right, they should not show a stop reason. But that triggers this 33139fdae7fSJim Ingham // code and causes us to stop seemingly for no reason. 33239fdae7fSJim Ingham // 33339fdae7fSJim 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 33439fdae7fSJim Ingham // to true unless this is the first stop. 33539fdae7fSJim Ingham // 33639fdae7fSJim Ingham // If this becomes a problem, we'll have to have another StopReason like "StopInfoHidden" which will look invalid 33739fdae7fSJim Ingham // everywhere but at this check. 33839fdae7fSJim Ingham 33921afbe03SEd Maste if (thread_sp->GetProcess()->GetStopID() > 1) 34039fdae7fSJim Ingham did_anybody_stop_for_a_reason = true; 34139fdae7fSJim Ingham else 342a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 343a0079044SJim Ingham 34410c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 3452cad65a5SGreg Clayton if (thread_should_stop) 3462cad65a5SGreg Clayton should_stop |= true; 3472cad65a5SGreg Clayton } 3482cad65a5SGreg Clayton 349a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 350a0079044SJim Ingham { 351a0079044SJim Ingham should_stop = true; 352a0079044SJim Ingham if (log) 353a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 354a0079044SJim Ingham } 355a0079044SJim Ingham 3562cad65a5SGreg Clayton if (log) 35710c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 3582cad65a5SGreg Clayton 35930fdc8d8SChris Lattner if (should_stop) 36030fdc8d8SChris Lattner { 361b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 36230fdc8d8SChris Lattner { 36330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 36430fdc8d8SChris Lattner thread_sp->WillStop (); 36530fdc8d8SChris Lattner } 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner 36830fdc8d8SChris Lattner return should_stop; 36930fdc8d8SChris Lattner } 37030fdc8d8SChris Lattner 37130fdc8d8SChris Lattner Vote 37230fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 37330fdc8d8SChris Lattner { 374ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3752cad65a5SGreg Clayton 37630fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 37730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 37830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 37930fdc8d8SChris Lattner 3805160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3812cad65a5SGreg Clayton 3822cad65a5SGreg Clayton if (log) 383d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 3842cad65a5SGreg Clayton 38530fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 38630fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 38730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 38830fdc8d8SChris Lattner { 38930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 390e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 3912cad65a5SGreg Clayton switch (vote) 39230fdc8d8SChris Lattner { 39330fdc8d8SChris Lattner case eVoteNoOpinion: 39430fdc8d8SChris Lattner continue; 3952cad65a5SGreg Clayton 39630fdc8d8SChris Lattner case eVoteYes: 39730fdc8d8SChris Lattner result = eVoteYes; 39830fdc8d8SChris Lattner break; 3992cad65a5SGreg Clayton 40030fdc8d8SChris Lattner case eVoteNo: 40130fdc8d8SChris Lattner if (result == eVoteNoOpinion) 4022cad65a5SGreg Clayton { 40330fdc8d8SChris Lattner result = eVoteNo; 4042cad65a5SGreg Clayton } 4052cad65a5SGreg Clayton else 4062cad65a5SGreg Clayton { 4072cad65a5SGreg Clayton if (log) 408d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 4092cad65a5SGreg Clayton __FUNCTION__, 4102cad65a5SGreg Clayton thread_sp->GetID (), 4112cad65a5SGreg Clayton GetVoteAsCString (vote), 4122cad65a5SGreg Clayton GetVoteAsCString (result)); 4132cad65a5SGreg Clayton } 41430fdc8d8SChris Lattner break; 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner } 4172cad65a5SGreg Clayton if (log) 41810c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 41930fdc8d8SChris Lattner return result; 42030fdc8d8SChris Lattner } 42130fdc8d8SChris Lattner 422221d51cfSJim Ingham void 423221d51cfSJim Ingham ThreadList::SetShouldReportStop (Vote vote) 424221d51cfSJim Ingham { 425221d51cfSJim Ingham Mutex::Locker locker(GetMutex()); 426221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 427221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 428221d51cfSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 429221d51cfSJim Ingham { 430221d51cfSJim Ingham ThreadSP thread_sp(*pos); 431221d51cfSJim Ingham thread_sp->SetShouldReportStop (vote); 432221d51cfSJim Ingham } 433221d51cfSJim Ingham } 434221d51cfSJim Ingham 43530fdc8d8SChris Lattner Vote 43630fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 43730fdc8d8SChris Lattner { 4382cad65a5SGreg Clayton 439ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 4402cad65a5SGreg Clayton 44130fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 44230fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 44330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 44430fdc8d8SChris Lattner 44530fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 44630fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 44730fdc8d8SChris Lattner 4485160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 449ce579839SJim Ingham 45030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 45130fdc8d8SChris Lattner { 452ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 453ce579839SJim Ingham { 454ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 45530fdc8d8SChris Lattner { 45630fdc8d8SChris Lattner case eVoteNoOpinion: 45730fdc8d8SChris Lattner continue; 45830fdc8d8SChris Lattner case eVoteYes: 45930fdc8d8SChris Lattner if (result == eVoteNoOpinion) 46030fdc8d8SChris Lattner result = eVoteYes; 46130fdc8d8SChris Lattner break; 46230fdc8d8SChris Lattner case eVoteNo: 463abcbc8acSGreg Clayton if (log) 464d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 465ce579839SJim Ingham (*pos)->GetIndexID(), 466ce579839SJim Ingham (*pos)->GetID()); 46730fdc8d8SChris Lattner result = eVoteNo; 46830fdc8d8SChris Lattner break; 46930fdc8d8SChris Lattner } 47030fdc8d8SChris Lattner } 471ce579839SJim Ingham } 47230fdc8d8SChris Lattner return result; 47330fdc8d8SChris Lattner } 47430fdc8d8SChris Lattner 47530fdc8d8SChris Lattner void 47630fdc8d8SChris Lattner ThreadList::Clear() 47730fdc8d8SChris Lattner { 478ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 47930fdc8d8SChris Lattner m_stop_id = 0; 48030fdc8d8SChris Lattner m_threads.clear(); 4812976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 48230fdc8d8SChris Lattner } 48330fdc8d8SChris Lattner 48430fdc8d8SChris Lattner void 485e1cd1be6SGreg Clayton ThreadList::Destroy() 486e1cd1be6SGreg Clayton { 487ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 488e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 489e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 490e1cd1be6SGreg Clayton { 491e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 492e1cd1be6SGreg Clayton } 493e1cd1be6SGreg Clayton } 494e1cd1be6SGreg Clayton 495e1cd1be6SGreg Clayton void 49630fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 49730fdc8d8SChris Lattner { 498ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 49930fdc8d8SChris Lattner 50030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 50130fdc8d8SChris Lattner 5025160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 50310c4b249SJim Ingham if (log && log->GetVerbose()) 5041c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5051c823b43SJim Ingham 50630fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 50730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 50830fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 50930fdc8d8SChris Lattner } 51030fdc8d8SChris Lattner 51130fdc8d8SChris Lattner void 51230fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 51330fdc8d8SChris Lattner { 51430fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 51530fdc8d8SChris Lattner // that you currently know about have any thread plans. 516ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 51730fdc8d8SChris Lattner 51830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 51930fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 52030fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 52130fdc8d8SChris Lattner 52230fdc8d8SChris Lattner } 52330fdc8d8SChris Lattner 52430fdc8d8SChris Lattner bool 52530fdc8d8SChris Lattner ThreadList::WillResume () 52630fdc8d8SChris Lattner { 52730fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 52830fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 52930fdc8d8SChris Lattner // threads stay where they are. 53030fdc8d8SChris Lattner 531ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 53230fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 53330fdc8d8SChris Lattner 53430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 53530fdc8d8SChris Lattner 536a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 537a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 538a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 539a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 540a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 541a3241c1bSJim Ingham // take priority. 542a3241c1bSJim Ingham 543a3241c1bSJim Ingham bool wants_solo_run = false; 54430fdc8d8SChris Lattner 54530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 546a3241c1bSJim Ingham { 5478f186f85SZachary Turner lldbassert((*pos)->GetCurrentPlan() && "thread should not have null thread plan"); 5488f186f85SZachary Turner if ((*pos)->GetResumeState() != eStateSuspended && 549a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 550a3241c1bSJim Ingham { 5516e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5526e0ff1a3SGreg Clayton continue; 553a3241c1bSJim Ingham wants_solo_run = true; 554a3241c1bSJim Ingham break; 555a3241c1bSJim Ingham } 556a3241c1bSJim Ingham } 557a3241c1bSJim Ingham 5581c823b43SJim Ingham if (wants_solo_run) 5591c823b43SJim Ingham { 5605160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 56110c4b249SJim Ingham if (log && log->GetVerbose()) 5621c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5631c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5641c823b43SJim Ingham } 5651c823b43SJim Ingham else 5661c823b43SJim Ingham { 5675160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 56810c4b249SJim Ingham if (log && log->GetVerbose()) 5691c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5701c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5711c823b43SJim Ingham } 572a3241c1bSJim Ingham 573a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 574a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 575a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 576a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 577a3241c1bSJim Ingham 578a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 579a3241c1bSJim Ingham { 580a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 581a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 582a3241c1bSJim Ingham { 5836e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 5846e0ff1a3SGreg Clayton continue; 58530fdc8d8SChris Lattner (*pos)->SetupForResume (); 586a3241c1bSJim Ingham } 587a3241c1bSJim Ingham } 58830fdc8d8SChris Lattner 58930fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 59030fdc8d8SChris Lattner // if so then pick one and run it. 591a3241c1bSJim Ingham 59230fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 59330fdc8d8SChris Lattner 59430fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 59530fdc8d8SChris Lattner 59630fdc8d8SChris Lattner bool run_only_current_thread = false; 59730fdc8d8SChris Lattner 59830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 59930fdc8d8SChris Lattner { 60030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 601b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 60230fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 60330fdc8d8SChris Lattner { 6046e0ff1a3SGreg Clayton if ((*pos)->IsOperatingSystemPluginThread() && !(*pos)->GetBackingThread()) 6056e0ff1a3SGreg Clayton continue; 6066e0ff1a3SGreg Clayton 60730fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 60830fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 60930fdc8d8SChris Lattner 6102976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 61130fdc8d8SChris Lattner { 612acbea8fbSJim Ingham // If the currently selected thread wants to run on its own, always let it. 61330fdc8d8SChris Lattner run_only_current_thread = true; 61430fdc8d8SChris Lattner run_me_only_list.Clear(); 61530fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 61630fdc8d8SChris Lattner break; 61730fdc8d8SChris Lattner } 61830fdc8d8SChris Lattner 61930fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 62030fdc8d8SChris Lattner } 62130fdc8d8SChris Lattner 62230fdc8d8SChris Lattner } 62330fdc8d8SChris Lattner 624513c6bb8SJim Ingham bool need_to_resume = true; 625513c6bb8SJim Ingham 6266e0ff1a3SGreg Clayton if (run_me_only_list.GetSize (false) == 0) 62730fdc8d8SChris Lattner { 62830fdc8d8SChris Lattner // Everybody runs as they wish: 62930fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 63030fdc8d8SChris Lattner { 63130fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 632cb5d5a57SJim Ingham StateType run_state; 633cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 634cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 635cb5d5a57SJim Ingham else 636cb5d5a57SJim Ingham run_state = eStateSuspended; 637160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 638513c6bb8SJim Ingham need_to_resume = false; 63930fdc8d8SChris Lattner } 64030fdc8d8SChris Lattner } 64130fdc8d8SChris Lattner else 64230fdc8d8SChris Lattner { 64330fdc8d8SChris Lattner ThreadSP thread_to_run; 64430fdc8d8SChris Lattner 64530fdc8d8SChris Lattner if (run_only_current_thread) 64630fdc8d8SChris Lattner { 6472976d00aSJim Ingham thread_to_run = GetSelectedThread(); 64830fdc8d8SChris Lattner } 64930fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 65030fdc8d8SChris Lattner { 65130fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 65230fdc8d8SChris Lattner } 65330fdc8d8SChris Lattner else 65430fdc8d8SChris Lattner { 65530fdc8d8SChris Lattner int random_thread = (int) 65630fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 65730fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 65830fdc8d8SChris Lattner } 65930fdc8d8SChris Lattner 66030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 66130fdc8d8SChris Lattner { 66230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 66330fdc8d8SChris Lattner if (thread_sp == thread_to_run) 664513c6bb8SJim Ingham { 665160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 666513c6bb8SJim Ingham need_to_resume = false; 667513c6bb8SJim Ingham } 66830fdc8d8SChris Lattner else 669160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 67030fdc8d8SChris Lattner } 67130fdc8d8SChris Lattner } 67230fdc8d8SChris Lattner 673513c6bb8SJim Ingham return need_to_resume; 67430fdc8d8SChris Lattner } 67530fdc8d8SChris Lattner 67630fdc8d8SChris Lattner void 67730fdc8d8SChris Lattner ThreadList::DidResume () 67830fdc8d8SChris Lattner { 679ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 68030fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 68130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 68230fdc8d8SChris Lattner { 68330fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 68430fdc8d8SChris Lattner // leave their state for the next time around. 68530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 68630fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 68730fdc8d8SChris Lattner thread_sp->DidResume (); 68830fdc8d8SChris Lattner } 68930fdc8d8SChris Lattner } 69030fdc8d8SChris Lattner 69129d65744SAndrew Kaylor void 69229d65744SAndrew Kaylor ThreadList::DidStop () 69329d65744SAndrew Kaylor { 69429d65744SAndrew Kaylor Mutex::Locker locker(GetMutex()); 69529d65744SAndrew Kaylor collection::iterator pos, end = m_threads.end(); 69629d65744SAndrew Kaylor for (pos = m_threads.begin(); pos != end; ++pos) 69729d65744SAndrew Kaylor { 69829d65744SAndrew Kaylor // Notify threads that the process just stopped. 69929d65744SAndrew Kaylor // Note, this currently assumes that all threads in the list 70029d65744SAndrew Kaylor // stop when the process stops. In the future we will want to support 70129d65744SAndrew Kaylor // a debugging model where some threads continue to run while others 70229d65744SAndrew Kaylor // are stopped. We either need to handle that somehow here or 70329d65744SAndrew Kaylor // create a special thread list containing only threads which will 70429d65744SAndrew Kaylor // stop in the code that calls this method (currently 70529d65744SAndrew Kaylor // Process::SetPrivateState). 70629d65744SAndrew Kaylor ThreadSP thread_sp(*pos); 70729d65744SAndrew Kaylor if (StateIsRunningState(thread_sp->GetState())) 70829d65744SAndrew Kaylor thread_sp->DidStop (); 70929d65744SAndrew Kaylor } 71029d65744SAndrew Kaylor } 71129d65744SAndrew Kaylor 71230fdc8d8SChris Lattner ThreadSP 7132976d00aSJim Ingham ThreadList::GetSelectedThread () 71430fdc8d8SChris Lattner { 715ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 716943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 717943ddb73SJohnny Chen if (!thread_sp.get()) 718943ddb73SJohnny Chen { 719354b9a65SJason Molenda if (m_threads.size() == 0) 720354b9a65SJason Molenda return thread_sp; 721943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 722943ddb73SJohnny Chen thread_sp = m_threads[0]; 723943ddb73SJohnny Chen } 724943ddb73SJohnny Chen return thread_sp; 72530fdc8d8SChris Lattner } 72630fdc8d8SChris Lattner 72730fdc8d8SChris Lattner bool 728c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 72930fdc8d8SChris Lattner { 730ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 731b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 732b7f6b2faSJim Ingham if (selected_thread_sp) 733b7f6b2faSJim Ingham { 7342976d00aSJim Ingham m_selected_tid = tid; 735b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 736b7f6b2faSJim Ingham } 73730fdc8d8SChris Lattner else 7382976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 73930fdc8d8SChris Lattner 740c3faa195SJim Ingham if (notify) 741c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 742c3faa195SJim Ingham 7432976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 74430fdc8d8SChris Lattner } 74530fdc8d8SChris Lattner 74630fdc8d8SChris Lattner bool 747c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 74830fdc8d8SChris Lattner { 749ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 750b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 751b7f6b2faSJim Ingham if (selected_thread_sp.get()) 752b7f6b2faSJim Ingham { 753b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 754b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 755b7f6b2faSJim Ingham } 75630fdc8d8SChris Lattner else 7572976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 75830fdc8d8SChris Lattner 759c3faa195SJim Ingham if (notify) 760c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 761c3faa195SJim Ingham 7622976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 76330fdc8d8SChris Lattner } 76430fdc8d8SChris Lattner 76556d9a1b3SGreg Clayton void 766c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 767c3faa195SJim Ingham { 768c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 769c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 770c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 771c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 772c3faa195SJim Ingham } 773c3faa195SJim Ingham 774c3faa195SJim Ingham void 77556d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 77656d9a1b3SGreg Clayton { 77756d9a1b3SGreg Clayton if (this != &rhs) 77856d9a1b3SGreg Clayton { 77956d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 780e171da5cSBruce Mitchener // while the assignment occurs 781ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 78256d9a1b3SGreg Clayton m_process = rhs.m_process; 78356d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 78456d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 78556d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 786e1cd1be6SGreg Clayton 787e1cd1be6SGreg Clayton 788e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 789e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 790e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 791e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 792e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 793e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 794e1cd1be6SGreg Clayton // need to work around the issue 795e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 796e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 797e1cd1be6SGreg Clayton { 798e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 799e1cd1be6SGreg Clayton bool thread_is_alive = false; 800e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 801e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 802e1cd1be6SGreg Clayton { 80365d4d5c3SRyan Brown ThreadSP backing_thread = m_threads[idx]->GetBackingThread(); 80465d4d5c3SRyan Brown if (m_threads[idx]->GetID() == tid || (backing_thread && backing_thread->GetID() == tid)) 805e1cd1be6SGreg Clayton { 806e1cd1be6SGreg Clayton thread_is_alive = true; 807e1cd1be6SGreg Clayton break; 808e1cd1be6SGreg Clayton } 809e1cd1be6SGreg Clayton } 810e1cd1be6SGreg Clayton if (!thread_is_alive) 811e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 812e1cd1be6SGreg Clayton } 81356d9a1b3SGreg Clayton } 81456d9a1b3SGreg Clayton } 81556d9a1b3SGreg Clayton 816fa559e5cSGreg Clayton void 817fa559e5cSGreg Clayton ThreadList::Flush () 818fa559e5cSGreg Clayton { 819ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 820fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 821fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 822fa559e5cSGreg Clayton (*pos)->Flush (); 823fa559e5cSGreg Clayton } 82456d9a1b3SGreg Clayton 825ba4e61d3SAndrew Kaylor Mutex & 826ba4e61d3SAndrew Kaylor ThreadList::GetMutex () 827ba4e61d3SAndrew Kaylor { 828ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 829ba4e61d3SAndrew Kaylor } 830ba4e61d3SAndrew Kaylor 831