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 { 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner 6630fdc8d8SChris Lattner uint32_t 6730fdc8d8SChris Lattner ThreadList::GetStopID () const 6830fdc8d8SChris Lattner { 6930fdc8d8SChris Lattner return m_stop_id; 7030fdc8d8SChris Lattner } 7130fdc8d8SChris Lattner 7230fdc8d8SChris Lattner void 7330fdc8d8SChris Lattner ThreadList::SetStopID (uint32_t stop_id) 7430fdc8d8SChris Lattner { 7530fdc8d8SChris Lattner m_stop_id = stop_id; 7630fdc8d8SChris Lattner } 7730fdc8d8SChris Lattner 7830fdc8d8SChris Lattner 7930fdc8d8SChris Lattner void 80c3776bf2SGreg Clayton ThreadList::AddThread (const ThreadSP &thread_sp) 8130fdc8d8SChris Lattner { 8230fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 8330fdc8d8SChris Lattner m_threads.push_back(thread_sp); 8430fdc8d8SChris Lattner } 8530fdc8d8SChris Lattner 8630fdc8d8SChris Lattner uint32_t 8730fdc8d8SChris Lattner ThreadList::GetSize (bool can_update) 8830fdc8d8SChris Lattner { 8930fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 9030fdc8d8SChris Lattner if (can_update) 9130fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 9230fdc8d8SChris Lattner return m_threads.size(); 9330fdc8d8SChris Lattner } 9430fdc8d8SChris Lattner 9530fdc8d8SChris Lattner ThreadSP 9630fdc8d8SChris Lattner ThreadList::GetThreadAtIndex (uint32_t idx, bool can_update) 9730fdc8d8SChris Lattner { 9830fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 9930fdc8d8SChris Lattner if (can_update) 10030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 10130fdc8d8SChris Lattner 10230fdc8d8SChris Lattner ThreadSP thread_sp; 10330fdc8d8SChris Lattner if (idx < m_threads.size()) 10430fdc8d8SChris Lattner thread_sp = m_threads[idx]; 10530fdc8d8SChris Lattner return thread_sp; 10630fdc8d8SChris Lattner } 10730fdc8d8SChris Lattner 10830fdc8d8SChris Lattner ThreadSP 10930fdc8d8SChris Lattner ThreadList::FindThreadByID (lldb::tid_t tid, bool can_update) 11030fdc8d8SChris Lattner { 11130fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 11230fdc8d8SChris Lattner 11330fdc8d8SChris Lattner if (can_update) 11430fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 11530fdc8d8SChris Lattner 11630fdc8d8SChris Lattner ThreadSP thread_sp; 11730fdc8d8SChris Lattner uint32_t idx = 0; 11830fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 11930fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 12030fdc8d8SChris Lattner { 12130fdc8d8SChris Lattner if (m_threads[idx]->GetID() == tid) 12230fdc8d8SChris Lattner { 12330fdc8d8SChris Lattner thread_sp = m_threads[idx]; 12430fdc8d8SChris Lattner break; 12530fdc8d8SChris Lattner } 12630fdc8d8SChris Lattner } 12730fdc8d8SChris Lattner return thread_sp; 12830fdc8d8SChris Lattner } 12930fdc8d8SChris Lattner 13030fdc8d8SChris Lattner ThreadSP 13130fdc8d8SChris Lattner ThreadList::GetThreadSPForThreadPtr (Thread *thread_ptr) 13230fdc8d8SChris Lattner { 13330fdc8d8SChris Lattner ThreadSP thread_sp; 13430fdc8d8SChris Lattner if (thread_ptr) 13530fdc8d8SChris Lattner { 13630fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 13730fdc8d8SChris Lattner 13830fdc8d8SChris Lattner uint32_t idx = 0; 13930fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 14030fdc8d8SChris Lattner for (idx = 0; idx < num_threads; ++idx) 14130fdc8d8SChris Lattner { 14230fdc8d8SChris Lattner if (m_threads[idx].get() == thread_ptr) 14330fdc8d8SChris Lattner { 14430fdc8d8SChris Lattner thread_sp = m_threads[idx]; 14530fdc8d8SChris Lattner break; 14630fdc8d8SChris Lattner } 14730fdc8d8SChris Lattner } 14830fdc8d8SChris Lattner } 14930fdc8d8SChris Lattner return thread_sp; 15030fdc8d8SChris Lattner } 15130fdc8d8SChris Lattner 15230fdc8d8SChris Lattner 15330fdc8d8SChris Lattner 15430fdc8d8SChris Lattner ThreadSP 15530fdc8d8SChris Lattner ThreadList::FindThreadByIndexID (uint32_t index_id, bool can_update) 15630fdc8d8SChris Lattner { 15730fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 15830fdc8d8SChris Lattner 15930fdc8d8SChris Lattner if (can_update) 16030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 16130fdc8d8SChris Lattner 16230fdc8d8SChris Lattner ThreadSP thread_sp; 16330fdc8d8SChris Lattner const uint32_t num_threads = m_threads.size(); 16430fdc8d8SChris Lattner for (uint32_t idx = 0; idx < num_threads; ++idx) 16530fdc8d8SChris Lattner { 16630fdc8d8SChris Lattner if (m_threads[idx]->GetIndexID() == index_id) 16730fdc8d8SChris Lattner { 16830fdc8d8SChris Lattner thread_sp = m_threads[idx]; 16930fdc8d8SChris Lattner break; 17030fdc8d8SChris Lattner } 17130fdc8d8SChris Lattner } 17230fdc8d8SChris Lattner return thread_sp; 17330fdc8d8SChris Lattner } 17430fdc8d8SChris Lattner 17530fdc8d8SChris Lattner bool 17630fdc8d8SChris Lattner ThreadList::ShouldStop (Event *event_ptr) 17730fdc8d8SChris Lattner { 178b42f3af3SJim Ingham bool should_stop = false; 17930fdc8d8SChris Lattner // Running events should never stop, obviously... 18030fdc8d8SChris Lattner 1812d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 18230fdc8d8SChris Lattner 183b42f3af3SJim Ingham // The ShouldStop method of the threads can do a whole lot of work, 184b42f3af3SJim Ingham // running breakpoint commands & conditions, etc. So we don't want 185b42f3af3SJim Ingham // to keep the ThreadList locked the whole time we are doing this. 186b42f3af3SJim Ingham // FIXME: It is possible that running code could cause new threads 187b42f3af3SJim Ingham // to be created. If that happens we will miss asking them whether 188b42f3af3SJim Ingham // then should stop. This is not a big deal, since we haven't had 189b42f3af3SJim Ingham // a chance to hang any interesting operations on those threads yet. 19030fdc8d8SChris Lattner 191b42f3af3SJim Ingham collection threads_copy; 192b42f3af3SJim Ingham { 193b42f3af3SJim Ingham // Scope for locker 194b42f3af3SJim Ingham Mutex::Locker locker(m_threads_mutex); 195b42f3af3SJim Ingham 196b42f3af3SJim Ingham m_process->UpdateThreadListIfNeeded(); 197b42f3af3SJim Ingham threads_copy = m_threads; 198b42f3af3SJim Ingham } 199b42f3af3SJim Ingham 200b42f3af3SJim Ingham collection::iterator pos, end = threads_copy.end(); 20130fdc8d8SChris Lattner 2022cad65a5SGreg Clayton if (log) 20310c4b249SJim Ingham { 20410c4b249SJim Ingham log->PutCString(""); 205*d01b2953SDaniel Malea log->Printf ("ThreadList::%s: %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 20610c4b249SJim Ingham } 2072cad65a5SGreg Clayton 208b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 20930fdc8d8SChris Lattner { 21030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 2112cad65a5SGreg Clayton 21210c4b249SJim Ingham const bool thread_should_stop = thread_sp->ShouldStop(event_ptr); 2132cad65a5SGreg Clayton if (thread_should_stop) 2142cad65a5SGreg Clayton should_stop |= true; 2152cad65a5SGreg Clayton } 2162cad65a5SGreg Clayton 2172cad65a5SGreg Clayton if (log) 21810c4b249SJim Ingham log->Printf ("ThreadList::%s overall should_stop = %i", __FUNCTION__, should_stop); 2192cad65a5SGreg Clayton 22030fdc8d8SChris Lattner if (should_stop) 22130fdc8d8SChris Lattner { 222b42f3af3SJim Ingham for (pos = threads_copy.begin(); pos != end; ++pos) 22330fdc8d8SChris Lattner { 22430fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 22530fdc8d8SChris Lattner thread_sp->WillStop (); 22630fdc8d8SChris Lattner } 22730fdc8d8SChris Lattner } 22830fdc8d8SChris Lattner 22930fdc8d8SChris Lattner return should_stop; 23030fdc8d8SChris Lattner } 23130fdc8d8SChris Lattner 23230fdc8d8SChris Lattner Vote 23330fdc8d8SChris Lattner ThreadList::ShouldReportStop (Event *event_ptr) 23430fdc8d8SChris Lattner { 2352cad65a5SGreg Clayton Mutex::Locker locker(m_threads_mutex); 2362cad65a5SGreg Clayton 23730fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 23830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 23930fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 24030fdc8d8SChris Lattner 2412d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 2422cad65a5SGreg Clayton 2432cad65a5SGreg Clayton if (log) 244*d01b2953SDaniel Malea log->Printf ("ThreadList::%s %" PRIu64 " threads", __FUNCTION__, (uint64_t)m_threads.size()); 2452cad65a5SGreg Clayton 24630fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 24730fdc8d8SChris Lattner // For stopping, a YES vote wins over everything. A NO vote wins over NO opinion. 24830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 24930fdc8d8SChris Lattner { 25030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 251e0d378b3SGreg Clayton const Vote vote = thread_sp->ShouldReportStop (event_ptr); 2522cad65a5SGreg Clayton switch (vote) 25330fdc8d8SChris Lattner { 25430fdc8d8SChris Lattner case eVoteNoOpinion: 25530fdc8d8SChris Lattner continue; 2562cad65a5SGreg Clayton 25730fdc8d8SChris Lattner case eVoteYes: 25830fdc8d8SChris Lattner result = eVoteYes; 25930fdc8d8SChris Lattner break; 2602cad65a5SGreg Clayton 26130fdc8d8SChris Lattner case eVoteNo: 26230fdc8d8SChris Lattner if (result == eVoteNoOpinion) 2632cad65a5SGreg Clayton { 26430fdc8d8SChris Lattner result = eVoteNo; 2652cad65a5SGreg Clayton } 2662cad65a5SGreg Clayton else 2672cad65a5SGreg Clayton { 2682cad65a5SGreg Clayton if (log) 269*d01b2953SDaniel Malea log->Printf ("ThreadList::%s thread 0x%4.4" PRIx64 ": voted %s, but lost out because result was %s", 2702cad65a5SGreg Clayton __FUNCTION__, 2712cad65a5SGreg Clayton thread_sp->GetID (), 2722cad65a5SGreg Clayton GetVoteAsCString (vote), 2732cad65a5SGreg Clayton GetVoteAsCString (result)); 2742cad65a5SGreg Clayton } 27530fdc8d8SChris Lattner break; 27630fdc8d8SChris Lattner } 27730fdc8d8SChris Lattner } 2782cad65a5SGreg Clayton if (log) 27910c4b249SJim Ingham log->Printf ("ThreadList::%s returning %s", __FUNCTION__, GetVoteAsCString (result)); 28030fdc8d8SChris Lattner return result; 28130fdc8d8SChris Lattner } 28230fdc8d8SChris Lattner 28330fdc8d8SChris Lattner Vote 28430fdc8d8SChris Lattner ThreadList::ShouldReportRun (Event *event_ptr) 28530fdc8d8SChris Lattner { 2862cad65a5SGreg Clayton 2872cad65a5SGreg Clayton Mutex::Locker locker(m_threads_mutex); 2882cad65a5SGreg Clayton 28930fdc8d8SChris Lattner Vote result = eVoteNoOpinion; 29030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 29130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 29230fdc8d8SChris Lattner 29330fdc8d8SChris Lattner // Run through the threads and ask whether we should report this event. 29430fdc8d8SChris Lattner // The rule is NO vote wins over everything, a YES vote wins over no opinion. 29530fdc8d8SChris Lattner 296ce579839SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 297ce579839SJim Ingham 29830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 29930fdc8d8SChris Lattner { 300ce579839SJim Ingham if ((*pos)->GetResumeState () != eStateSuspended) 301ce579839SJim Ingham { 302ce579839SJim Ingham switch ((*pos)->ShouldReportRun (event_ptr)) 30330fdc8d8SChris Lattner { 30430fdc8d8SChris Lattner case eVoteNoOpinion: 30530fdc8d8SChris Lattner continue; 30630fdc8d8SChris Lattner case eVoteYes: 30730fdc8d8SChris Lattner if (result == eVoteNoOpinion) 30830fdc8d8SChris Lattner result = eVoteYes; 30930fdc8d8SChris Lattner break; 31030fdc8d8SChris Lattner case eVoteNo: 311abcbc8acSGreg Clayton if (log) 312*d01b2953SDaniel Malea log->Printf ("ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64 ") says don't report.", 313ce579839SJim Ingham (*pos)->GetIndexID(), 314ce579839SJim Ingham (*pos)->GetID()); 31530fdc8d8SChris Lattner result = eVoteNo; 31630fdc8d8SChris Lattner break; 31730fdc8d8SChris Lattner } 31830fdc8d8SChris Lattner } 319ce579839SJim Ingham } 32030fdc8d8SChris Lattner return result; 32130fdc8d8SChris Lattner } 32230fdc8d8SChris Lattner 32330fdc8d8SChris Lattner void 32430fdc8d8SChris Lattner ThreadList::Clear() 32530fdc8d8SChris Lattner { 326c4e411ffSGreg Clayton Mutex::Locker locker(m_threads_mutex); 32730fdc8d8SChris Lattner m_stop_id = 0; 32830fdc8d8SChris Lattner m_threads.clear(); 3292976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 33030fdc8d8SChris Lattner } 33130fdc8d8SChris Lattner 33230fdc8d8SChris Lattner void 333e1cd1be6SGreg Clayton ThreadList::Destroy() 334e1cd1be6SGreg Clayton { 335e1cd1be6SGreg Clayton Mutex::Locker locker(m_threads_mutex); 336e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 337e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 338e1cd1be6SGreg Clayton { 339e1cd1be6SGreg Clayton m_threads[idx]->DestroyThread(); 340e1cd1be6SGreg Clayton } 341e1cd1be6SGreg Clayton } 342e1cd1be6SGreg Clayton 343e1cd1be6SGreg Clayton void 34430fdc8d8SChris Lattner ThreadList::RefreshStateAfterStop () 34530fdc8d8SChris Lattner { 34630fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 34730fdc8d8SChris Lattner 34830fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 34930fdc8d8SChris Lattner 3501c823b43SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 35110c4b249SJim Ingham if (log && log->GetVerbose()) 3521c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 3531c823b43SJim Ingham 35430fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 35530fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 35630fdc8d8SChris Lattner (*pos)->RefreshStateAfterStop (); 35730fdc8d8SChris Lattner } 35830fdc8d8SChris Lattner 35930fdc8d8SChris Lattner void 36030fdc8d8SChris Lattner ThreadList::DiscardThreadPlans () 36130fdc8d8SChris Lattner { 36230fdc8d8SChris Lattner // You don't need to update the thread list here, because only threads 36330fdc8d8SChris Lattner // that you currently know about have any thread plans. 36430fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 36530fdc8d8SChris Lattner 36630fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 36730fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 36830fdc8d8SChris Lattner (*pos)->DiscardThreadPlans (true); 36930fdc8d8SChris Lattner 37030fdc8d8SChris Lattner } 37130fdc8d8SChris Lattner 37230fdc8d8SChris Lattner bool 37330fdc8d8SChris Lattner ThreadList::WillResume () 37430fdc8d8SChris Lattner { 37530fdc8d8SChris Lattner // Run through the threads and perform their momentary actions. 37630fdc8d8SChris Lattner // But we only do this for threads that are running, user suspended 37730fdc8d8SChris Lattner // threads stay where they are. 37830fdc8d8SChris Lattner 37930fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 38030fdc8d8SChris Lattner m_process->UpdateThreadListIfNeeded(); 38130fdc8d8SChris Lattner 38230fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 38330fdc8d8SChris Lattner 384a3241c1bSJim Ingham // See if any thread wants to run stopping others. If it does, then we won't 385a3241c1bSJim Ingham // setup the other threads for resume, since they aren't going to get a chance 386a3241c1bSJim Ingham // to run. This is necessary because the SetupForResume might add "StopOthers" 387a3241c1bSJim Ingham // plans which would then get to be part of the who-gets-to-run negotiation, but 388a3241c1bSJim Ingham // they're coming in after the fact, and the threads that are already set up should 389a3241c1bSJim Ingham // take priority. 390a3241c1bSJim Ingham 391a3241c1bSJim Ingham bool wants_solo_run = false; 39230fdc8d8SChris Lattner 39330fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 394a3241c1bSJim Ingham { 395a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended && 396a3241c1bSJim Ingham (*pos)->GetCurrentPlan()->StopOthers()) 397a3241c1bSJim Ingham { 398a3241c1bSJim Ingham wants_solo_run = true; 399a3241c1bSJim Ingham break; 400a3241c1bSJim Ingham } 401a3241c1bSJim Ingham } 402a3241c1bSJim Ingham 4031c823b43SJim Ingham if (wants_solo_run) 4041c823b43SJim Ingham { 4051c823b43SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 40610c4b249SJim Ingham if (log && log->GetVerbose()) 4071c823b43SJim Ingham log->Printf ("Turning on notification of new threads while single stepping a thread."); 4081c823b43SJim Ingham m_process->StartNoticingNewThreads(); 4091c823b43SJim Ingham } 4101c823b43SJim Ingham else 4111c823b43SJim Ingham { 4121c823b43SJim Ingham LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 41310c4b249SJim Ingham if (log && log->GetVerbose()) 4141c823b43SJim Ingham log->Printf ("Turning off notification of new threads while single stepping a thread."); 4151c823b43SJim Ingham m_process->StopNoticingNewThreads(); 4161c823b43SJim Ingham } 417a3241c1bSJim Ingham 418a3241c1bSJim Ingham // Give all the threads that are likely to run a last chance to set up their state before we 419a3241c1bSJim Ingham // negotiate who is actually going to get a chance to run... 420a3241c1bSJim Ingham // Don't set to resume suspended threads, and if any thread wanted to stop others, only 421a3241c1bSJim Ingham // call setup on the threads that request StopOthers... 422a3241c1bSJim Ingham 423a3241c1bSJim Ingham for (pos = m_threads.begin(); pos != end; ++pos) 424a3241c1bSJim Ingham { 425a3241c1bSJim Ingham if ((*pos)->GetResumeState() != eStateSuspended 426a3241c1bSJim Ingham && (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) 427a3241c1bSJim Ingham { 42830fdc8d8SChris Lattner (*pos)->SetupForResume (); 429a3241c1bSJim Ingham } 430a3241c1bSJim Ingham } 43130fdc8d8SChris Lattner 43230fdc8d8SChris Lattner // Now go through the threads and see if any thread wants to run just itself. 43330fdc8d8SChris Lattner // if so then pick one and run it. 434a3241c1bSJim Ingham 43530fdc8d8SChris Lattner ThreadList run_me_only_list (m_process); 43630fdc8d8SChris Lattner 43730fdc8d8SChris Lattner run_me_only_list.SetStopID(m_process->GetStopID()); 43830fdc8d8SChris Lattner 43930fdc8d8SChris Lattner ThreadSP immediate_thread_sp; 44030fdc8d8SChris Lattner bool run_only_current_thread = false; 44130fdc8d8SChris Lattner 44230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 44330fdc8d8SChris Lattner { 44430fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 445b15bfc75SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended && 44630fdc8d8SChris Lattner thread_sp->GetCurrentPlan()->StopOthers()) 44730fdc8d8SChris Lattner { 44830fdc8d8SChris Lattner // You can't say "stop others" and also want yourself to be suspended. 44930fdc8d8SChris Lattner assert (thread_sp->GetCurrentPlan()->RunState() != eStateSuspended); 45030fdc8d8SChris Lattner 4512976d00aSJim Ingham if (thread_sp == GetSelectedThread()) 45230fdc8d8SChris Lattner { 45330fdc8d8SChris Lattner run_only_current_thread = true; 45430fdc8d8SChris Lattner run_me_only_list.Clear(); 45530fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 45630fdc8d8SChris Lattner break; 45730fdc8d8SChris Lattner } 45830fdc8d8SChris Lattner 45930fdc8d8SChris Lattner run_me_only_list.AddThread (thread_sp); 46030fdc8d8SChris Lattner } 46130fdc8d8SChris Lattner 46230fdc8d8SChris Lattner } 46330fdc8d8SChris Lattner 464513c6bb8SJim Ingham bool need_to_resume = true; 465513c6bb8SJim Ingham 46630fdc8d8SChris Lattner if (immediate_thread_sp) 46730fdc8d8SChris Lattner { 46830fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 46930fdc8d8SChris Lattner { 47030fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 47130fdc8d8SChris Lattner if (thread_sp.get() == immediate_thread_sp.get()) 47230fdc8d8SChris Lattner thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState()); 47330fdc8d8SChris Lattner else 47430fdc8d8SChris Lattner thread_sp->WillResume (eStateSuspended); 47530fdc8d8SChris Lattner } 47630fdc8d8SChris Lattner } 47730fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 0) 47830fdc8d8SChris Lattner { 47930fdc8d8SChris Lattner // Everybody runs as they wish: 48030fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 48130fdc8d8SChris Lattner { 48230fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 483cb5d5a57SJim Ingham StateType run_state; 484cb5d5a57SJim Ingham if (thread_sp->GetResumeState() != eStateSuspended) 485cb5d5a57SJim Ingham run_state = thread_sp->GetCurrentPlan()->RunState(); 486cb5d5a57SJim Ingham else 487cb5d5a57SJim Ingham run_state = eStateSuspended; 488513c6bb8SJim Ingham if (!thread_sp->WillResume(run_state)) 489513c6bb8SJim Ingham need_to_resume = false; 49030fdc8d8SChris Lattner } 49130fdc8d8SChris Lattner } 49230fdc8d8SChris Lattner else 49330fdc8d8SChris Lattner { 49430fdc8d8SChris Lattner ThreadSP thread_to_run; 49530fdc8d8SChris Lattner 49630fdc8d8SChris Lattner if (run_only_current_thread) 49730fdc8d8SChris Lattner { 4982976d00aSJim Ingham thread_to_run = GetSelectedThread(); 49930fdc8d8SChris Lattner } 50030fdc8d8SChris Lattner else if (run_me_only_list.GetSize (false) == 1) 50130fdc8d8SChris Lattner { 50230fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (0); 50330fdc8d8SChris Lattner } 50430fdc8d8SChris Lattner else 50530fdc8d8SChris Lattner { 50630fdc8d8SChris Lattner int random_thread = (int) 50730fdc8d8SChris Lattner ((run_me_only_list.GetSize (false) * (double) rand ()) / (RAND_MAX + 1.0)); 50830fdc8d8SChris Lattner thread_to_run = run_me_only_list.GetThreadAtIndex (random_thread); 50930fdc8d8SChris Lattner } 51030fdc8d8SChris Lattner 51130fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 51230fdc8d8SChris Lattner { 51330fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 51430fdc8d8SChris Lattner if (thread_sp == thread_to_run) 515513c6bb8SJim Ingham { 516513c6bb8SJim Ingham if (!thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState())) 517513c6bb8SJim Ingham need_to_resume = false; 518513c6bb8SJim Ingham } 51930fdc8d8SChris Lattner else 52030fdc8d8SChris Lattner thread_sp->WillResume (eStateSuspended); 52130fdc8d8SChris Lattner } 52230fdc8d8SChris Lattner } 52330fdc8d8SChris Lattner 524513c6bb8SJim Ingham return need_to_resume; 52530fdc8d8SChris Lattner } 52630fdc8d8SChris Lattner 52730fdc8d8SChris Lattner void 52830fdc8d8SChris Lattner ThreadList::DidResume () 52930fdc8d8SChris Lattner { 530c4e411ffSGreg Clayton Mutex::Locker locker(m_threads_mutex); 53130fdc8d8SChris Lattner collection::iterator pos, end = m_threads.end(); 53230fdc8d8SChris Lattner for (pos = m_threads.begin(); pos != end; ++pos) 53330fdc8d8SChris Lattner { 53430fdc8d8SChris Lattner // Don't clear out threads that aren't going to get a chance to run, rather 53530fdc8d8SChris Lattner // leave their state for the next time around. 53630fdc8d8SChris Lattner ThreadSP thread_sp(*pos); 53730fdc8d8SChris Lattner if (thread_sp->GetResumeState() != eStateSuspended) 53830fdc8d8SChris Lattner thread_sp->DidResume (); 53930fdc8d8SChris Lattner } 54030fdc8d8SChris Lattner } 54130fdc8d8SChris Lattner 54230fdc8d8SChris Lattner ThreadSP 5432976d00aSJim Ingham ThreadList::GetSelectedThread () 54430fdc8d8SChris Lattner { 54530fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 546943ddb73SJohnny Chen ThreadSP thread_sp = FindThreadByID(m_selected_tid); 547943ddb73SJohnny Chen if (!thread_sp.get()) 548943ddb73SJohnny Chen { 549354b9a65SJason Molenda if (m_threads.size() == 0) 550354b9a65SJason Molenda return thread_sp; 551943ddb73SJohnny Chen m_selected_tid = m_threads[0]->GetID(); 552943ddb73SJohnny Chen thread_sp = m_threads[0]; 553943ddb73SJohnny Chen } 554943ddb73SJohnny Chen return thread_sp; 55530fdc8d8SChris Lattner } 55630fdc8d8SChris Lattner 55730fdc8d8SChris Lattner bool 5582976d00aSJim Ingham ThreadList::SetSelectedThreadByID (lldb::tid_t tid) 55930fdc8d8SChris Lattner { 56030fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 561b7f6b2faSJim Ingham ThreadSP selected_thread_sp(FindThreadByID(tid)); 562b7f6b2faSJim Ingham if (selected_thread_sp) 563b7f6b2faSJim Ingham { 5642976d00aSJim Ingham m_selected_tid = tid; 565b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 566b7f6b2faSJim Ingham } 56730fdc8d8SChris Lattner else 5682976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 56930fdc8d8SChris Lattner 5702976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 57130fdc8d8SChris Lattner } 57230fdc8d8SChris Lattner 57330fdc8d8SChris Lattner bool 5742976d00aSJim Ingham ThreadList::SetSelectedThreadByIndexID (uint32_t index_id) 57530fdc8d8SChris Lattner { 57630fdc8d8SChris Lattner Mutex::Locker locker(m_threads_mutex); 577b7f6b2faSJim Ingham ThreadSP selected_thread_sp (FindThreadByIndexID(index_id)); 578b7f6b2faSJim Ingham if (selected_thread_sp.get()) 579b7f6b2faSJim Ingham { 580b7f6b2faSJim Ingham m_selected_tid = selected_thread_sp->GetID(); 581b7f6b2faSJim Ingham selected_thread_sp->SetDefaultFileAndLineToSelectedFrame(); 582b7f6b2faSJim Ingham } 58330fdc8d8SChris Lattner else 5842976d00aSJim Ingham m_selected_tid = LLDB_INVALID_THREAD_ID; 58530fdc8d8SChris Lattner 5862976d00aSJim Ingham return m_selected_tid != LLDB_INVALID_THREAD_ID; 58730fdc8d8SChris Lattner } 58830fdc8d8SChris Lattner 58956d9a1b3SGreg Clayton void 59056d9a1b3SGreg Clayton ThreadList::Update (ThreadList &rhs) 59156d9a1b3SGreg Clayton { 59256d9a1b3SGreg Clayton if (this != &rhs) 59356d9a1b3SGreg Clayton { 59456d9a1b3SGreg Clayton // Lock both mutexes to make sure neither side changes anyone on us 59556d9a1b3SGreg Clayton // while the assignement occurs 59656d9a1b3SGreg Clayton Mutex::Locker locker_lhs(m_threads_mutex); 59756d9a1b3SGreg Clayton Mutex::Locker locker_rhs(rhs.m_threads_mutex); 59856d9a1b3SGreg Clayton m_process = rhs.m_process; 59956d9a1b3SGreg Clayton m_stop_id = rhs.m_stop_id; 60056d9a1b3SGreg Clayton m_threads.swap(rhs.m_threads); 60156d9a1b3SGreg Clayton m_selected_tid = rhs.m_selected_tid; 602e1cd1be6SGreg Clayton 603e1cd1be6SGreg Clayton 604e1cd1be6SGreg Clayton // Now we look for threads that we are done with and 605e1cd1be6SGreg Clayton // make sure to clear them up as much as possible so 606e1cd1be6SGreg Clayton // anyone with a shared pointer will still have a reference, 607e1cd1be6SGreg Clayton // but the thread won't be of much use. Using std::weak_ptr 608e1cd1be6SGreg Clayton // for all backward references (such as a thread to a process) 609e1cd1be6SGreg Clayton // will eventually solve this issue for us, but for now, we 610e1cd1be6SGreg Clayton // need to work around the issue 611e1cd1be6SGreg Clayton collection::iterator rhs_pos, rhs_end = rhs.m_threads.end(); 612e1cd1be6SGreg Clayton for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) 613e1cd1be6SGreg Clayton { 614e1cd1be6SGreg Clayton const lldb::tid_t tid = (*rhs_pos)->GetID(); 615e1cd1be6SGreg Clayton bool thread_is_alive = false; 616e1cd1be6SGreg Clayton const uint32_t num_threads = m_threads.size(); 617e1cd1be6SGreg Clayton for (uint32_t idx = 0; idx < num_threads; ++idx) 618e1cd1be6SGreg Clayton { 619e1cd1be6SGreg Clayton if (m_threads[idx]->GetID() == tid) 620e1cd1be6SGreg Clayton { 621e1cd1be6SGreg Clayton thread_is_alive = true; 622e1cd1be6SGreg Clayton break; 623e1cd1be6SGreg Clayton } 624e1cd1be6SGreg Clayton } 625e1cd1be6SGreg Clayton if (!thread_is_alive) 626e1cd1be6SGreg Clayton (*rhs_pos)->DestroyThread(); 627e1cd1be6SGreg Clayton } 62856d9a1b3SGreg Clayton } 62956d9a1b3SGreg Clayton } 63056d9a1b3SGreg Clayton 631fa559e5cSGreg Clayton void 632fa559e5cSGreg Clayton ThreadList::Flush () 633fa559e5cSGreg Clayton { 634fa559e5cSGreg Clayton Mutex::Locker locker(m_threads_mutex); 635fa559e5cSGreg Clayton collection::iterator pos, end = m_threads.end(); 636fa559e5cSGreg Clayton for (pos = m_threads.begin(); pos != end; ++pos) 637fa559e5cSGreg Clayton (*pos)->Flush (); 638fa559e5cSGreg Clayton } 63956d9a1b3SGreg Clayton 640