Exemplo n.º 1
0
uint32_t MachThreadList::ProcessDidStop(MachProcess *process) {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  // Update our thread list
  const uint32_t num_threads = UpdateThreadList(process, true);
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->ThreadDidStop();
  }
  return num_threads;
}
Exemplo n.º 2
0
void
MachThreadList::ProcessWillResume(MachProcess *process, const DNBThreadResumeActions &thread_actions)
{
    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);

    // 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 = { -1U, 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();
    for (uint32_t idx = 0; idx < num_threads; ++idx)
    {
        MachThread *thread = m_threads[idx].get();
        bool handled = false;
        for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx)
        {
            if (thread == new_threads[new_idx].get())
            {
                thread->ThreadWillResume(&resume_new_threads);
                handled = true;
                break;
            }
        }

        if (!handled)
        {
            const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true);
            // There must always be a thread action for every thread.
            assert (thread_action);
            bool others_stopped = false;
            if (solo_thread == thread->ThreadID())
                others_stopped = true;
            thread->ThreadWillResume (thread_action, others_stopped);
        }
    }
    
    if (new_threads.size())
    {
        for (uint32_t idx = 0; idx < num_new_threads; ++idx)
        {
            DNBLogThreadedIf (LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%4.4x, thread-is-user-ready=%i)", 
                              process->ProcessID(), 
                              process->StopCount(), 
                              new_threads[idx]->ThreadID(),
                              new_threads[idx]->IsUserReady());
        }
    }
}