debugserver per-thread suspension and resume preparation

llvm-project/lldb/tools/debugserver/source/MacOSX/MachThread.cpp · 794 lines · browse source

Per-thread suspend-count accounting and the callbacks that prepare register and architecture state before resume and normalize it after a stop.

MachThread::Suspend source
void MachThread::Suspend() {
  DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )",
                   __FUNCTION__);
  if (MachPortNumberIsValid(m_mach_port_number)) {
    DNBError err(::thread_suspend(m_mach_port_number), DNBError::MachKernel);
    if (err.Success())
      m_suspend_count++;
    if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
      err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number);
  }
}
MachThread::Resume source
void MachThread::Resume(bool others_stopped) {
  DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )",
                   __FUNCTION__);
  if (MachPortNumberIsValid(m_mach_port_number)) {
    SetSuspendCountBeforeResume(others_stopped);
  }
}
MachThread::ThreadWillResume source
void MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action,
                                  bool others_stopped) {
  if (thread_action->addr != INVALID_NUB_ADDRESS)
    SetPC(thread_action->addr);

  SetState(thread_action->state);
  switch (thread_action->state) {
  case eStateStopped:
  case eStateSuspended:
    assert(others_stopped == false);
    Suspend();
    break;

  case eStateRunning:
  case eStateStepping:
    Resume(others_stopped);
    break;
  default:
    break;
  }
  m_arch_up->ThreadWillResume();
  m_stop_exception.Clear();
}
MachThread::ThreadDidStop source
bool MachThread::ThreadDidStop() {
  // This thread has existed prior to resuming under debug nub control,
  // and has just been stopped. Do any cleanup that needs to be done
  // after running.

  // The thread state and breakpoint will still have the same values
  // as they had prior to resuming the thread, so it makes it easy to check
  // if we were trying to step a thread, or we tried to resume while being
  // at a breakpoint.

  // When this method gets called, the process state is still in the
  // state it was in while running so we can act accordingly.
  m_arch_up->ThreadDidStop();

  // We may have suspended this thread so the primary thread could step
  // without worrying about race conditions, so lets restore our suspend
  // count.
  RestoreSuspendCountAfterStop();

  // Update the basic information for a thread
  MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info);

  if (m_basic_info.suspend_count > 0)
    SetState(eStateSuspended);
  else
    SetState(eStateStopped);
  return true;
}