diff options
| author | Jim Ingham <jingham@apple.com> | 2011-07-21 01:54:41 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2011-07-21 01:54:41 +0000 |
| commit | 9411ddb65ff6ffb1358f14c604e077367d7f10f7 (patch) | |
| tree | fba171a36bcf08f9cde92b983abb38b1dd98670e /lldb/tools/debugserver/source | |
| parent | bd243d0dfe3cd3fa8dc59030a578d5dec72292c7 (diff) | |
| download | bcm5719-llvm-9411ddb65ff6ffb1358f14c604e077367d7f10f7.tar.gz bcm5719-llvm-9411ddb65ff6ffb1358f14c604e077367d7f10f7.zip | |
If we are telling only one thread to run in debugserver, and that thread has been suspended from outside
the debugger, resume it before running so we will actually make progress.
llvm-svn: 135655
Diffstat (limited to 'lldb/tools/debugserver/source')
| -rw-r--r-- | lldb/tools/debugserver/source/MacOSX/MachThread.cpp | 88 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/MacOSX/MachThread.h | 13 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp | 29 |
3 files changed, 99 insertions, 31 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index 0fe65b6927a..493f2bc7dc9 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -48,7 +48,7 @@ MachThread::~MachThread() -uint32_t +void MachThread::Suspend() { DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); @@ -60,27 +60,69 @@ MachThread::Suspend() if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) err.LogThreaded("::thread_suspend (%4.4x)", m_tid); } - return SuspendCount(); } -uint32_t -MachThread::Resume() +void +MachThread::Resume(bool others_stopped) { DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); if (ThreadIDIsValid(m_tid)) { - RestoreSuspendCount(); + SetSuspendCountBeforeResume(others_stopped); } - return SuspendCount(); } bool -MachThread::RestoreSuspendCount() +MachThread::SetSuspendCountBeforeResume(bool others_stopped) { DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); DNBError err; if (ThreadIDIsValid(m_tid) == false) return false; + + size_t times_to_resume; + + if (others_stopped) + { + times_to_resume = GetBasicInfo()->suspend_count; + m_suspendCount = - (times_to_resume - m_suspendCount); + } + else + { + times_to_resume = m_suspendCount; + m_suspendCount = 0; + } + + if (times_to_resume > 0) + { + while (times_to_resume > 0) + { + err = ::thread_resume (m_tid); + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::thread_resume (%4.4x)", m_tid); + if (err.Success()) + --times_to_resume; + else + { + if (GetBasicInfo()) + times_to_resume = m_basicInfo.suspend_count; + else + times_to_resume = 0; + return false; // ??? + } + } + } + return true; +} + +bool +MachThread::RestoreSuspendCountAfterStop () +{ + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); + DNBError err; + if (ThreadIDIsValid(m_tid) == false) + return false; + if (m_suspendCount > 0) { while (m_suspendCount > 0) @@ -100,20 +142,17 @@ MachThread::RestoreSuspendCount() } } } - // We don't currently really support resuming a thread that was externally - // suspended. If/when we do, we will need to make the code below work and - // m_suspendCount will need to become signed instead of unsigned. -// else if (m_suspendCount < 0) -// { -// while (m_suspendCount < 0) -// { -// err = ::thread_suspend (m_tid); -// if (err.Success()) -// ++m_suspendCount; -// if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) -// err.LogThreaded("::thread_suspend (%4.4x)", m_tid); -// } -// } + else if (m_suspendCount < 0) + { + while (m_suspendCount < 0) + { + err = ::thread_suspend (m_tid); + if (err.Success()) + ++m_suspendCount; + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::thread_suspend (%4.4x)", m_tid); + } + } return true; } @@ -317,7 +356,7 @@ MachThread::Dump(uint32_t index) } void -MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) +MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, bool others_stopped) { if (thread_action->addr != INVALID_NUB_ADDRESS) SetPC (thread_action->addr); @@ -327,12 +366,13 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) { case eStateStopped: case eStateSuspended: + assert (others_stopped == false); Suspend(); break; case eStateRunning: case eStateStepping: - Resume(); + Resume(others_stopped); break; default: break; @@ -437,7 +477,7 @@ MachThread::ThreadDidStop() // We may have suspended this thread so the primary thread could step // without worrying about race conditions, so lets restore our suspend // count. - RestoreSuspendCount(); + RestoreSuspendCountAfterStop(); // Update the basic information for a thread MachThread::GetBasicInfo(m_tid, &m_basicInfo); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index e7e18fe262c..9e247477115 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -49,10 +49,10 @@ public: uint32_t SequenceID() const { return m_seq_id; } static bool ThreadIDIsValid(thread_t thread); - uint32_t Resume(); - uint32_t Suspend(); - uint32_t SuspendCount() const { return m_suspendCount; } - bool RestoreSuspendCount(); + void Resume(bool others_stopped); + void Suspend(); + bool SetSuspendCountBeforeResume(bool others_stopped); + bool RestoreSuspendCountAfterStop(); bool GetRegisterState(int flavor, bool force); bool SetRegisterState(int flavor); @@ -69,7 +69,7 @@ public: nub_state_t GetState(); void SetState(nub_state_t state); - void ThreadWillResume (const DNBThreadResumeAction *thread_action); + void ThreadWillResume (const DNBThreadResumeAction *thread_action, bool others_stopped = false); bool ShouldStop(bool &step_more); bool IsStepping(); bool ThreadDidStop(); @@ -119,7 +119,8 @@ protected: PThreadMutex m_state_mutex; // Multithreaded protection for m_state nub_break_t m_breakID; // Breakpoint that this thread is (stopped)/was(running) at (NULL for none) struct thread_basic_info m_basicInfo; // Basic information for a thread used to see if a thread is valid - uint32_t m_suspendCount; // The current suspend count + int32_t m_suspendCount; // The current suspend count > 0 means we have suspended m_suspendCount times, + // < 0 means we have resumed it m_suspendCount times. MachException::Data m_stop_exception; // The best exception that describes why this thread is stopped std::auto_ptr<DNBArchProtocol> m_arch_ap; // Arch specific information for register state and more const DNBRegisterSetInfo *const m_reg_sets; // Register set information for this thread diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index c08d92034f2..acd38eb7707 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -321,10 +321,34 @@ MachThreadList::ProcessWillResume(MachProcess *process, const DNBThreadResumeAct // Update our thread list, because sometimes libdispatch or the kernel // will spawn threads while a task is suspended. MachThreadList::collection new_threads; + + // First figure out if we were planning on running only one thread, and if so force that thread to resume. + bool run_one_thread; + nub_thread_t solo_thread = INVALID_NUB_THREAD; + if (thread_actions.GetSize() > 0 + && thread_actions.NumActionsWithState(eStateStepping) + thread_actions.NumActionsWithState (eStateRunning) == 1) + { + run_one_thread = true; + const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); + size_t num_actions = thread_actions.GetSize(); + for (size_t i = 0; i < num_actions; i++, action_ptr++) + { + if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning) + { + solo_thread = action_ptr->tid; + break; + } + } + } + else + run_one_thread = false; UpdateThreadList(process, true, &new_threads); DNBThreadResumeAction resume_new_threads = { -1, eStateRunning, 0, INVALID_NUB_ADDRESS }; + // If we are planning to run only one thread, any new threads should be suspended. + if (run_one_thread) + resume_new_threads.state = eStateSuspended; const uint32_t num_new_threads = new_threads.size(); const uint32_t num_threads = m_threads.size(); @@ -347,7 +371,10 @@ MachThreadList::ProcessWillResume(MachProcess *process, const DNBThreadResumeAct const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true); // There must always be a thread action for every thread. assert (thread_action); - thread->ThreadWillResume (thread_action); + bool others_stopped = false; + if (solo_thread == thread->ThreadID()) + others_stopped = true; + thread->ThreadWillResume (thread_action, others_stopped); } } |

