//===-- 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)->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);
  }
}
