summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2011-07-21 01:54:41 +0000
committerJim Ingham <jingham@apple.com>2011-07-21 01:54:41 +0000
commit9411ddb65ff6ffb1358f14c604e077367d7f10f7 (patch)
treefba171a36bcf08f9cde92b983abb38b1dd98670e /lldb/tools/debugserver/source
parentbd243d0dfe3cd3fa8dc59030a578d5dec72292c7 (diff)
downloadbcm5719-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.cpp88
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.h13
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp29
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);
}
}
OpenPOWER on IntegriCloud