//===-- 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/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.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();

  Log *log = GetLog(LLDBLog::Step);
  if (log && log->GetVerbose())
    LLDB_LOGF(log,
              "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();

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

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

  if (thread_to_run != nullptr) {
    Log *log = GetLog(LLDBLog::Step);
    if (log && log->GetVerbose())
      LLDB_LOGF(log, "Turning on notification of new threads while single "
                     "stepping a thread.");
    m_process.StartNoticingNewThreads();
  } else {
    Log *log = GetLog(LLDBLog::Step);
    if (log && log->GetVerbose())
      LLDB_LOGF(log, "Turning off notification of new threads while single "
                     "stepping a thread.");
    m_process.StopNoticingNewThreads();
  }

  bool need_to_resume = true;

  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(eStateSuspended);
    }
  }

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