//===-- ThreadList.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <cstdlib>

#include <algorithm>

#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"

using namespace lldb;
using namespace lldb_private;

ThreadList::ThreadList(Process &process)
    : ThreadCollection(), m_process(process), m_stop_id(0),
      m_selected_tid(LLDB_INVALID_THREAD_ID) {}

ThreadList::ThreadList(const ThreadList &rhs)
    : ThreadCollection(), m_process(rhs.m_process), m_stop_id(rhs.m_stop_id),
      m_selected_tid() {
  // Use the assignment operator since it uses the mutex
  *this = rhs;
}

const ThreadList &ThreadList::operator=(const ThreadList &rhs) {
  if (this != &rhs) {
    // We only allow assignments between thread lists describing the same
    // process. Same process implies same mutex, which means it's enough to lock
    // just the current object.
    assert(&m_process == &rhs.m_process);
    assert(&GetMutex() == &rhs.GetMutex());
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    m_stop_id = rhs.m_stop_id;
    m_threads = rhs.m_threads;
    m_selected_tid = rhs.m_selected_tid;
  }
  return *this;
}

ThreadList::~ThreadList() {
  // Clear the thread list. Clear will take the mutex lock which will ensure
  // that if anyone is using the list they won't get it removed while using it.
  Clear();
}

lldb::ThreadSP ThreadList::GetExpressionExecutionThread() {
  if (m_expression_tid_stack.empty())
    return GetSelectedThread();
  ThreadSP expr_thread_sp = FindThreadByID(m_expression_tid_stack.back());
  if (expr_thread_sp)
    return expr_thread_sp;
  else
    return GetSelectedThread();
}

void ThreadList::PushExpressionExecutionThread(lldb::tid_t tid) {
  m_expression_tid_stack.push_back(tid);
}

void ThreadList::PopExpressionExecutionThread(lldb::tid_t tid) {
  assert(m_expression_tid_stack.back() == tid);
  m_expression_tid_stack.pop_back();
}

uint32_t ThreadList::GetStopID() const { return m_stop_id; }

void ThreadList::SetStopID(uint32_t stop_id) { m_stop_id = stop_id; }

uint32_t ThreadList::GetSize(bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();
  return m_threads.size();
}

ThreadSP ThreadList::GetThreadAtIndex(uint32_t idx, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  if (idx < m_threads.size())
    thread_sp = m_threads[idx];
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetID() == tid) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByProtocolID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetProtocolID() == tid) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::RemoveThreadByID(lldb::tid_t tid, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetID() == tid) {
      thread_sp = m_threads[idx];
      m_threads.erase(m_threads.begin() + idx);
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::RemoveThreadByProtocolID(lldb::tid_t tid,
                                              bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  uint32_t idx = 0;
  const uint32_t num_threads = m_threads.size();
  for (idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetProtocolID() == tid) {
      thread_sp = m_threads[idx];
      m_threads.erase(m_threads.begin() + idx);
      break;
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::GetThreadSPForThreadPtr(Thread *thread_ptr) {
  ThreadSP thread_sp;
  if (thread_ptr) {
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    uint32_t idx = 0;
    const uint32_t num_threads = m_threads.size();
    for (idx = 0; idx < num_threads; ++idx) {
      if (m_threads[idx].get() == thread_ptr) {
        thread_sp = m_threads[idx];
        break;
      }
    }
  }
  return thread_sp;
}

ThreadSP ThreadList::FindThreadByIndexID(uint32_t index_id, bool can_update) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  if (can_update)
    m_process.UpdateThreadListIfNeeded();

  ThreadSP thread_sp;
  const uint32_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->GetIndexID() == index_id) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

bool ThreadList::ShouldStop(Event *event_ptr) {
  // Running events should never stop, obviously...

  Log *log = GetLog(LLDBLog::Step);

  // The ShouldStop method of the threads can do a whole lot of work, figuring
  // out whether the thread plan conditions are met.  So we don't want to keep
  // the ThreadList locked the whole time we are doing this.
  // FIXME: It is possible that running code could cause new threads
  // to be created.  If that happens, we will miss asking them whether they
  // should stop.  This is not a big deal since we haven't had a chance to hang
  // any interesting operations on those threads yet.

  collection threads_copy;
  {
    // Scope for locker
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    m_process.UpdateThreadListIfNeeded();
    for (lldb::ThreadSP thread_sp : m_threads) {
      // This is an optimization...  If we didn't let a thread run in between
      // the previous stop and this one, we shouldn't have to consult it for
      // ShouldStop.  So just leave it off the list we are going to inspect.
      // If the thread didn't run but had work to do before declaring a public
      // stop, then also include it.
      // On Linux, if a thread-specific conditional breakpoint was hit, it won't
      // necessarily be the thread that hit the breakpoint itself that
      // evaluates the conditional expression, so the thread that hit the
      // breakpoint could still be asked to stop, even though it hasn't been
      // allowed to run since the previous stop.
      if (thread_sp->GetTemporaryResumeState() != eStateSuspended ||
          thread_sp->IsStillAtLastBreakpointHit()
          || thread_sp->ShouldRunBeforePublicStop())
        threads_copy.push_back(thread_sp);
    }

    // It is possible the threads we were allowing to run all exited and then
    // maybe the user interrupted or something, then fall back on looking at
    // all threads:

    if (threads_copy.size() == 0)
      threads_copy = m_threads;
  }

  collection::iterator pos, end = threads_copy.end();

  if (log) {
    log->PutCString("");
    LLDB_LOGF(log,
              "ThreadList::%s: %" PRIu64 " threads, %" PRIu64
              " unsuspended threads",
              __FUNCTION__, (uint64_t)m_threads.size(),
              (uint64_t)threads_copy.size());
  }

  bool did_anybody_stop_for_a_reason = false;

  // If the event is an Interrupt event, then we're going to stop no matter
  // what.  Otherwise, presume we won't stop.
  bool should_stop = false;
  if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) {
    LLDB_LOGF(
        log, "ThreadList::%s handling interrupt event, should stop set to true",
        __FUNCTION__);

    should_stop = true;
  }

  // Now we run through all the threads and get their stop info's.  We want to
  // make sure to do this first before we start running the ShouldStop, because
  // one thread's ShouldStop could destroy information (like deleting a thread
  // specific breakpoint another thread had stopped at) which could lead us to
  // compute the StopInfo incorrectly. We don't need to use it here, we just
  // want to make sure it gets computed.

  for (pos = threads_copy.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    thread_sp->GetStopInfo();
  }

  // If a thread needs to finish some job that can be done just on this thread
  // before broadcastion the stop, it will signal that by returning true for
  // ShouldRunBeforePublicStop.  This variable gathers the results from that.
  bool a_thread_needs_to_run = false;
  for (pos = threads_copy.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);

    // We should never get a stop for which no thread had a stop reason, but
    // sometimes we do see this - for instance when we first connect to a
    // remote stub.  In that case we should stop, since we can't figure out the
    // right thing to do and stopping gives the user control over what to do in
    // this instance.
    //
    // Note, this causes a problem when you have a thread specific breakpoint,
    // and a bunch of threads hit the breakpoint, but not the thread which we
    // are waiting for.  All the threads that are not "supposed" to hit the
    // breakpoint are marked as having no stop reason, which is right, they
    // should not show a stop reason.  But that triggers this code and causes
    // us to stop seemingly for no reason.
    //
    // Since the only way we ever saw this error was on first attach, I'm only
    // going to trigger set did_anybody_stop_for_a_reason to true unless this
    // is the first stop.
    //
    // If this becomes a problem, we'll have to have another StopReason like
    // "StopInfoHidden" which will look invalid everywhere but at this check.

    if (thread_sp->GetProcess()->GetStopID() > 1)
      did_anybody_stop_for_a_reason = true;
    else
      did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();

    const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);

    if (thread_should_stop)
      should_stop |= true;
    else {
      bool this_thread_forces_run = thread_sp->ShouldRunBeforePublicStop();
      a_thread_needs_to_run |= this_thread_forces_run;
      if (this_thread_forces_run) 
        LLDB_LOG(log,
                 "ThreadList::{0} thread: {1:x}, "
                 "says it needs to run before public stop.",
                 __FUNCTION__, thread_sp->GetID());
    }
  }

  if (a_thread_needs_to_run) {
    should_stop = false;
  } else if (!should_stop && !did_anybody_stop_for_a_reason) {
    should_stop = true;
    LLDB_LOGF(log,
              "ThreadList::%s we stopped but no threads had a stop reason, "
              "overriding should_stop and stopping.",
              __FUNCTION__);
  }

  LLDB_LOGF(log, "ThreadList::%s overall should_stop = %i", __FUNCTION__,
            should_stop);

  if (should_stop) {
    for (pos = threads_copy.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      thread_sp->WillStop();
    }
  }

  return should_stop;
}

Vote ThreadList::ShouldReportStop(Event *event_ptr) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  Vote result = eVoteNoOpinion;
  m_process.UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();

  Log *log = GetLog(LLDBLog::Step);

  LLDB_LOGF(log, "ThreadList::%s %" PRIu64 " threads", __FUNCTION__,
            (uint64_t)m_threads.size());

  // Run through the threads and ask whether we should report this event. For
  // stopping, a YES vote wins over everything.  A NO vote wins over NO
  // opinion.  The exception is if a thread has work it needs to force before
  // a public stop, which overrides everyone else's opinion:
  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    if (thread_sp->ShouldRunBeforePublicStop()) {
      LLDB_LOG(log, "Thread {0:x} has private business to complete, overrode "
               "the should report stop.", thread_sp->GetID());
      result = eVoteNo;
      break;
    }

    const Vote vote = thread_sp->ShouldReportStop(event_ptr);
    switch (vote) {
    case eVoteNoOpinion:
      continue;

    case eVoteYes:
      result = eVoteYes;
      break;

    case eVoteNo:
      if (result == eVoteNoOpinion) {
        result = eVoteNo;
      } else {
        LLDB_LOG(log,
          "Thread {0:x} voted {1}, but lost out because result was {2}",
          thread_sp->GetID(), vote, result);
      }
      break;
    }
  }
  LLDB_LOG(log, "Returning {0}", result);
  return result;
}

void ThreadList::SetShouldReportStop(Vote vote) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  m_process.UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    thread_sp->SetShouldReportStop(vote);
  }
}

Vote ThreadList::ShouldReportRun(Event *event_ptr) {

  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  Vote result = eVoteNoOpinion;
  m_process.UpdateThreadListIfNeeded();
  collection::iterator pos, end = m_threads.end();

  // Run through the threads and ask whether we should report this event. The
  // rule is NO vote wins over everything, a YES vote wins over no opinion.

  Log *log = GetLog(LLDBLog::Step);

  for (pos = m_threads.begin(); pos != end; ++pos) {
    if ((*pos)->GetResumeState() != eStateSuspended) {
      switch ((*pos)->ShouldReportRun(event_ptr)) {
      case eVoteNoOpinion:
        continue;
      case eVoteYes:
        if (result == eVoteNoOpinion)
          result = eVoteYes;
        break;
      case eVoteNo:
        LLDB_LOGF(log,
                  "ThreadList::ShouldReportRun() thread %d (0x%4.4" PRIx64
                  ") says don't report.",
                  (*pos)->GetIndexID(), (*pos)->GetID());
        result = eVoteNo;
        break;
      }
    }
  }
  return result;
}

void ThreadList::Clear() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  m_stop_id = 0;
  m_threads.clear();
  m_selected_tid = LLDB_INVALID_THREAD_ID;
}

void ThreadList::Destroy() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  const uint32_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->DestroyThread();
  }
}

void ThreadList::RefreshStateAfterStop() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  m_process.UpdateThreadListIfNeeded();

  LLDB_LOGF_VERBOSE(
      GetLog(LLDBLog::Step),
      "Turning off notification of new threads while single stepping "
      "a thread.");

  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    (*pos)->SetState(eStateStopped);
    (*pos)->RefreshStateAfterStop();
  }
}

void ThreadList::DiscardThreadPlans() {
  // You don't need to update the thread list here, because only threads that
  // you currently know about have any thread plans.
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos)
    (*pos)->DiscardThreadPlans(true);
}

bool ThreadList::WillResume(RunDirection &direction) {
  // Run through the threads and perform their momentary actions. But we only
  // do this for threads that are running, user suspended threads stay where
  // they are.

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  m_process.UpdateThreadListIfNeeded();

  collection::iterator pos, end = m_threads.end();

  // Clear tracking state from the previous stop and pop any leftover
  // StepOverBreakpoint plans. This gives us a clean slate: plans will be
  // recreated fresh by SetupToStepOverBreakpointIfNeeded below, and the
  // batching logic will recompute deferred state from scratch.
  m_threads_stepping_over_bp.clear();
  for (const auto &thread_sp : m_threads) {
    ThreadPlan *plan = thread_sp->GetCurrentPlan();
    if (plan && plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
      auto *bp_plan = static_cast<ThreadPlanStepOverBreakpoint *>(plan);
      // Only pop plans created by our batching logic (deferred plans).
      // Plans from the single-thread path must not be popped, as doing so
      // would change the StopOthers scan result and cause other threads
      // to lose their breakpoint stop reason.
      if (bp_plan->GetDeferReenableBreakpointSite()) {
        // Suppress the re-enable side effect in DidPop(), the breakpoint
        // may still be disabled from the previous batch, and we don't want
        // to toggle it. The new plans will handle re-enable correctly.
        bp_plan->SetReenabledBreakpointSite();
        thread_sp->DiscardPlan();
      }
    }
  }

  // Go through the threads and see if any thread wants to run just itself.
  // if so then pick one and run it.

  // Collect threads for batched vCont for multiple threads at the same
  // breakpoint.
  llvm::SmallVector<ThreadSP> batched_step_threads;

  ThreadList run_me_only_list(m_process);

  run_me_only_list.SetStopID(m_process.GetStopID());

  // One or more threads might want to "Stop Others".  We want to handle all
  // those requests first.  And if there is a thread that wanted to "resume
  // before a public stop", let it get the first crack:
  // There are two special kinds of thread that have priority for "StopOthers":
  // a "ShouldRunBeforePublicStop thread, or the currently selected thread.  If
  // we find one satisfying that critereon, put it here.
  ThreadSP thread_to_run;
  for (pos = m_threads.begin(); pos != end; ++pos) {
    ThreadSP thread_sp(*pos);
    if (thread_sp->GetResumeState() != eStateSuspended &&
        thread_sp->GetCurrentPlan()->StopOthers()) {
      if (thread_sp->IsOperatingSystemPluginThread() &&
          !thread_sp->GetBackingThread())
        continue;

      // You can't say "stop others" and also want yourself to be suspended.
      assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
      run_me_only_list.AddThread(thread_sp);

      if (thread_sp == GetSelectedThread())
        thread_to_run = thread_sp;

      if (thread_sp->ShouldRunBeforePublicStop()) {
        // This takes precedence, so if we find one of these, service it:
        thread_to_run = thread_sp;
        break;
      }
    }
  }

  if (run_me_only_list.GetSize(false) > 0 && !thread_to_run) {
    if (run_me_only_list.GetSize(false) == 1) {
      thread_to_run = run_me_only_list.GetThreadAtIndex(0);
    } else {
      int random_thread =
          (int)((run_me_only_list.GetSize(false) * (double)rand()) /
                (RAND_MAX + 1.0));
      thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
    }
  }

  if (thread_to_run != nullptr) {
    direction = thread_to_run->GetCurrentPlan()->GetDirection();
  } else {
    direction = m_process.GetBaseDirection();
  }

  // Give all the threads that are likely to run a last chance to set up their
  // state before we negotiate who is actually going to get a chance to run...
  // Don't set to resume suspended threads, and if any thread wanted to stop
  // others, only call setup on the threads that request StopOthers...
  if (thread_to_run != nullptr) {
    // See if any thread wants to run stopping others.  If it does, then we
    // won't setup the other threads for resume, since they aren't going to get
    // a chance to run.  This is necessary because the SetupForResume might add
    // "StopOthers" plans which would then get to be part of the who-gets-to-run
    // negotiation, but they're coming in after the fact, and the threads that
    // are already set up should take priority.
    if (thread_to_run->SetupToStepOverBreakpointIfNeeded(direction)) {
      // We only need to step over breakpoints when running forward, and the
      // step-over-breakpoint plan itself wants to run forward, so this
      // keeps our desired direction.
      assert(thread_to_run->GetCurrentPlan()->GetDirection() == direction);
    }
  } else {
    // Pre-scan to find all threads that need to step over a breakpoint,
    // and group them by breakpoint address. This optimization allows us to
    // step multiple threads over the same breakpoint with minimal breakpoint
    // swaps, only the last thread in each group will re-enable the breakpoint.
    llvm::DenseMap<lldb::addr_t, llvm::SmallVector<ThreadSP>> breakpoint_groups;
    bool found_run_before_public_stop = false;

    for (pos = m_threads.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      if (thread_sp->GetResumeState() != eStateSuspended) {
        if (thread_sp->IsOperatingSystemPluginThread() &&
            !thread_sp->GetBackingThread())
          continue;
        if (thread_sp->SetupToStepOverBreakpointIfNeeded(direction)) {
          // We only need to step over breakpoints when running forward, and the
          // step-over-breakpoint plan itself wants to run forward, so this
          // keeps our desired direction.
          assert(thread_sp->GetCurrentPlan()->GetDirection() == direction);
          // You can't say "stop others" and also want yourself to be suspended.
          assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);

          // Get the breakpoint address from the step-over-breakpoint plan.
          ThreadPlan *current_plan = thread_sp->GetCurrentPlan();
          if (current_plan &&
              current_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
            ThreadPlanStepOverBreakpoint *bp_plan =
                static_cast<ThreadPlanStepOverBreakpoint *>(current_plan);
            lldb::addr_t bp_addr = bp_plan->GetBreakpointLoadAddress();
            breakpoint_groups[bp_addr].push_back(thread_sp);
          }

          thread_to_run = thread_sp;
          if (thread_sp->ShouldRunBeforePublicStop()) {
            // This takes precedence, so if we find one of these, service it:
            found_run_before_public_stop = true;
            break;
          }
        }
      }
    }

    // Only apply batching optimization if we have a complete picture of
    // breakpoint groups. If a ShouldRunBeforePublicStop thread caused the
    // scan to exit early, the groups are incomplete and the priority thread
    // must run solo. Deferred state will be cleaned up on next WillResume().
    if (!found_run_before_public_stop) {
      // For each group of threads at the same breakpoint, register them with
      // ThreadList and set them to use deferred re-enable. The breakpoint will
      // only be re-enabled when ALL threads have finished stepping over it.
      // Also collect threads for batched vCont if multiple threads at same BP.
      for (auto &group : breakpoint_groups) {
        lldb::addr_t bp_addr = group.first;
        llvm::SmallVector<ThreadSP> &threads = group.second;

        if (threads.size() > 1) {
          // Use tracking since multiple threads are stepping over the same
          // breakpoint.
          for (ThreadSP &thread_sp : threads) {
            // Register this thread as stepping over the breakpoint.
            RegisterThreadSteppingOverBreakpoint(bp_addr, thread_sp->GetID());

            // Set the plan to defer re-enabling (use callback instead).
            ThreadPlan *plan = thread_sp->GetCurrentPlan();
            // Verify the plan is actually a StepOverBreakpoint plan.
            if (plan &&
                plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
              ThreadPlanStepOverBreakpoint *bp_plan =
                  static_cast<ThreadPlanStepOverBreakpoint *>(plan);
              bp_plan->SetDeferReenableBreakpointSite(true);
            }
          }

          // Pick the largest group for batched vCont.
          if (threads.size() > batched_step_threads.size())
            batched_step_threads = threads;
        }
        // Keeps default behavior for a single thread at breakpoint.
      }

      // If we found a batch, use the first thread as thread_to_run.
      if (!batched_step_threads.empty())
        thread_to_run = batched_step_threads[0];
    }
  }

  if (thread_to_run != nullptr) {
    LLDB_LOGF_VERBOSE(GetLog(LLDBLog::Step),
                      "Turning on notification of new threads while single "
                      "stepping a thread.");
    m_process.StartNoticingNewThreads();
  } else {
    LLDB_LOGF_VERBOSE(GetLog(LLDBLog::Step),
                      "Turning off notification of new threads while single "
                      "stepping a thread.");
    m_process.StopNoticingNewThreads();
  }

  bool need_to_resume = true;

  // Check if any threads should always be allowed to run based on their name.
  Args always_run_names = m_process.GetAlwaysRunThreadNames();
  auto resume_state_for_thread = [&](const ThreadSP &thread_sp) -> StateType {
    if (always_run_names.GetArgumentCount() == 0)
      return eStateSuspended;
    const char *name = thread_sp->GetName();
    if (!name)
      return eStateSuspended;
    llvm::StringRef name_str(name);
    Log *log = GetLog(LLDBLog::Step);
    for (size_t i = 0; i < always_run_names.GetArgumentCount(); ++i) {
      if (name_str == always_run_names.GetArgumentAtIndex(i)) {
        LLDB_LOG(log,
                 "Thread \"{0}\" (tid={1:x}) will continue due to "
                 "always-run-thread-names setting",
                 name, thread_sp->GetID());
        return eStateRunning;
      }
    }
    return eStateSuspended;
  };

  if (!batched_step_threads.empty()) {
    // Batched stepping: all threads in the batch step together,
    // all other threads stay suspended.
    llvm::DenseSet<lldb::tid_t> batch_tids;
    for (ThreadSP &thread_sp : batched_step_threads)
      batch_tids.insert(thread_sp->GetID());

    for (const auto &thread_sp : m_threads) {
      if (batch_tids.count(thread_sp->GetID()) > 0) {
        // This thread is in the batch, let it step.
        if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
          need_to_resume = false;
      } else {
        // Suspend it since it's not in the batch, unless it should always run.
        thread_sp->ShouldResume(resume_state_for_thread(thread_sp));
      }
    }
  } else if (thread_to_run == nullptr) {
    // Everybody runs as they wish:
    for (pos = m_threads.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      StateType run_state;
      if (thread_sp->GetResumeState() != eStateSuspended)
        run_state = thread_sp->GetCurrentPlan()->RunState();
      else
        run_state = eStateSuspended;
      if (!thread_sp->ShouldResume(run_state))
        need_to_resume = false;
    }
    if (need_to_resume) {
      // Ensure all threads are running in the right direction
      for (pos = m_threads.begin(); pos != end; ++pos) {
        ThreadSP thread_sp(*pos);
        while (thread_sp->GetCurrentPlan()->GetDirection() != direction) {
          // This can't discard the base plan because its direction is
          // m_process.GetBaseDirection() i.e. `direction`.
          thread_sp->DiscardPlan();
        }
      }
    }
  } else {
    for (pos = m_threads.begin(); pos != end; ++pos) {
      ThreadSP thread_sp(*pos);
      if (thread_sp == thread_to_run) {
        // Note, a thread might be able to fulfil it's plan w/o actually
        // resuming.  An example of this is a step that changes the current
        // inlined function depth w/o moving the PC.  Check that here:
        if (!thread_sp->ShouldResume(thread_sp->GetCurrentPlan()->RunState()))
          need_to_resume = false;
      } else
        thread_sp->ShouldResume(resume_state_for_thread(thread_sp));
    }
  }

  return need_to_resume;
}

void ThreadList::DidResume() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    // Don't clear out threads that aren't going to get a chance to run, rather
    // leave their state for the next time around.
    ThreadSP thread_sp(*pos);
    if (thread_sp->GetTemporaryResumeState() != eStateSuspended)
      thread_sp->DidResume();
  }
}

void ThreadList::DidStop() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos) {
    // Notify threads that the process just stopped. Note, this currently
    // assumes that all threads in the list stop when the process stops.  In
    // the future we will want to support a debugging model where some threads
    // continue to run while others are stopped.  We either need to handle that
    // somehow here or create a special thread list containing only threads
    // which will stop in the code that calls this method (currently
    // Process::SetPrivateState).
    ThreadSP thread_sp(*pos);
    if (StateIsRunningState(thread_sp->GetState()))
      thread_sp->DidStop();
  }
}

ThreadSP ThreadList::GetSelectedThread() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP thread_sp = FindThreadByID(m_selected_tid);
  if (!thread_sp.get()) {
    if (m_threads.size() == 0)
      return thread_sp;
    m_selected_tid = m_threads[0]->GetID();
    thread_sp = m_threads[0];
  }
  return thread_sp;
}

bool ThreadList::SetSelectedThreadByID(lldb::tid_t tid, bool notify) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP selected_thread_sp(FindThreadByID(tid));
  if (selected_thread_sp) {
    m_selected_tid = tid;
    selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
  } else
    m_selected_tid = LLDB_INVALID_THREAD_ID;

  if (notify)
    NotifySelectedThreadChanged(m_selected_tid);

  return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

bool ThreadList::SetSelectedThreadByIndexID(uint32_t index_id, bool notify) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  ThreadSP selected_thread_sp(FindThreadByIndexID(index_id));
  if (selected_thread_sp.get()) {
    m_selected_tid = selected_thread_sp->GetID();
    selected_thread_sp->SetDefaultFileAndLineToSelectedFrame();
  } else
    m_selected_tid = LLDB_INVALID_THREAD_ID;

  if (notify)
    NotifySelectedThreadChanged(m_selected_tid);

  return m_selected_tid != LLDB_INVALID_THREAD_ID;
}

void ThreadList::NotifySelectedThreadChanged(lldb::tid_t tid) {
  ThreadSP selected_thread_sp(FindThreadByID(tid));
  if (selected_thread_sp->EventTypeHasListeners(
          Thread::eBroadcastBitThreadSelected)) {
    auto data_sp =
        std::make_shared<Thread::ThreadEventData>(selected_thread_sp);
    selected_thread_sp->BroadcastEvent(Thread::eBroadcastBitThreadSelected,
                                       data_sp);
  }
}

void ThreadList::Update(ThreadList &rhs) {
  if (this != &rhs) {
    // We only allow assignments between thread lists describing the same
    // process. Same process implies same mutex, which means it's enough to lock
    // just the current object.
    assert(&m_process == &rhs.m_process);
    assert(&GetMutex() == &rhs.GetMutex());
    std::lock_guard<std::recursive_mutex> guard(GetMutex());

    m_stop_id = rhs.m_stop_id;
    m_threads.swap(rhs.m_threads);
    m_selected_tid = rhs.m_selected_tid;

    // Now we look for threads that we are done with and make sure to clear
    // them up as much as possible so anyone with a shared pointer will still
    // have a reference, but the thread won't be of much use. Using
    // std::weak_ptr for all backward references (such as a thread to a
    // process) will eventually solve this issue for us, but for now, we need
    // to work around the issue
    collection::iterator rhs_pos, rhs_end = rhs.m_threads.end();
    for (rhs_pos = rhs.m_threads.begin(); rhs_pos != rhs_end; ++rhs_pos) {
      // If this thread has already been destroyed, we don't need to look for
      // it to destroy it again.
      if (!(*rhs_pos)->IsValid())
        continue;

      const lldb::tid_t tid = (*rhs_pos)->GetID();
      bool thread_is_alive = false;
      const uint32_t num_threads = m_threads.size();
      for (uint32_t idx = 0; idx < num_threads; ++idx) {
        ThreadSP backing_thread = m_threads[idx]->GetBackingThread();
        if (m_threads[idx]->GetID() == tid ||
            (backing_thread && backing_thread->GetID() == tid)) {
          thread_is_alive = true;
          break;
        }
      }
      if (!thread_is_alive) {
        (*rhs_pos)->DestroyThread();
      }
    }
  }
}

void ThreadList::Flush() {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  collection::iterator pos, end = m_threads.end();
  for (pos = m_threads.begin(); pos != end; ++pos)
    (*pos)->Flush();
}

std::recursive_mutex &ThreadList::GetMutex() const {
  return m_process.m_thread_mutex;
}

ThreadList::ExpressionExecutionThreadPusher::ExpressionExecutionThreadPusher(
    lldb::ThreadSP thread_sp)
    : m_thread_list(nullptr), m_tid(LLDB_INVALID_THREAD_ID) {
  if (thread_sp) {
    m_tid = thread_sp->GetID();
    m_thread_list = &thread_sp->GetProcess()->GetThreadList();
    m_thread_list->PushExpressionExecutionThread(m_tid);
  }
}

void ThreadList::RegisterThreadSteppingOverBreakpoint(addr_t breakpoint_addr,
                                                      tid_t tid) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  m_threads_stepping_over_bp[breakpoint_addr].insert(tid);

  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOGF(
      log,
      "ThreadList::%s: Registered thread 0x%" PRIx64
      " stepping over breakpoint at 0x%" PRIx64 " (now %zu threads)",
      __FUNCTION__, tid, breakpoint_addr,
      static_cast<size_t>(m_threads_stepping_over_bp[breakpoint_addr].size()));
}

void ThreadList::ThreadFinishedSteppingOverBreakpoint(addr_t breakpoint_addr,
                                                      tid_t tid) {
  std::lock_guard<std::recursive_mutex> guard(GetMutex());

  Log *log = GetLog(LLDBLog::Step);

  auto it = m_threads_stepping_over_bp.find(breakpoint_addr);
  if (it == m_threads_stepping_over_bp.end()) {
    // No threads registered for this breakpoint, re-enable directly.
    LLDB_LOGF(log,
              "ThreadList::%s: Thread 0x%" PRIx64
              " finished stepping over breakpoint at 0x%" PRIx64
              " but no threads were registered, re-enabling directly",
              __FUNCTION__, tid, breakpoint_addr);
    if (BreakpointSiteSP bp_site_sp =
            m_process.GetBreakpointSiteList().FindByAddress(breakpoint_addr))
      m_process.EnableBreakpointSite(bp_site_sp.get());
    return;
  }

  // Remove this thread from the set.
  it->second.erase(tid);

  LLDB_LOGF(log,
            "ThreadList::%s: Thread 0x%" PRIx64
            " finished stepping over breakpoint at 0x%" PRIx64
            " (%zu threads remaining)",
            __FUNCTION__, tid, breakpoint_addr,
            static_cast<size_t>(it->second.size()));

  // If no more threads are stepping over this breakpoint, re-enable it.
  if (it->second.empty()) {
    LLDB_LOGF(log,
              "ThreadList::%s: All threads finished stepping over breakpoint "
              "at 0x%" PRIx64 ", re-enabling breakpoint",
              __FUNCTION__, breakpoint_addr);

    if (BreakpointSiteSP bp_site_sp =
            m_process.GetBreakpointSiteList().FindByAddress(breakpoint_addr))
      m_process.EnableBreakpointSite(bp_site_sp.get());

    // Clean up the entry.
    m_threads_stepping_over_bp.erase(it);
  }
}
