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" 142cad65a5SGreg Clayton #include "lldb/Target/RegisterContext.h" 1530fdc8d8SChris Lattner #include "lldb/Target/ThreadList.h" 1630fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 1730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h" 1830fdc8d8SChris Lattner #include "lldb/Target/Process.h" 1930fdc8d8SChris Lattner 2030fdc8d8SChris Lattner using namespace lldb; 2130fdc8d8SChris Lattner using namespace lldb_private; 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner ThreadList::ThreadList (Process *process) : 2430fdc8d8SChris Lattner m_process (process), 2530fdc8d8SChris Lattner m_stop_id (0), 2630fdc8d8SChris Lattner m_threads(), 2730fdc8d8SChris Lattner m_threads_mutex (Mutex::eMutexTypeRecursive), 282976d00aSJim Ingham m_selected_tid (LLDB_INVALID_THREAD_ID) 2930fdc8d8SChris Lattner { 3030fdc8d8SChris Lattner } 3130fdc8d8SChris Lattner 3230fdc8d8SChris Lattner ThreadList::ThreadList (const ThreadList &rhs) : 3330fdc8d8SChris Lattner m_process (), 3430fdc8d8SChris Lattner m_stop_id (), 3530fdc8d8SChris Lattner m_threads (), 3630fdc8d8SChris Lattner m_threads_mutex (Mutex::eMutexTypeRecursive), 372976d00aSJim Ingham m_selected_tid () 3830fdc8d8SChris Lattner { 3930fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 4030fdc8d8SChris Lattner *this = rhs; 4130fdc8d8SChris Lattner } 4230fdc8d8SChris Lattner 4330fdc8d8SChris Lattner const ThreadList& 4430fdc8d8SChris Lattner ThreadList::operator = (const ThreadList& rhs) 4530fdc8d8SChris Lattner { 4630fdc8d8SChris Lattner if (this != &rhs) 4730fdc8d8SChris Lattner { 4830fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 4930fdc8d8SChris Lattner // while the assignement occurs 50b132097bSGreg Clayton Mutex::Locker locker_lhs(m_threads_mutex); 5130fdc8d8SChris Lattner Mutex::Locker locker_rhs(rhs.m_threads_mutex); 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 8330fdc8d8SChris Lattner void 84c3776bf2SGreg Clayton ThreadList::AddThread (const ThreadSP &thread_sp) 8530fdc8d8SChris Lattner { 8630fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 8730fdc8d8SChris Lattner m_threads.push_back(thread_sp); 8830fdc8d8SChris Lattner } 8930fdc8d8SChris Lattner 9030fdc8d8SChris Lattner uint32_t 9130fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 9230fdc8d8SChris Lattner { 9330fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 9430fdc8d8SChris Lattner if (can_update) 9530fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9630fdc8d8SChris Lattner return m_threads.size(); 9730fdc8d8SChris Lattner } 9830fdc8d8SChris Lattner 9930fdc8d8SChris Lattner ThreadSP 10030fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 10130fdc8d8SChris Lattner { 10230fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 10330fdc8d8SChris Lattner if (can_update) 10430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 10530fdc8d8SChris Lattner 10630fdc8d8SChris Lattner ThreadSP thread_sp; 10730fdc8d8SChris Lattner if (idx < m_threads.size()) 10830fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10930fdc8d8SChris Lattner return thread_sp; 11030fdc8d8SChris Lattner } 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner ThreadSP 11330fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 11430fdc8d8SChris Lattner { 11530fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner if (can_update) 11830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner ThreadSP thread_sp; 12130fdc8d8SChris Lattner uint32_t idx = 0; 12230fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 12330fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 12430fdc8d8SChris Lattner { 12530fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 12630fdc8d8SChris Lattner { 12730fdc8d8SChris Lattner thread_sp = m_threads[idx]; 12830fdc8d8SChris Lattner break; 12930fdc8d8SChris Lattner } 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner return thread_sp; 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner ThreadSP 135c2c423eaSHan Ming Ong ThreadList::RemoveThreadByID (lldb::tid_t tid, bool can_update) 136c2c423eaSHan Ming Ong { 137c2c423eaSHan Ming Ong Mutex::Locker locker(m_threads_mutex); 138c2c423eaSHan Ming Ong 139c2c423eaSHan Ming Ong if (can_update) 140c2c423eaSHan Ming Ong m_process->UpdateThreadListIfNeeded(); 141c2c423eaSHan Ming Ong 142c2c423eaSHan Ming Ong ThreadSP thread_sp; 143c2c423eaSHan Ming Ong uint32_t idx = 0; 144c2c423eaSHan Ming Ong const uint32_t num_threads = m_threads.size(); 145c2c423eaSHan Ming Ong for (idx = 0; idx < num_threads; ++idx) 146c2c423eaSHan Ming Ong { 147c2c423eaSHan Ming Ong if (m_threads[idx]->GetID() == tid) 148c2c423eaSHan Ming Ong { 149c2c423eaSHan Ming Ong thread_sp = m_threads[idx]; 150c2c423eaSHan Ming Ong m_threads.erase(m_threads.begin()+idx); 151c2c423eaSHan Ming Ong break; 152c2c423eaSHan Ming Ong } 153c2c423eaSHan Ming Ong } 154c2c423eaSHan Ming Ong return thread_sp; 155c2c423eaSHan Ming Ong } 156c2c423eaSHan Ming Ong 157c2c423eaSHan Ming Ong ThreadSP 15830fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 15930fdc8d8SChris Lattner { 16030fdc8d8SChris Lattner ThreadSP thread_sp; 16130fdc8d8SChris Lattner if (thread_ptr) 16230fdc8d8SChris Lattner { 16330fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 16430fdc8d8SChris Lattner 16530fdc8d8SChris Lattner uint32_t idx = 0; 16630fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 16730fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 16830fdc8d8SChris Lattner { 16930fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 17030fdc8d8SChris Lattner { 17130fdc8d8SChris Lattner thread_sp = m_threads[idx]; 17230fdc8d8SChris Lattner break; 17330fdc8d8SChris Lattner } 17430fdc8d8SChris Lattner } 17530fdc8d8SChris Lattner } 17630fdc8d8SChris Lattner return thread_sp; 17730fdc8d8SChris Lattner } 17830fdc8d8SChris Lattner 17930fdc8d8SChris Lattner 18030fdc8d8SChris Lattner 18130fdc8d8SChris Lattner ThreadSP 18230fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 18330fdc8d8SChris Lattner { 18430fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 18530fdc8d8SChris Lattner 18630fdc8d8SChris Lattner if (can_update) 18730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 18830fdc8d8SChris Lattner 18930fdc8d8SChris Lattner ThreadSP thread_sp; 19030fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 19130fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 19230fdc8d8SChris Lattner { 19330fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 19430fdc8d8SChris Lattner { 19530fdc8d8SChris Lattner thread_sp = m_threads[idx]; 19630fdc8d8SChris Lattner break; 19730fdc8d8SChris Lattner } 19830fdc8d8SChris Lattner } 19930fdc8d8SChris Lattner return thread_sp; 20030fdc8d8SChris Lattner } 20130fdc8d8SChris Lattner 20230fdc8d8SChris Lattner bool 20330fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 20430fdc8d8SChris Lattner { 20530fdc8d8SChris Lattner // Running events should never stop, obviously... 20630fdc8d8SChris Lattner 2075160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 20830fdc8d8SChris Lattner 209b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 210b42f3af3SJim Ingham // running breakpoint commands & conditions, etc. So we don't want 211b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 212b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 213b42f3af3SJim Ingham // to be created. If that happens we will miss asking them whether 214b42f3af3SJim Ingham // then should stop. This is not a big deal, since we haven't had 215b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 21630fdc8d8SChris Lattner 217b42f3af3SJim Ingham collection threads_copy; 218b42f3af3SJim Ingham { 219b42f3af3SJim Ingham // Scope for locker 220b42f3af3SJim Ingham Mutex::Locker locker(m_threads_mutex); 221b42f3af3SJim Ingham 222b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 223b42f3af3SJim Ingham threads_copy = m_threads; 224b42f3af3SJim Ingham } 225b42f3af3SJim Ingham 226b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 22730fdc8d8SChris Lattner 2282cad65a5SGreg Clayton if (log) 22910c4b249SJim Ingham { 23010c4b249SJim Ingham log->PutCString(""); 231d01b2953SDaniel Malea log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 23210c4b249SJim Ingham } 2332cad65a5SGreg Clayton 234a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 235a0079044SJim Ingham bool should_stop = false; 236*7bc3465fSJim Ingham 237*7bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 238*7bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 239*7bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 240*7bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 241*7bc3465fSJim Ingham 242*7bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 243*7bc3465fSJim Ingham { 244*7bc3465fSJim Ingham ThreadSP thread_sp(*pos); 245*7bc3465fSJim Ingham thread_sp->GetStopInfo(); 246*7bc3465fSJim Ingham } 247a0079044SJim Ingham 248b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 24930fdc8d8SChris Lattner { 25030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 2512cad65a5SGreg Clayton 252a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 253a0079044SJim Ingham 25410c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 2552cad65a5SGreg Clayton if (thread_should_stop) 2562cad65a5SGreg Clayton should_stop |= true; 2572cad65a5SGreg Clayton } 2582cad65a5SGreg Clayton 259a0079044SJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 260a0079044SJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 261a0079044SJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 262a0079044SJim Ingham 263a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 264a0079044SJim Ingham { 265a0079044SJim Ingham should_stop = true; 266a0079044SJim Ingham if (log) 267a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 268a0079044SJim Ingham } 269a0079044SJim Ingham 2702cad65a5SGreg Clayton if (log) 27110c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 2722cad65a5SGreg Clayton 27330fdc8d8SChris Lattner if (should_stop) 27430fdc8d8SChris Lattner { 275b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 27630fdc8d8SChris Lattner { 27730fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 27830fdc8d8SChris Lattner thread_sp->WillStop (); 27930fdc8d8SChris Lattner } 28030fdc8d8SChris Lattner } 28130fdc8d8SChris Lattner 28230fdc8d8SChris Lattner return should_stop; 28330fdc8d8SChris Lattner } 28430fdc8d8SChris Lattner 28530fdc8d8SChris Lattner Vote 28630fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 28730fdc8d8SChris Lattner { 2882cad65a5SGreg Clayton Mutex::Locker locker(m_threads_mutex); 2892cad65a5SGreg Clayton 29030fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 29130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 29230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 29330fdc8d8SChris Lattner 2945160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 2952cad65a5SGreg Clayton 2962cad65a5SGreg Clayton if (log) 297d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 2982cad65a5SGreg Clayton 29930fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 30030fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 30130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 30230fdc8d8SChris Lattner { 30330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 304e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 3052cad65a5SGreg Clayton switch (vote) 30630fdc8d8SChris Lattner { 30730fdc8d8SChris Lattner case eVoteNoOpinion: 30830fdc8d8SChris Lattner continue; 3092cad65a5SGreg Clayton 31030fdc8d8SChris Lattner case eVoteYes: 31130fdc8d8SChris Lattner result = eVoteYes; 31230fdc8d8SChris Lattner break; 3132cad65a5SGreg Clayton 31430fdc8d8SChris Lattner case eVoteNo: 31530fdc8d8SChris Lattner if (result == eVoteNoOpinion) 3162cad65a5SGreg Clayton { 31730fdc8d8SChris Lattner result = eVoteNo; 3182cad65a5SGreg Clayton } 3192cad65a5SGreg Clayton else 3202cad65a5SGreg Clayton { 3212cad65a5SGreg Clayton if (log) 322d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 3232cad65a5SGreg Clayton __FUNCTION__, 3242cad65a5SGreg Clayton thread_sp->GetID (), 3252cad65a5SGreg Clayton GetVoteAsCString (vote), 3262cad65a5SGreg Clayton GetVoteAsCString (result)); 3272cad65a5SGreg Clayton } 32830fdc8d8SChris Lattner break; 32930fdc8d8SChris Lattner } 33030fdc8d8SChris Lattner } 3312cad65a5SGreg Clayton if (log) 33210c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 33330fdc8d8SChris Lattner return result; 33430fdc8d8SChris Lattner } 33530fdc8d8SChris Lattner 33630fdc8d8SChris Lattner Vote 33730fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 33830fdc8d8SChris Lattner { 3392cad65a5SGreg Clayton 3402cad65a5SGreg Clayton Mutex::Locker locker(m_threads_mutex); 3412cad65a5SGreg Clayton 34230fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 34330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 34430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 34530fdc8d8SChris Lattner 34630fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 34730fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 34830fdc8d8SChris Lattner 3495160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 350ce579839SJim Ingham 35130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 35230fdc8d8SChris Lattner { 353ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 354ce579839SJim Ingham { 355ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 35630fdc8d8SChris Lattner { 35730fdc8d8SChris Lattner case eVoteNoOpinion: 35830fdc8d8SChris Lattner continue; 35930fdc8d8SChris Lattner case eVoteYes: 36030fdc8d8SChris Lattner if (result == eVoteNoOpinion) 36130fdc8d8SChris Lattner result = eVoteYes; 36230fdc8d8SChris Lattner break; 36330fdc8d8SChris Lattner case eVoteNo: 364abcbc8acSGreg Clayton if (log) 365d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 366ce579839SJim Ingham (*pos)->GetIndexID(), 367ce579839SJim Ingham (*pos)->GetID()); 36830fdc8d8SChris Lattner result = eVoteNo; 36930fdc8d8SChris Lattner break; 37030fdc8d8SChris Lattner } 37130fdc8d8SChris Lattner } 372ce579839SJim Ingham } 37330fdc8d8SChris Lattner return result; 37430fdc8d8SChris Lattner } 37530fdc8d8SChris Lattner 37630fdc8d8SChris Lattner void 37730fdc8d8SChris Lattner ThreadList::Clear() 37830fdc8d8SChris Lattner { 379c4e411ffSGreg Clayton Mutex::Locker locker(m_threads_mutex); 38030fdc8d8SChris Lattner m_stop_id = 0; 38130fdc8d8SChris Lattner m_threads.clear(); 3822976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 38330fdc8d8SChris Lattner } 38430fdc8d8SChris Lattner 38530fdc8d8SChris Lattner void 386e1cd1be6SGreg Clayton ThreadList::Destroy() 387e1cd1be6SGreg Clayton { 388e1cd1be6SGreg Clayton Mutex::Locker locker(m_threads_mutex); 389e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 390e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 391e1cd1be6SGreg Clayton { 392e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 393e1cd1be6SGreg Clayton } 394e1cd1be6SGreg Clayton } 395e1cd1be6SGreg Clayton 396e1cd1be6SGreg Clayton void 39730fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 39830fdc8d8SChris Lattner { 39930fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 40030fdc8d8SChris Lattner 40130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 40230fdc8d8SChris Lattner 4035160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 40410c4b249SJim Ingham if (log && log->GetVerbose()) 4051c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4061c823b43SJim Ingham 40730fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 40830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 40930fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 41030fdc8d8SChris Lattner } 41130fdc8d8SChris Lattner 41230fdc8d8SChris Lattner void 41330fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 41430fdc8d8SChris Lattner { 41530fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 41630fdc8d8SChris Lattner // that you currently know about have any thread plans. 41730fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 41830fdc8d8SChris Lattner 41930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 42030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 42130fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 42230fdc8d8SChris Lattner 42330fdc8d8SChris Lattner } 42430fdc8d8SChris Lattner 42530fdc8d8SChris Lattner bool 42630fdc8d8SChris Lattner ThreadList::WillResume () 42730fdc8d8SChris Lattner { 42830fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 42930fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 43030fdc8d8SChris Lattner // threads stay where they are. 43130fdc8d8SChris Lattner 43230fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 43330fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 43430fdc8d8SChris Lattner 43530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 43630fdc8d8SChris Lattner 437a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 438a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 439a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 440a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 441a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 442a3241c1bSJim Ingham // take priority. 443a3241c1bSJim Ingham 444a3241c1bSJim Ingham bool wants_solo_run = false; 44530fdc8d8SChris Lattner 44630fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 447a3241c1bSJim Ingham { 448a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended && 449a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 450a3241c1bSJim Ingham { 451a3241c1bSJim Ingham wants_solo_run = true; 452a3241c1bSJim Ingham break; 453a3241c1bSJim Ingham } 454a3241c1bSJim Ingham } 455a3241c1bSJim Ingham 4561c823b43SJim Ingham if (wants_solo_run) 4571c823b43SJim Ingham { 4585160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 45910c4b249SJim Ingham if (log && log->GetVerbose()) 4601c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 4611c823b43SJim Ingham m_process->StartNoticingNewThreads(); 4621c823b43SJim Ingham } 4631c823b43SJim Ingham else 4641c823b43SJim Ingham { 4655160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 46610c4b249SJim Ingham if (log && log->GetVerbose()) 4671c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4681c823b43SJim Ingham m_process->StopNoticingNewThreads(); 4691c823b43SJim Ingham } 470a3241c1bSJim Ingham 471a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 472a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 473a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 474a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 475a3241c1bSJim Ingham 476a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 477a3241c1bSJim Ingham { 478a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 479a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 480a3241c1bSJim Ingham { 48130fdc8d8SChris Lattner (*pos)->SetupForResume (); 482a3241c1bSJim Ingham } 483a3241c1bSJim Ingham } 48430fdc8d8SChris Lattner 48530fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 48630fdc8d8SChris Lattner // if so then pick one and run it. 487a3241c1bSJim Ingham 48830fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 48930fdc8d8SChris Lattner 49030fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 49130fdc8d8SChris Lattner 49230fdc8d8SChris Lattner ThreadSP immediate_thread_sp; 49330fdc8d8SChris Lattner bool run_only_current_thread = false; 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 49630fdc8d8SChris Lattner { 49730fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 498b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 49930fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 50030fdc8d8SChris Lattner { 50130fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 50230fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 50330fdc8d8SChris Lattner 5042976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 50530fdc8d8SChris Lattner { 50630fdc8d8SChris Lattner run_only_current_thread = true; 50730fdc8d8SChris Lattner run_me_only_list.Clear(); 50830fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 50930fdc8d8SChris Lattner break; 51030fdc8d8SChris Lattner } 51130fdc8d8SChris Lattner 51230fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 51330fdc8d8SChris Lattner } 51430fdc8d8SChris Lattner 51530fdc8d8SChris Lattner } 51630fdc8d8SChris Lattner 517513c6bb8SJim Ingham bool need_to_resume = true; 518513c6bb8SJim Ingham 51930fdc8d8SChris Lattner if (immediate_thread_sp) 52030fdc8d8SChris Lattner { 52130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 52230fdc8d8SChris Lattner { 52330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 52430fdc8d8SChris Lattner if (thread_sp.get() == immediate_thread_sp.get()) 52530fdc8d8SChris Lattner thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState()); 52630fdc8d8SChris Lattner else 52730fdc8d8SChris Lattner thread_sp->WillResume (eStateSuspended); 52830fdc8d8SChris Lattner } 52930fdc8d8SChris Lattner } 53030fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 0) 53130fdc8d8SChris Lattner { 53230fdc8d8SChris Lattner // Everybody runs as they wish: 53330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 53430fdc8d8SChris Lattner { 53530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 536cb5d5a57SJim Ingham StateType run_state; 537cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 538cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 539cb5d5a57SJim Ingham else 540cb5d5a57SJim Ingham run_state = eStateSuspended; 541513c6bb8SJim Ingham if (!thread_sp->WillResume(run_state)) 542513c6bb8SJim Ingham need_to_resume = false; 54330fdc8d8SChris Lattner } 54430fdc8d8SChris Lattner } 54530fdc8d8SChris Lattner else 54630fdc8d8SChris Lattner { 54730fdc8d8SChris Lattner ThreadSP thread_to_run; 54830fdc8d8SChris Lattner 54930fdc8d8SChris Lattner if (run_only_current_thread) 55030fdc8d8SChris Lattner { 5512976d00aSJim Ingham thread_to_run = GetSelectedThread(); 55230fdc8d8SChris Lattner } 55330fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 55430fdc8d8SChris Lattner { 55530fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 55630fdc8d8SChris Lattner } 55730fdc8d8SChris Lattner else 55830fdc8d8SChris Lattner { 55930fdc8d8SChris Lattner int random_thread = (int) 56030fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 56130fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 56230fdc8d8SChris Lattner } 56330fdc8d8SChris Lattner 56430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 56530fdc8d8SChris Lattner { 56630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 56730fdc8d8SChris Lattner if (thread_sp == thread_to_run) 568513c6bb8SJim Ingham { 569513c6bb8SJim Ingham if (!thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState())) 570513c6bb8SJim Ingham need_to_resume = false; 571513c6bb8SJim Ingham } 57230fdc8d8SChris Lattner else 57330fdc8d8SChris Lattner thread_sp->WillResume (eStateSuspended); 57430fdc8d8SChris Lattner } 57530fdc8d8SChris Lattner } 57630fdc8d8SChris Lattner 577513c6bb8SJim Ingham return need_to_resume; 57830fdc8d8SChris Lattner } 57930fdc8d8SChris Lattner 58030fdc8d8SChris Lattner void 58130fdc8d8SChris Lattner ThreadList::DidResume () 58230fdc8d8SChris Lattner { 583c4e411ffSGreg Clayton Mutex::Locker locker(m_threads_mutex); 58430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 58530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 58630fdc8d8SChris Lattner { 58730fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 58830fdc8d8SChris Lattner // leave their state for the next time around. 58930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 59030fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 59130fdc8d8SChris Lattner thread_sp->DidResume (); 59230fdc8d8SChris Lattner } 59330fdc8d8SChris Lattner } 59430fdc8d8SChris Lattner 59530fdc8d8SChris Lattner ThreadSP 5962976d00aSJim Ingham ThreadList::GetSelectedThread () 59730fdc8d8SChris Lattner { 59830fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 599943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 600943ddb73SJohnny Chen if (!thread_sp.get()) 601943ddb73SJohnny Chen { 602354b9a65SJason Molenda if (m_threads.size() == 0) 603354b9a65SJason Molenda return thread_sp; 604943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 605943ddb73SJohnny Chen thread_sp = m_threads[0]; 606943ddb73SJohnny Chen } 607943ddb73SJohnny Chen return thread_sp; 60830fdc8d8SChris Lattner } 60930fdc8d8SChris Lattner 61030fdc8d8SChris Lattner bool 611c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 61230fdc8d8SChris Lattner { 61330fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 614b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 615b7f6b2faSJim Ingham if (selected_thread_sp) 616b7f6b2faSJim Ingham { 6172976d00aSJim Ingham m_selected_tid = tid; 618b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 619b7f6b2faSJim Ingham } 62030fdc8d8SChris Lattner else 6212976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 62230fdc8d8SChris Lattner 623c3faa195SJim Ingham if (notify) 624c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 625c3faa195SJim Ingham 6262976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 62730fdc8d8SChris Lattner } 62830fdc8d8SChris Lattner 62930fdc8d8SChris Lattner bool 630c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 63130fdc8d8SChris Lattner { 63230fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 633b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 634b7f6b2faSJim Ingham if (selected_thread_sp.get()) 635b7f6b2faSJim Ingham { 636b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 637b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 638b7f6b2faSJim Ingham } 63930fdc8d8SChris Lattner else 6402976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 64130fdc8d8SChris Lattner 642c3faa195SJim Ingham if (notify) 643c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 644c3faa195SJim Ingham 6452976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 64630fdc8d8SChris Lattner } 64730fdc8d8SChris Lattner 64856d9a1b3SGreg Clayton void 649c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 650c3faa195SJim Ingham { 651c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 652c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 653c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 654c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 655c3faa195SJim Ingham } 656c3faa195SJim Ingham 657c3faa195SJim Ingham void 65856d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 65956d9a1b3SGreg Clayton { 66056d9a1b3SGreg Clayton if (this != &rhs) 66156d9a1b3SGreg Clayton { 66256d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 66356d9a1b3SGreg Clayton // while the assignement occurs 66456d9a1b3SGreg Clayton Mutex::Locker locker_lhs(m_threads_mutex); 66556d9a1b3SGreg Clayton Mutex::Locker locker_rhs(rhs.m_threads_mutex); 66656d9a1b3SGreg Clayton m_process = rhs.m_process; 66756d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 66856d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 66956d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 670e1cd1be6SGreg Clayton 671e1cd1be6SGreg Clayton 672e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 673e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 674e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 675e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 676e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 677e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 678e1cd1be6SGreg Clayton // need to work around the issue 679e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 680e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 681e1cd1be6SGreg Clayton { 682e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 683e1cd1be6SGreg Clayton bool thread_is_alive = false; 684e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 685e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 686e1cd1be6SGreg Clayton { 687e1cd1be6SGreg Clayton if (m_threads[idx]->GetID() == tid) 688e1cd1be6SGreg Clayton { 689e1cd1be6SGreg Clayton thread_is_alive = true; 690e1cd1be6SGreg Clayton break; 691e1cd1be6SGreg Clayton } 692e1cd1be6SGreg Clayton } 693e1cd1be6SGreg Clayton if (!thread_is_alive) 694e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 695e1cd1be6SGreg Clayton } 69656d9a1b3SGreg Clayton } 69756d9a1b3SGreg Clayton } 69856d9a1b3SGreg Clayton 699fa559e5cSGreg Clayton void 700fa559e5cSGreg Clayton ThreadList::Flush () 701fa559e5cSGreg Clayton { 702fa559e5cSGreg Clayton Mutex::Locker locker(m_threads_mutex); 703fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 704fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 705fa559e5cSGreg Clayton (*pos)->Flush (); 706fa559e5cSGreg Clayton } 70756d9a1b3SGreg Clayton 708