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) : 32ba4e61d3SAndrew Kaylor m_process (rhs.m_process), 33ba4e61d3SAndrew 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 48ba4e61d3SAndrew 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 { 83ba4e61d3SAndrew 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 { 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, 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 263ba4e61d3SAndrew 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 { 331ba4e61d3SAndrew 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 379*221d51cfSJim Ingham void 380*221d51cfSJim Ingham ThreadList::SetShouldReportStop (Vote vote) 381*221d51cfSJim Ingham { 382*221d51cfSJim Ingham Mutex::Locker locker(GetMutex()); 383*221d51cfSJim Ingham m_process->UpdateThreadListIfNeeded(); 384*221d51cfSJim Ingham collection::iterator pos, end = m_threads.end(); 385*221d51cfSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 386*221d51cfSJim Ingham { 387*221d51cfSJim Ingham ThreadSP thread_sp(*pos); 388*221d51cfSJim Ingham thread_sp->SetShouldReportStop (vote); 389*221d51cfSJim Ingham } 390*221d51cfSJim Ingham } 391*221d51cfSJim Ingham 39230fdc8d8SChris Lattner Vote 39330fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 39430fdc8d8SChris Lattner { 3952cad65a5SGreg Clayton 396ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 3972cad65a5SGreg Clayton 39830fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 39930fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 40030fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 40130fdc8d8SChris Lattner 40230fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 40330fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 40430fdc8d8SChris Lattner 4055160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 406ce579839SJim Ingham 40730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 40830fdc8d8SChris Lattner { 409ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 410ce579839SJim Ingham { 411ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 41230fdc8d8SChris Lattner { 41330fdc8d8SChris Lattner case eVoteNoOpinion: 41430fdc8d8SChris Lattner continue; 41530fdc8d8SChris Lattner case eVoteYes: 41630fdc8d8SChris Lattner if (result == eVoteNoOpinion) 41730fdc8d8SChris Lattner result = eVoteYes; 41830fdc8d8SChris Lattner break; 41930fdc8d8SChris Lattner case eVoteNo: 420abcbc8acSGreg Clayton if (log) 421d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 422ce579839SJim Ingham (*pos)->GetIndexID(), 423ce579839SJim Ingham (*pos)->GetID()); 42430fdc8d8SChris Lattner result = eVoteNo; 42530fdc8d8SChris Lattner break; 42630fdc8d8SChris Lattner } 42730fdc8d8SChris Lattner } 428ce579839SJim Ingham } 42930fdc8d8SChris Lattner return result; 43030fdc8d8SChris Lattner } 43130fdc8d8SChris Lattner 43230fdc8d8SChris Lattner void 43330fdc8d8SChris Lattner ThreadList::Clear() 43430fdc8d8SChris Lattner { 435ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 43630fdc8d8SChris Lattner m_stop_id = 0; 43730fdc8d8SChris Lattner m_threads.clear(); 4382976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 43930fdc8d8SChris Lattner } 44030fdc8d8SChris Lattner 44130fdc8d8SChris Lattner void 442e1cd1be6SGreg Clayton ThreadList::Destroy() 443e1cd1be6SGreg Clayton { 444ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 445e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 446e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 447e1cd1be6SGreg Clayton { 448e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 449e1cd1be6SGreg Clayton } 450e1cd1be6SGreg Clayton } 451e1cd1be6SGreg Clayton 452e1cd1be6SGreg Clayton void 45330fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 45430fdc8d8SChris Lattner { 455ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 45630fdc8d8SChris Lattner 45730fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 45830fdc8d8SChris Lattner 4595160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 46010c4b249SJim Ingham if (log && log->GetVerbose()) 4611c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4621c823b43SJim Ingham 46330fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 46430fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 46530fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 46630fdc8d8SChris Lattner } 46730fdc8d8SChris Lattner 46830fdc8d8SChris Lattner void 46930fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 47030fdc8d8SChris Lattner { 47130fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 47230fdc8d8SChris Lattner // that you currently know about have any thread plans. 473ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 47430fdc8d8SChris Lattner 47530fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 47630fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 47730fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 47830fdc8d8SChris Lattner 47930fdc8d8SChris Lattner } 48030fdc8d8SChris Lattner 48130fdc8d8SChris Lattner bool 48230fdc8d8SChris Lattner ThreadList::WillResume () 48330fdc8d8SChris Lattner { 48430fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 48530fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 48630fdc8d8SChris Lattner // threads stay where they are. 48730fdc8d8SChris Lattner 488ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 48930fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 49030fdc8d8SChris Lattner 49130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 49230fdc8d8SChris Lattner 493a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 494a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 495a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 496a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 497a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 498a3241c1bSJim Ingham // take priority. 499a3241c1bSJim Ingham 500a3241c1bSJim Ingham bool wants_solo_run = false; 50130fdc8d8SChris Lattner 50230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 503a3241c1bSJim Ingham { 504a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended && 505a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 506a3241c1bSJim Ingham { 507a3241c1bSJim Ingham wants_solo_run = true; 508a3241c1bSJim Ingham break; 509a3241c1bSJim Ingham } 510a3241c1bSJim Ingham } 511a3241c1bSJim Ingham 5121c823b43SJim Ingham if (wants_solo_run) 5131c823b43SJim Ingham { 5145160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 51510c4b249SJim Ingham if (log && log->GetVerbose()) 5161c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 5171c823b43SJim Ingham m_process->StartNoticingNewThreads(); 5181c823b43SJim Ingham } 5191c823b43SJim Ingham else 5201c823b43SJim Ingham { 5215160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 52210c4b249SJim Ingham if (log && log->GetVerbose()) 5231c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 5241c823b43SJim Ingham m_process->StopNoticingNewThreads(); 5251c823b43SJim Ingham } 526a3241c1bSJim Ingham 527a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 528a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 529a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 530a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 531a3241c1bSJim Ingham 532a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 533a3241c1bSJim Ingham { 534a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 535a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 536a3241c1bSJim Ingham { 53730fdc8d8SChris Lattner (*pos)->SetupForResume (); 538a3241c1bSJim Ingham } 539a3241c1bSJim Ingham } 54030fdc8d8SChris Lattner 54130fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 54230fdc8d8SChris Lattner // if so then pick one and run it. 543a3241c1bSJim Ingham 54430fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 54530fdc8d8SChris Lattner 54630fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 54730fdc8d8SChris Lattner 54830fdc8d8SChris Lattner ThreadSP immediate_thread_sp; 54930fdc8d8SChris Lattner bool run_only_current_thread = false; 55030fdc8d8SChris Lattner 55130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 55230fdc8d8SChris Lattner { 55330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 554b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 55530fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 55630fdc8d8SChris Lattner { 55730fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 55830fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 55930fdc8d8SChris Lattner 5602976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 56130fdc8d8SChris Lattner { 56230fdc8d8SChris Lattner run_only_current_thread = true; 56330fdc8d8SChris Lattner run_me_only_list.Clear(); 56430fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 56530fdc8d8SChris Lattner break; 56630fdc8d8SChris Lattner } 56730fdc8d8SChris Lattner 56830fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 56930fdc8d8SChris Lattner } 57030fdc8d8SChris Lattner 57130fdc8d8SChris Lattner } 57230fdc8d8SChris Lattner 573513c6bb8SJim Ingham bool need_to_resume = true; 574513c6bb8SJim Ingham 57530fdc8d8SChris Lattner if (immediate_thread_sp) 57630fdc8d8SChris Lattner { 57730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 57830fdc8d8SChris Lattner { 57930fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 58030fdc8d8SChris Lattner if (thread_sp.get() == immediate_thread_sp.get()) 581160c9d81SGreg Clayton thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()); 58230fdc8d8SChris Lattner else 583160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 58430fdc8d8SChris Lattner } 58530fdc8d8SChris Lattner } 58630fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 0) 58730fdc8d8SChris Lattner { 58830fdc8d8SChris Lattner // Everybody runs as they wish: 58930fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 59030fdc8d8SChris Lattner { 59130fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 592cb5d5a57SJim Ingham StateType run_state; 593cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 594cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 595cb5d5a57SJim Ingham else 596cb5d5a57SJim Ingham run_state = eStateSuspended; 597160c9d81SGreg Clayton if (!thread_sp->ShouldResume(run_state)) 598513c6bb8SJim Ingham need_to_resume = false; 59930fdc8d8SChris Lattner } 60030fdc8d8SChris Lattner } 60130fdc8d8SChris Lattner else 60230fdc8d8SChris Lattner { 60330fdc8d8SChris Lattner ThreadSP thread_to_run; 60430fdc8d8SChris Lattner 60530fdc8d8SChris Lattner if (run_only_current_thread) 60630fdc8d8SChris Lattner { 6072976d00aSJim Ingham thread_to_run = GetSelectedThread(); 60830fdc8d8SChris Lattner } 60930fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 61030fdc8d8SChris Lattner { 61130fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 61230fdc8d8SChris Lattner } 61330fdc8d8SChris Lattner else 61430fdc8d8SChris Lattner { 61530fdc8d8SChris Lattner int random_thread = (int) 61630fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 61730fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 61830fdc8d8SChris Lattner } 61930fdc8d8SChris Lattner 62030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 62130fdc8d8SChris Lattner { 62230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 62330fdc8d8SChris Lattner if (thread_sp == thread_to_run) 624513c6bb8SJim Ingham { 625160c9d81SGreg Clayton if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState())) 626513c6bb8SJim Ingham need_to_resume = false; 627513c6bb8SJim Ingham } 62830fdc8d8SChris Lattner else 629160c9d81SGreg Clayton thread_sp->ShouldResume (eStateSuspended); 63030fdc8d8SChris Lattner } 63130fdc8d8SChris Lattner } 63230fdc8d8SChris Lattner 633513c6bb8SJim Ingham return need_to_resume; 63430fdc8d8SChris Lattner } 63530fdc8d8SChris Lattner 63630fdc8d8SChris Lattner void 63730fdc8d8SChris Lattner ThreadList::DidResume () 63830fdc8d8SChris Lattner { 639ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 64030fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 64130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 64230fdc8d8SChris Lattner { 64330fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 64430fdc8d8SChris Lattner // leave their state for the next time around. 64530fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 64630fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 64730fdc8d8SChris Lattner thread_sp->DidResume (); 64830fdc8d8SChris Lattner } 64930fdc8d8SChris Lattner } 65030fdc8d8SChris Lattner 65130fdc8d8SChris Lattner ThreadSP 6522976d00aSJim Ingham ThreadList::GetSelectedThread () 65330fdc8d8SChris Lattner { 654ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 655943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 656943ddb73SJohnny Chen if (!thread_sp.get()) 657943ddb73SJohnny Chen { 658354b9a65SJason Molenda if (m_threads.size() == 0) 659354b9a65SJason Molenda return thread_sp; 660943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 661943ddb73SJohnny Chen thread_sp = m_threads[0]; 662943ddb73SJohnny Chen } 663943ddb73SJohnny Chen return thread_sp; 66430fdc8d8SChris Lattner } 66530fdc8d8SChris Lattner 66630fdc8d8SChris Lattner bool 667c3faa195SJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid, bool notify) 66830fdc8d8SChris Lattner { 669ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 670b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 671b7f6b2faSJim Ingham if (selected_thread_sp) 672b7f6b2faSJim Ingham { 6732976d00aSJim Ingham m_selected_tid = tid; 674b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 675b7f6b2faSJim Ingham } 67630fdc8d8SChris Lattner else 6772976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 67830fdc8d8SChris Lattner 679c3faa195SJim Ingham if (notify) 680c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 681c3faa195SJim Ingham 6822976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 68330fdc8d8SChris Lattner } 68430fdc8d8SChris Lattner 68530fdc8d8SChris Lattner bool 686c3faa195SJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id, bool notify) 68730fdc8d8SChris Lattner { 688ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 689b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 690b7f6b2faSJim Ingham if (selected_thread_sp.get()) 691b7f6b2faSJim Ingham { 692b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 693b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 694b7f6b2faSJim Ingham } 69530fdc8d8SChris Lattner else 6962976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 69730fdc8d8SChris Lattner 698c3faa195SJim Ingham if (notify) 699c3faa195SJim Ingham NotifySelectedThreadChanged(m_selected_tid); 700c3faa195SJim Ingham 7012976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 70230fdc8d8SChris Lattner } 70330fdc8d8SChris Lattner 70456d9a1b3SGreg Clayton void 705c3faa195SJim Ingham ThreadList::NotifySelectedThreadChanged (lldb::tid_t tid) 706c3faa195SJim Ingham { 707c3faa195SJim Ingham ThreadSP selected_thread_sp (FindThreadByID(tid)); 708c3faa195SJim Ingham if (selected_thread_sp->EventTypeHasListeners(Thread::eBroadcastBitThreadSelected)) 709c3faa195SJim Ingham selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected, 710c3faa195SJim Ingham new Thread::ThreadEventData(selected_thread_sp)); 711c3faa195SJim Ingham } 712c3faa195SJim Ingham 713c3faa195SJim Ingham void 71456d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 71556d9a1b3SGreg Clayton { 71656d9a1b3SGreg Clayton if (this != &rhs) 71756d9a1b3SGreg Clayton { 71856d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 71956d9a1b3SGreg Clayton // while the assignement occurs 720ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 72156d9a1b3SGreg Clayton m_process = rhs.m_process; 72256d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 72356d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 72456d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 725e1cd1be6SGreg Clayton 726e1cd1be6SGreg Clayton 727e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 728e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 729e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 730e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 731e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 732e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 733e1cd1be6SGreg Clayton // need to work around the issue 734e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 735e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 736e1cd1be6SGreg Clayton { 737e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 738e1cd1be6SGreg Clayton bool thread_is_alive = false; 739e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 740e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 741e1cd1be6SGreg Clayton { 742e1cd1be6SGreg Clayton if (m_threads[idx]->GetID() == tid) 743e1cd1be6SGreg Clayton { 744e1cd1be6SGreg Clayton thread_is_alive = true; 745e1cd1be6SGreg Clayton break; 746e1cd1be6SGreg Clayton } 747e1cd1be6SGreg Clayton } 748e1cd1be6SGreg Clayton if (!thread_is_alive) 749e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 750e1cd1be6SGreg Clayton } 75156d9a1b3SGreg Clayton } 75256d9a1b3SGreg Clayton } 75356d9a1b3SGreg Clayton 754fa559e5cSGreg Clayton void 755fa559e5cSGreg Clayton ThreadList::Flush () 756fa559e5cSGreg Clayton { 757ba4e61d3SAndrew Kaylor Mutex::Locker locker(GetMutex()); 758fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 759fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 760fa559e5cSGreg Clayton (*pos)->Flush (); 761fa559e5cSGreg Clayton } 76256d9a1b3SGreg Clayton 763ba4e61d3SAndrew Kaylor Mutex & 764ba4e61d3SAndrew Kaylor ThreadList::GetMutex () 765ba4e61d3SAndrew Kaylor { 766ba4e61d3SAndrew Kaylor return m_process->m_thread_mutex; 767ba4e61d3SAndrew Kaylor } 768ba4e61d3SAndrew Kaylor 769