diff options
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX/MachThread.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/MacOSX/MachThread.cpp | 157 |
1 files changed, 106 insertions, 51 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index e61d2800287..6cdcd302db2 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -30,14 +30,15 @@ MachThread::MachThread (MachProcess *process, thread_t thread) : m_state (eStateUnloaded), m_state_mutex (PTHREAD_MUTEX_RECURSIVE), m_breakID (INVALID_NUB_BREAK_ID), - m_suspendCount (0), + m_suspend_count (0), m_arch_ap (DNBArchProtocol::Create (this)), - m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets)) + m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets)), + m_basic_info_valid (false) { // Get the thread state so we know if a thread is in a state where we can't // muck with it and also so we get the suspend count correct in case it was // already suspended - GetBasicInfo(); + GetBasicInfo(true); DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%4.4x, seq_id = %u )", &m_process, m_tid, m_seq_id); } @@ -48,7 +49,7 @@ MachThread::~MachThread() -uint32_t +int32_t MachThread::Suspend() { DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); @@ -56,14 +57,47 @@ MachThread::Suspend() { DNBError err(::thread_suspend (m_tid), DNBError::MachKernel); if (err.Success()) - m_suspendCount++; + m_suspend_count++; if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) err.LogThreaded("::thread_suspend (%4.4x)", m_tid); } - return SuspendCount(); + return m_suspend_count; } -uint32_t +int32_t +MachThread::ForceResume () +{ + // We need to resume this all the way to 0. + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); + // Okay, now m_basic_info has the full suspend count. So I'll just + // keep decrementing the suspend count till that is zero, and at the same time + // decrement m_suspend_count. If that goes below zero, then the next time we + // call RestoreSuspendCount, we'll have to suspend it back to 0. + uint32_t num_suspends = m_basic_info.suspend_count + m_suspend_count; + DNBError err; + while (num_suspends > 0) + { + if (m_suspend_count < 0) + DNBLogThreadedIf(LOG_THREAD, "MachThread::%s ( ) (tid = %4.4x) setting suspend count negative = %d", __FUNCTION__, + m_tid, m_suspend_count); + err = ::thread_resume (m_tid); + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("ForceResume ::thread_resume (%4.4x)", m_tid); + if (err.Success()) + { + --m_suspend_count; + --num_suspends; + } + else + { + break; + } + } + return m_suspend_count; + +} + +int32_t MachThread::Resume() { DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); @@ -71,49 +105,59 @@ MachThread::Resume() { RestoreSuspendCount(); } - return SuspendCount(); + return m_suspend_count; } bool MachThread::RestoreSuspendCount() { - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( ) (tid = %4.4x) our suspend count = %d", __FUNCTION__, + m_tid, m_suspend_count); DNBError err; if (ThreadIDIsValid(m_tid) == false) return false; - if (m_suspendCount > 0) + if (m_suspend_count > 0) { - while (m_suspendCount > 0) + while (m_suspend_count > 0) { err = ::thread_resume (m_tid); if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_resume (%4.4x)", m_tid); + err.LogThreaded("RestoreSuspendCount ::thread_resume (%4.4x)", m_tid); if (err.Success()) - --m_suspendCount; + --m_suspend_count; else { - if (GetBasicInfo()) - m_suspendCount = m_basicInfo.suspend_count; + if (GetBasicInfo(true)) + m_suspend_count = m_basic_info.suspend_count; else - m_suspendCount = 0; + m_suspend_count = 0; return false; // ??? } } } - // 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_suspend_count < 0) + { + DNBLogThreadedIf(LOG_THREAD, "MachThread::%s ( ) (tid = %4.4x) negative suspend count = %d", __FUNCTION__, + m_tid, m_suspend_count); + while (m_suspend_count < 0) + { + err = ::thread_suspend (m_tid); + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("RestoreSuspendCount ::thread_suspend (%4.4x)", m_tid); + + if (err.Success()) + ++m_suspend_count; + else + { + if (GetBasicInfo(true)) + m_suspend_count = m_basic_info.suspend_count; + else + m_suspend_count = 0; + return false; // ??? + } + + } + } return true; } @@ -193,10 +237,9 @@ MachThread::InferiorThreadID() const bool MachThread::IsUserReady() { - if (m_basicInfo.run_state == 0) - GetBasicInfo (); + GetBasicInfo (false); - switch (m_basicInfo.run_state) + switch (m_basic_info.run_state) { default: case TH_STATE_UNINTERRUPTIBLE: @@ -212,10 +255,16 @@ MachThread::IsUserReady() } struct thread_basic_info * -MachThread::GetBasicInfo () +MachThread::GetBasicInfo (bool force) { - if (MachThread::GetBasicInfo(m_tid, &m_basicInfo)) - return &m_basicInfo; + if (!force && m_basic_info_valid) + return &m_basic_info; + + if (MachThread::GetBasicInfo(m_tid, &m_basic_info)) + { + m_basic_info_valid = true; + return &m_basic_info; + } return NULL; } @@ -287,7 +336,7 @@ MachThread::Dump(uint32_t index) { const char * thread_run_state = NULL; - switch (m_basicInfo.run_state) + switch (m_basic_info.run_state) { case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped @@ -304,15 +353,15 @@ MachThread::Dump(uint32_t index) GetPC(INVALID_NUB_ADDRESS), GetSP(INVALID_NUB_ADDRESS), m_breakID, - m_basicInfo.user_time.seconds, m_basicInfo.user_time.microseconds, - m_basicInfo.system_time.seconds, m_basicInfo.system_time.microseconds, - m_basicInfo.cpu_usage, - m_basicInfo.policy, - m_basicInfo.run_state, + m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, + m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, + m_basic_info.cpu_usage, + m_basic_info.policy, + m_basic_info.run_state, thread_run_state, - m_basicInfo.flags, - m_basicInfo.suspend_count, m_suspendCount, - m_basicInfo.sleep_time); + m_basic_info.flags, + m_basic_info.suspend_count, m_suspend_count, + m_basic_info.sleep_time); //DumpRegisterState(0); } @@ -321,7 +370,11 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) { if (thread_action->addr != INVALID_NUB_ADDRESS) SetPC (thread_action->addr); - + // DidStop restores the state to it's natural state, and sets + // m_suspend_count to 0 in the process, and then here is the only + // place that we should be suspending or resuming (and thus changing + // that state. + assert (m_suspend_count == 0); SetState (thread_action->state); switch (thread_action->state) { @@ -331,9 +384,11 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) break; case eStateRunning: - case eStateStepping: Resume(); break; + case eStateStepping: + ForceResume(); + break; } m_arch_ap->ThreadWillResume(); m_stop_exception.Clear(); @@ -438,7 +493,7 @@ MachThread::ThreadDidStop() RestoreSuspendCount(); // Update the basic information for a thread - MachThread::GetBasicInfo(m_tid, &m_basicInfo); + GetBasicInfo (true); #if ENABLE_AUTO_STEPPING_OVER_BP // See if we were at a breakpoint when we last resumed that we disabled, @@ -448,7 +503,7 @@ MachThread::ThreadDidStop() if (NUB_BREAK_ID_IS_VALID(breakID)) { m_process->EnableBreakpoint(breakID); - if (m_basicInfo.suspend_count > 0) + if (m_basic_info.suspend_count > 0) { SetState(eStateSuspended); } @@ -471,7 +526,7 @@ MachThread::ThreadDidStop() } else { - if (m_basicInfo.suspend_count > 0) + if (m_basic_info.suspend_count > 0) { SetState(eStateSuspended); } @@ -481,7 +536,7 @@ MachThread::ThreadDidStop() } } #else - if (m_basicInfo.suspend_count > 0) + if (m_basic_info.suspend_count > 0) SetState(eStateSuspended); else SetState(eStateStopped); |