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(), 272976d00aSJim Ingham m_selected_tid (LLDB_INVALID_THREAD_ID) 2830fdc8d8SChris Lattner { 2930fdc8d8SChris Lattner } 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner ThreadList::ThreadList (const ThreadList &rhs) : 32*ba4e61d3SAndrew Kaylor m_process (rhs.m_process), 33*ba4e61d3SAndrew Kaylor m_stop_id (rhs.m_stop_id), 3430fdc8d8SChris Lattner m_threads (), 352976d00aSJim Ingham m_selected_tid () 3630fdc8d8SChris Lattner { 3730fdc8d8SChris Lattner // Use the assignment operator since it uses the mutex 3830fdc8d8SChris Lattner *this = rhs; 3930fdc8d8SChris Lattner } 4030fdc8d8SChris Lattner 4130fdc8d8SChris Lattner const ThreadList& 4230fdc8d8SChris Lattner ThreadList::operator = (const ThreadList& rhs) 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner if (this != &rhs) 4530fdc8d8SChris Lattner { 4630fdc8d8SChris Lattner // Lock both mutexes to make sure neither side changes anyone on us 4730fdc8d8SChris Lattner // while the assignement occurs 48*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 4930fdc8d8SChris Lattner m_process = rhs.m_process; 5030fdc8d8SChris Lattner m_stop_id = rhs.m_stop_id; 5130fdc8d8SChris Lattner m_threads = rhs.m_threads; 522976d00aSJim Ingham m_selected_tid = rhs.m_selected_tid; 5330fdc8d8SChris Lattner } 5430fdc8d8SChris Lattner return *this; 5530fdc8d8SChris Lattner } 5630fdc8d8SChris Lattner 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner ThreadList::~ThreadList() 5930fdc8d8SChris Lattner { 60ac358da5SGreg Clayton // Clear the thread list. Clear will take the mutex lock 61ac358da5SGreg Clayton // which will ensure that if anyone is using the list 62ac358da5SGreg Clayton // they won't get it removed while using it. 63ac358da5SGreg Clayton Clear(); 6430fdc8d8SChris Lattner } 6530fdc8d8SChris Lattner 6630fdc8d8SChris Lattner 6730fdc8d8SChris Lattner uint32_t 6830fdc8d8SChris Lattner ThreadList::GetStopID () const 6930fdc8d8SChris Lattner { 7030fdc8d8SChris Lattner return m_stop_id; 7130fdc8d8SChris Lattner } 7230fdc8d8SChris Lattner 7330fdc8d8SChris Lattner void 7430fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 7530fdc8d8SChris Lattner { 7630fdc8d8SChris Lattner m_stop_id = stop_id; 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner 7930fdc8d8SChris Lattner 8030fdc8d8SChris Lattner void 81c3776bf2SGreg Clayton ThreadList::AddThread (const ThreadSP &thread_sp) 8230fdc8d8SChris Lattner { 83*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 8430fdc8d8SChris Lattner m_threads.push_back(thread_sp); 8530fdc8d8SChris Lattner } 8630fdc8d8SChris Lattner 8730fdc8d8SChris Lattner uint32_t 8830fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 8930fdc8d8SChris Lattner { 90*ba4e61d3SAndrew 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 { 99*ba4e61d3SAndrew 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 { 112*ba4e61d3SAndrew 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 { 134*ba4e61d3SAndrew 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 { 157*ba4e61d3SAndrew 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 { 180*ba4e61d3SAndrew 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 { 206*ba4e61d3SAndrew 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 { 227*ba4e61d3SAndrew 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, 253b42f3af3SJim Ingham // running breakpoint commands & conditions, etc. 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 256b42f3af3SJim Ingham // to be created. If that happens we will miss asking them whether 257b42f3af3SJim Ingham // then 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 263*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 264b42f3af3SJim Ingham 265b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 266b42f3af3SJim Ingham threads_copy = m_threads; 267b42f3af3SJim Ingham } 268b42f3af3SJim Ingham 269b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 27030fdc8d8SChris Lattner 2712cad65a5SGreg Clayton if (log) 27210c4b249SJim Ingham { 27310c4b249SJim Ingham log->PutCString(""); 274d01b2953SDaniel Malea log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 27510c4b249SJim Ingham } 2762cad65a5SGreg Clayton 277a0079044SJim Ingham bool did_anybody_stop_for_a_reason = false; 278a0079044SJim Ingham bool should_stop = false; 2797bc3465fSJim Ingham 2807bc3465fSJim Ingham // Now we run through all the threads and get their stop info's. We want to make sure to do this first before 2817bc3465fSJim Ingham // we start running the ShouldStop, because one thread's ShouldStop could destroy information (like deleting a 2827bc3465fSJim Ingham // thread specific breakpoint another thread had stopped at) which could lead us to compute the StopInfo incorrectly. 2837bc3465fSJim Ingham // We don't need to use it here, we just want to make sure it gets computed. 2847bc3465fSJim Ingham 2857bc3465fSJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 2867bc3465fSJim Ingham { 2877bc3465fSJim Ingham ThreadSP thread_sp(*pos); 2887bc3465fSJim Ingham thread_sp->GetStopInfo(); 2897bc3465fSJim Ingham } 290a0079044SJim Ingham 291b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 29230fdc8d8SChris Lattner { 29330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 2942cad65a5SGreg Clayton 295a0079044SJim Ingham did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason(); 296a0079044SJim Ingham 29710c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 2982cad65a5SGreg Clayton if (thread_should_stop) 2992cad65a5SGreg Clayton should_stop |= true; 3002cad65a5SGreg Clayton } 3012cad65a5SGreg Clayton 302a0079044SJim Ingham // We should never get a stop for which no thread had a stop reason, but sometimes we do see this - 303a0079044SJim Ingham // for instance when we first connect to a remote stub. In that case we should stop, since we can't figure out 304a0079044SJim Ingham // the right thing to do and stopping gives the user control over what to do in this instance. 305a0079044SJim Ingham 306a0079044SJim Ingham if (!should_stop && !did_anybody_stop_for_a_reason) 307a0079044SJim Ingham { 308a0079044SJim Ingham should_stop = true; 309a0079044SJim Ingham if (log) 310a0079044SJim Ingham log->Printf ("ThreadList::%s we stopped but no threads had a stop reason, overriding should_stop and stopping.", __FUNCTION__); 311a0079044SJim Ingham } 312a0079044SJim Ingham 3132cad65a5SGreg Clayton if (log) 31410c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 3152cad65a5SGreg Clayton 31630fdc8d8SChris Lattner if (should_stop) 31730fdc8d8SChris Lattner { 318b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 31930fdc8d8SChris Lattner { 32030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 32130fdc8d8SChris Lattner thread_sp->WillStop (); 32230fdc8d8SChris Lattner } 32330fdc8d8SChris Lattner } 32430fdc8d8SChris Lattner 32530fdc8d8SChris Lattner return should_stop; 32630fdc8d8SChris Lattner } 32730fdc8d8SChris Lattner 32830fdc8d8SChris Lattner Vote 32930fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 33030fdc8d8SChris Lattner { 331*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3322cad65a5SGreg Clayton 33330fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 33430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 33530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 33630fdc8d8SChris Lattner 3375160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3382cad65a5SGreg Clayton 3392cad65a5SGreg Clayton if (log) 340d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 3412cad65a5SGreg Clayton 34230fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 34330fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 34430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 34530fdc8d8SChris Lattner { 34630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 347e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 3482cad65a5SGreg Clayton switch (vote) 34930fdc8d8SChris Lattner { 35030fdc8d8SChris Lattner case eVoteNoOpinion: 35130fdc8d8SChris Lattner continue; 3522cad65a5SGreg Clayton 35330fdc8d8SChris Lattner case eVoteYes: 35430fdc8d8SChris Lattner result = eVoteYes; 35530fdc8d8SChris Lattner break; 3562cad65a5SGreg Clayton 35730fdc8d8SChris Lattner case eVoteNo: 35830fdc8d8SChris Lattner if (result == eVoteNoOpinion) 3592cad65a5SGreg Clayton { 36030fdc8d8SChris Lattner result = eVoteNo; 3612cad65a5SGreg Clayton } 3622cad65a5SGreg Clayton else 3632cad65a5SGreg Clayton { 3642cad65a5SGreg Clayton if (log) 365d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 3662cad65a5SGreg Clayton __FUNCTION__, 3672cad65a5SGreg Clayton thread_sp->GetID (), 3682cad65a5SGreg Clayton GetVoteAsCString (vote), 3692cad65a5SGreg Clayton GetVoteAsCString (result)); 3702cad65a5SGreg Clayton } 37130fdc8d8SChris Lattner break; 37230fdc8d8SChris Lattner } 37330fdc8d8SChris Lattner } 3742cad65a5SGreg Clayton if (log) 37510c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 37630fdc8d8SChris Lattner return result; 37730fdc8d8SChris Lattner } 37830fdc8d8SChris Lattner 37930fdc8d8SChris Lattner Vote 38030fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 38130fdc8d8SChris Lattner { 3822cad65a5SGreg Clayton 383*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3842cad65a5SGreg Clayton 38530fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 38630fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 38730fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 38830fdc8d8SChris Lattner 38930fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 39030fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 39130fdc8d8SChris Lattner 3925160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 393ce579839SJim Ingham 39430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 39530fdc8d8SChris Lattner { 396ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 397ce579839SJim Ingham { 398ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 39930fdc8d8SChris Lattner { 40030fdc8d8SChris Lattner case eVoteNoOpinion: 40130fdc8d8SChris Lattner continue; 40230fdc8d8SChris Lattner case eVoteYes: 40330fdc8d8SChris Lattner if (result == eVoteNoOpinion) 40430fdc8d8SChris Lattner result = eVoteYes; 40530fdc8d8SChris Lattner break; 40630fdc8d8SChris Lattner case eVoteNo: 407abcbc8acSGreg Clayton if (log) 408d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 409ce579839SJim Ingham (*pos)->GetIndexID(), 410ce579839SJim Ingham (*pos)->GetID()); 41130fdc8d8SChris Lattner result = eVoteNo; 41230fdc8d8SChris Lattner break; 41330fdc8d8SChris Lattner } 41430fdc8d8SChris Lattner } 415ce579839SJim Ingham } 41630fdc8d8SChris Lattner return result; 41730fdc8d8SChris Lattner } 41830fdc8d8SChris Lattner 41930fdc8d8SChris Lattner void 42030fdc8d8SChris Lattner ThreadList::Clear() 42130fdc8d8SChris Lattner { 422*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 42330fdc8d8SChris Lattner m_stop_id = 0; 42430fdc8d8SChris Lattner m_threads.clear(); 4252976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 42630fdc8d8SChris Lattner } 42730fdc8d8SChris Lattner 42830fdc8d8SChris Lattner void 429e1cd1be6SGreg Clayton ThreadList::Destroy() 430e1cd1be6SGreg Clayton { 431*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 432e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 433e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 434e1cd1be6SGreg Clayton { 435e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 436e1cd1be6SGreg Clayton } 437e1cd1be6SGreg Clayton } 438e1cd1be6SGreg Clayton 439e1cd1be6SGreg Clayton void 44030fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 44130fdc8d8SChris Lattner { 442*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 44330fdc8d8SChris Lattner 44430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 44530fdc8d8SChris Lattner 4465160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 44710c4b249SJim Ingham if (log && log->GetVerbose()) 4481c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4491c823b43SJim Ingham 45030fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 45130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 45230fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 45330fdc8d8SChris Lattner } 45430fdc8d8SChris Lattner 45530fdc8d8SChris Lattner void 45630fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 45730fdc8d8SChris Lattner { 45830fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 45930fdc8d8SChris Lattner // that you currently know about have any thread plans. 460*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 46130fdc8d8SChris Lattner 46230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 46330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 46430fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 46530fdc8d8SChris Lattner 46630fdc8d8SChris Lattner } 46730fdc8d8SChris Lattner 46830fdc8d8SChris Lattner bool 46930fdc8d8SChris Lattner ThreadList::WillResume () 47030fdc8d8SChris Lattner { 47130fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 47230fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 47330fdc8d8SChris Lattner // threads stay where they are. 47430fdc8d8SChris Lattner 475*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 47630fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 47730fdc8d8SChris Lattner 47830fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 47930fdc8d8SChris Lattner 480a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 481a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 482a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 483a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 484a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 485a3241c1bSJim Ingham // take priority. 486a3241c1bSJim Ingham 487a3241c1bSJim Ingham bool wants_solo_run = false; 48830fdc8d8SChris Lattner 48930fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 490a3241c1bSJim Ingham { 491a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended && 492a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 493a3241c1bSJim Ingham { 494a3241c1bSJim Ingham wants_solo_run = true; 495a3241c1bSJim Ingham break; 496a3241c1bSJim Ingham } 497a3241c1bSJim Ingham } 498a3241c1bSJim Ingham 4991c823b43SJim Ingham if (wants_solo_run) 5001c823b43SJim Ingham { 5015160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 50210c4b249SJim Ingham if (log && log->GetVerbose()) 5031c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5041c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5051c823b43SJim Ingham } 5061c823b43SJim Ingham else 5071c823b43SJim Ingham { 5085160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 50910c4b249SJim Ingham if (log && log->GetVerbose()) 5101c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5111c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5121c823b43SJim Ingham } 513a3241c1bSJim Ingham 514a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 515a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 516a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 517a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 518a3241c1bSJim Ingham 519a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 520a3241c1bSJim Ingham { 521a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 522a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 523a3241c1bSJim Ingham { 52430fdc8d8SChris Lattner (*pos)->SetupForResume (); 525a3241c1bSJim Ingham } 526a3241c1bSJim Ingham } 52730fdc8d8SChris Lattner 52830fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 52930fdc8d8SChris Lattner // if so then pick one and run it. 530a3241c1bSJim Ingham 53130fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 53230fdc8d8SChris Lattner 53330fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 53430fdc8d8SChris Lattner 53530fdc8d8SChris Lattner ThreadSP immediate_thread_sp; 53630fdc8d8SChris Lattner bool run_only_current_thread = false; 53730fdc8d8SChris Lattner 53830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 53930fdc8d8SChris Lattner { 54030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 541b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 54230fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 54330fdc8d8SChris Lattner { 54430fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 54530fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 54630fdc8d8SChris Lattner 5472976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 54830fdc8d8SChris Lattner { 54930fdc8d8SChris Lattner run_only_current_thread = true; 55030fdc8d8SChris Lattner run_me_only_list.Clear(); 55130fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 55230fdc8d8SChris Lattner break; 55330fdc8d8SChris Lattner } 55430fdc8d8SChris Lattner 55530fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 55630fdc8d8SChris Lattner } 55730fdc8d8SChris Lattner 55830fdc8d8SChris Lattner } 55930fdc8d8SChris Lattner 560513c6bb8SJim Ingham bool need_to_resume = true; 561513c6bb8SJim Ingham 56230fdc8d8SChris Lattner if (immediate_thread_sp) 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.get() == immediate_thread_sp.get()) 568160c9d81SGreg Clayton thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()); 56930fdc8d8SChris Lattner else 570160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 57130fdc8d8SChris Lattner } 57230fdc8d8SChris Lattner } 57330fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 0) 57430fdc8d8SChris Lattner { 57530fdc8d8SChris Lattner // Everybody runs as they wish: 57630fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 57730fdc8d8SChris Lattner { 57830fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 579cb5d5a57SJim Ingham StateType run_state; 580cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 581cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 582cb5d5a57SJim Ingham else 583cb5d5a57SJim Ingham run_state = eStateSuspended; 584160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 585513c6bb8SJim Ingham need_to_resume = false; 58630fdc8d8SChris Lattner } 58730fdc8d8SChris Lattner } 58830fdc8d8SChris Lattner else 58930fdc8d8SChris Lattner { 59030fdc8d8SChris Lattner ThreadSP thread_to_run; 59130fdc8d8SChris Lattner 59230fdc8d8SChris Lattner if (run_only_current_thread) 59330fdc8d8SChris Lattner { 5942976d00aSJim Ingham thread_to_run = GetSelectedThread(); 59530fdc8d8SChris Lattner } 59630fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 59730fdc8d8SChris Lattner { 59830fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 59930fdc8d8SChris Lattner } 60030fdc8d8SChris Lattner else 60130fdc8d8SChris Lattner { 60230fdc8d8SChris Lattner int random_thread = (int) 60330fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 60430fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 60530fdc8d8SChris Lattner } 60630fdc8d8SChris Lattner 60730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 60830fdc8d8SChris Lattner { 60930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 61030fdc8d8SChris Lattner if (thread_sp == thread_to_run) 611513c6bb8SJim Ingham { 612160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 613513c6bb8SJim Ingham need_to_resume = false; 614513c6bb8SJim Ingham } 61530fdc8d8SChris Lattner else 616160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 61730fdc8d8SChris Lattner } 61830fdc8d8SChris Lattner } 61930fdc8d8SChris Lattner 620513c6bb8SJim Ingham return need_to_resume; 62130fdc8d8SChris Lattner } 62230fdc8d8SChris Lattner 62330fdc8d8SChris Lattner void 62430fdc8d8SChris Lattner ThreadList::DidResume () 62530fdc8d8SChris Lattner { 626*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 62730fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 62830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 62930fdc8d8SChris Lattner { 63030fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 63130fdc8d8SChris Lattner // leave their state for the next time around. 63230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 63330fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 63430fdc8d8SChris Lattner thread_sp->DidResume (); 63530fdc8d8SChris Lattner } 63630fdc8d8SChris Lattner } 63730fdc8d8SChris Lattner 63830fdc8d8SChris Lattner ThreadSP 6392976d00aSJim Ingham ThreadList::GetSelectedThread () 64030fdc8d8SChris Lattner { 641*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 642943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 643943ddb73SJohnny Chen if (!thread_sp.get()) 644943ddb73SJohnny Chen { 645354b9a65SJason Molenda if (m_threads.size() == 0) 646354b9a65SJason Molenda return thread_sp; 647943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 648943ddb73SJohnny Chen thread_sp = m_threads[0]; 649943ddb73SJohnny Chen } 650943ddb73SJohnny Chen return thread_sp; 65130fdc8d8SChris Lattner } 65230fdc8d8SChris Lattner 65330fdc8d8SChris Lattner bool 654c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 65530fdc8d8SChris Lattner { 656*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 657b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 658b7f6b2faSJim Ingham if (selected_thread_sp) 659b7f6b2faSJim Ingham { 6602976d00aSJim Ingham m_selected_tid = tid; 661b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 662b7f6b2faSJim Ingham } 66330fdc8d8SChris Lattner else 6642976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 66530fdc8d8SChris Lattner 666c3faa195SJim Ingham if (notify) 667c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 668c3faa195SJim Ingham 6692976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 67030fdc8d8SChris Lattner } 67130fdc8d8SChris Lattner 67230fdc8d8SChris Lattner bool 673c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 67430fdc8d8SChris Lattner { 675*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 676b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 677b7f6b2faSJim Ingham if (selected_thread_sp.get()) 678b7f6b2faSJim Ingham { 679b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 680b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 681b7f6b2faSJim Ingham } 68230fdc8d8SChris Lattner else 6832976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 68430fdc8d8SChris Lattner 685c3faa195SJim Ingham if (notify) 686c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 687c3faa195SJim Ingham 6882976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 68930fdc8d8SChris Lattner } 69030fdc8d8SChris Lattner 69156d9a1b3SGreg Clayton void 692c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 693c3faa195SJim Ingham { 694c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 695c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 696c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 697c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 698c3faa195SJim Ingham } 699c3faa195SJim Ingham 700c3faa195SJim Ingham void 70156d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 70256d9a1b3SGreg Clayton { 70356d9a1b3SGreg Clayton if (this != &rhs) 70456d9a1b3SGreg Clayton { 70556d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 70656d9a1b3SGreg Clayton // while the assignement occurs 707*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 70856d9a1b3SGreg Clayton m_process = rhs.m_process; 70956d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 71056d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 71156d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 712e1cd1be6SGreg Clayton 713e1cd1be6SGreg Clayton 714e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 715e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 716e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 717e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 718e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 719e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 720e1cd1be6SGreg Clayton // need to work around the issue 721e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 722e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 723e1cd1be6SGreg Clayton { 724e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 725e1cd1be6SGreg Clayton bool thread_is_alive = false; 726e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 727e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 728e1cd1be6SGreg Clayton { 729e1cd1be6SGreg Clayton if (m_threads[idx]->GetID() == tid) 730e1cd1be6SGreg Clayton { 731e1cd1be6SGreg Clayton thread_is_alive = true; 732e1cd1be6SGreg Clayton break; 733e1cd1be6SGreg Clayton } 734e1cd1be6SGreg Clayton } 735e1cd1be6SGreg Clayton if (!thread_is_alive) 736e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 737e1cd1be6SGreg Clayton } 73856d9a1b3SGreg Clayton } 73956d9a1b3SGreg Clayton } 74056d9a1b3SGreg Clayton 741fa559e5cSGreg Clayton void 742fa559e5cSGreg Clayton ThreadList::Flush () 743fa559e5cSGreg Clayton { 744*ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 745fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 746fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 747fa559e5cSGreg Clayton (*pos)->Flush (); 748fa559e5cSGreg Clayton } 74956d9a1b3SGreg Clayton 750*ba4e61d3SAndrew Kaylor Mutex & 751*ba4e61d3SAndrew Kaylor ThreadList::GetMutex () 752*ba4e61d3SAndrew Kaylor { 753*ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 754*ba4e61d3SAndrew Kaylor } 755*ba4e61d3SAndrew Kaylor 756