//===-- SBThread.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBThread.h"

#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBSymbolContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Stream.h"

#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"

using namespace lldb;
using namespace lldb_private;

const char *SBThread::GetBroadcasterClassName() {
  return Thread::GetStaticBroadcasterClass().AsCString();
}

//----------------------------------------------------------------------
// Constructors
//----------------------------------------------------------------------
SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {}

SBThread::SBThread(const ThreadSP &lldb_object_sp)
    : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {}

SBThread::SBThread(const SBThread &rhs)
    : m_opaque_sp(new ExecutionContextRef(*rhs.m_opaque_sp)) {}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------

const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
  if (this != &rhs)
    *m_opaque_sp = *rhs.m_opaque_sp;
  return *this;
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SBThread::~SBThread() {}

lldb::SBQueue SBThread::GetQueue() const {
  SBQueue sb_queue;
  QueueSP queue_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
      if (queue_sp) {
        sb_queue.SetQueue(queue_sp);
      }
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetQueue() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetQueue () => SBQueue(%p)",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                static_cast<void *>(queue_sp.get()));

  return sb_queue;
}

bool SBThread::IsValid() const {
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  Target *target = exe_ctx.GetTargetPtr();
  Process *process = exe_ctx.GetProcessPtr();
  if (target && process) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process->GetRunLock()))
      return m_opaque_sp->GetThreadSP().get() != NULL;
  }
  // Without a valid target & process, this thread can't be valid.
  return false;
}

void SBThread::Clear() { m_opaque_sp->Clear(); }

StopReason SBThread::GetStopReason() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  StopReason reason = eStopReasonInvalid;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      return exe_ctx.GetThreadPtr()->GetStopReason();
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::GetStopReason() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetStopReason () => %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                Thread::StopReasonAsCString(reason));

  return reason;
}

size_t SBThread::GetStopReasonDataCount() {
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
      if (stop_info_sp) {
        StopReason reason = stop_info_sp->GetStopReason();
        switch (reason) {
        case eStopReasonInvalid:
        case eStopReasonNone:
        case eStopReasonTrace:
        case eStopReasonExec:
        case eStopReasonPlanComplete:
        case eStopReasonThreadExiting:
        case eStopReasonInstrumentation:
          // There is no data for these stop reasons.
          return 0;

        case eStopReasonBreakpoint: {
          break_id_t site_id = stop_info_sp->GetValue();
          lldb::BreakpointSiteSP bp_site_sp(
              exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
                  site_id));
          if (bp_site_sp)
            return bp_site_sp->GetNumberOfOwners() * 2;
          else
            return 0; // Breakpoint must have cleared itself...
        } break;

        case eStopReasonWatchpoint:
          return 1;

        case eStopReasonSignal:
          return 1;

        case eStopReasonException:
          return 1;
        }
      }
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBThread(%p)::GetStopReasonDataCount() => error: process "
                    "is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }
  return 0;
}

uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      Thread *thread = exe_ctx.GetThreadPtr();
      StopInfoSP stop_info_sp = thread->GetStopInfo();
      if (stop_info_sp) {
        StopReason reason = stop_info_sp->GetStopReason();
        switch (reason) {
        case eStopReasonInvalid:
        case eStopReasonNone:
        case eStopReasonTrace:
        case eStopReasonExec:
        case eStopReasonPlanComplete:
        case eStopReasonThreadExiting:
        case eStopReasonInstrumentation:
          // There is no data for these stop reasons.
          return 0;

        case eStopReasonBreakpoint: {
          break_id_t site_id = stop_info_sp->GetValue();
          lldb::BreakpointSiteSP bp_site_sp(
              exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
                  site_id));
          if (bp_site_sp) {
            uint32_t bp_index = idx / 2;
            BreakpointLocationSP bp_loc_sp(
                bp_site_sp->GetOwnerAtIndex(bp_index));
            if (bp_loc_sp) {
              if (idx & 1) {
                // Odd idx, return the breakpoint location ID
                return bp_loc_sp->GetID();
              } else {
                // Even idx, return the breakpoint ID
                return bp_loc_sp->GetBreakpoint().GetID();
              }
            }
          }
          return LLDB_INVALID_BREAK_ID;
        } break;

        case eStopReasonWatchpoint:
          return stop_info_sp->GetValue();

        case eStopReasonSignal:
          return stop_info_sp->GetValue();

        case eStopReasonException:
          return stop_info_sp->GetValue();
        }
      }
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBThread(%p)::GetStopReasonDataAtIndex() => error: "
                    "process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }
  return 0;
}

bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
  Stream &strm = stream.ref();

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (!exe_ctx.HasThreadScope())
    return false;

  StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
  StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
  if (!info)
    return false;

  info->Dump(strm);

  return true;
}

SBThreadCollection
SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
  ThreadCollectionSP threads;
  threads.reset(new ThreadCollection());

  // We currently only support ThreadSanitizer.
  if (type != eInstrumentationRuntimeTypeThreadSanitizer)
    return threads;

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (!exe_ctx.HasThreadScope())
    return threads;

  ProcessSP process_sp = exe_ctx.GetProcessSP();

  StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
  StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
  if (!info)
    return threads;

  return process_sp->GetInstrumentationRuntime(type)
      ->GetBacktracesFromExtendedStopInfo(info);
}

size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {

      StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
      if (stop_info_sp) {
        const char *stop_desc = stop_info_sp->GetDescription();
        if (stop_desc) {
          if (log)
            log->Printf(
                "SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
                static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);
          if (dst)
            return ::snprintf(dst, dst_len, "%s", stop_desc);
          else {
            // NULL dst passed in, return the length needed to contain the
            // description
            return ::strlen(stop_desc) + 1; // Include the NULL byte for size
          }
        } else {
          size_t stop_desc_len = 0;
          switch (stop_info_sp->GetStopReason()) {
          case eStopReasonTrace:
          case eStopReasonPlanComplete: {
            static char trace_desc[] = "step";
            stop_desc = trace_desc;
            stop_desc_len =
                sizeof(trace_desc); // Include the NULL byte for size
          } break;

          case eStopReasonBreakpoint: {
            static char bp_desc[] = "breakpoint hit";
            stop_desc = bp_desc;
            stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
          } break;

          case eStopReasonWatchpoint: {
            static char wp_desc[] = "watchpoint hit";
            stop_desc = wp_desc;
            stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
          } break;

          case eStopReasonSignal: {
            stop_desc =
                exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(
                    stop_info_sp->GetValue());
            if (stop_desc == NULL || stop_desc[0] == '\0') {
              static char signal_desc[] = "signal";
              stop_desc = signal_desc;
              stop_desc_len =
                  sizeof(signal_desc); // Include the NULL byte for size
            }
          } break;

          case eStopReasonException: {
            char exc_desc[] = "exception";
            stop_desc = exc_desc;
            stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
          } break;

          case eStopReasonExec: {
            char exc_desc[] = "exec";
            stop_desc = exc_desc;
            stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
          } break;

          case eStopReasonThreadExiting: {
            char limbo_desc[] = "thread exiting";
            stop_desc = limbo_desc;
            stop_desc_len = sizeof(limbo_desc);
          } break;
          default:
            break;
          }

          if (stop_desc && stop_desc[0]) {
            if (log)
              log->Printf(
                  "SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
                  static_cast<void *>(exe_ctx.GetThreadPtr()), stop_desc);

            if (dst)
              return ::snprintf(dst, dst_len, "%s", stop_desc) +
                     1; // Include the NULL byte

            if (stop_desc_len == 0)
              stop_desc_len = ::strlen(stop_desc) + 1; // Include the NULL byte

            return stop_desc_len;
          }
        }
      }
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf(
            "SBThread(%p)::GetStopDescription() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }
  if (dst)
    *dst = 0;
  return 0;
}

SBValue SBThread::GetStopReturnValue() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  ValueObjectSP return_valobj_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
      if (stop_info_sp) {
        return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
      }
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::GetStopReturnValue() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetStopReturnValue () => %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                return_valobj_sp.get() ? return_valobj_sp->GetValueAsCString()
                                       : "<no return value>");

  return SBValue(return_valobj_sp);
}

void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
  m_opaque_sp->SetThreadSP(lldb_object_sp);
}

lldb::tid_t SBThread::GetThreadID() const {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetID();
  return LLDB_INVALID_THREAD_ID;
}

uint32_t SBThread::GetIndexID() const {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetIndexID();
  return LLDB_INVALID_INDEX32;
}

const char *SBThread::GetName() const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  const char *name = NULL;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      name = exe_ctx.GetThreadPtr()->GetName();
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetName() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetName () => %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                name ? name : "NULL");

  return name;
}

const char *SBThread::GetQueueName() const {
  const char *name = NULL;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      name = exe_ctx.GetThreadPtr()->GetQueueName();
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetQueueName() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetQueueName () => %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                name ? name : "NULL");

  return name;
}

lldb::queue_id_t SBThread::GetQueueID() const {
  queue_id_t id = LLDB_INVALID_QUEUE_ID;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      id = exe_ctx.GetThreadPtr()->GetQueueID();
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetQueueID() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetQueueID () => 0x%" PRIx64,
                static_cast<void *>(exe_ctx.GetThreadPtr()), id);

  return id;
}

bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  bool success = false;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      Thread *thread = exe_ctx.GetThreadPtr();
      StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
      if (info_root_sp) {
        StructuredData::ObjectSP node =
            info_root_sp->GetObjectForDotSeparatedPath(path);
        if (node) {
          if (node->GetType() == StructuredData::Type::eTypeString) {
            strm.Printf("%s", node->GetAsString()->GetValue().c_str());
            success = true;
          }
          if (node->GetType() == StructuredData::Type::eTypeInteger) {
            strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
            success = true;
          }
          if (node->GetType() == StructuredData::Type::eTypeFloat) {
            strm.Printf("0x%f", node->GetAsFloat()->GetValue());
            success = true;
          }
          if (node->GetType() == StructuredData::Type::eTypeBoolean) {
            if (node->GetAsBoolean()->GetValue() == true)
              strm.Printf("true");
            else
              strm.Printf("false");
            success = true;
          }
          if (node->GetType() == StructuredData::Type::eTypeNull) {
            strm.Printf("null");
            success = true;
          }
        }
      }
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetInfoItemByPathAsString() => error: "
                    "process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetInfoItemByPathAsString (\"%s\") => \"%s\"",
                static_cast<void *>(exe_ctx.GetThreadPtr()), path, strm.GetData());

  return success;
}

SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
                                ThreadPlan *new_plan) {
  SBError sb_error;

  Process *process = exe_ctx.GetProcessPtr();
  if (!process) {
    sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
    return sb_error;
  }

  Thread *thread = exe_ctx.GetThreadPtr();
  if (!thread) {
    sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
    return sb_error;
  }

  // User level plans should be Master Plans so they can be interrupted, other
  // plans executed, and
  // then a "continue" will resume the plan.
  if (new_plan != NULL) {
    new_plan->SetIsMasterPlan(true);
    new_plan->SetOkayToDiscard(false);
  }

  // Why do we need to set the current thread by ID here???
  process->GetThreadList().SetSelectedThreadByID(thread->GetID());

  if (process->GetTarget().GetDebugger().GetAsyncExecution())
    sb_error.ref() = process->Resume();
  else
    sb_error.ref() = process->ResumeSynchronous(NULL);

  return sb_error;
}

void SBThread::StepOver(lldb::RunMode stop_other_threads) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::StepOver (stop_other_threads='%s')",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                Thread::RunModeAsCString(stop_other_threads));

  if (exe_ctx.HasThreadScope()) {
    Thread *thread = exe_ctx.GetThreadPtr();
    bool abort_other_plans = false;
    StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));

    ThreadPlanSP new_plan_sp;
    if (frame_sp) {
      if (frame_sp->HasDebugInformation()) {
        const LazyBool avoid_no_debug = eLazyBoolCalculate;
        SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
        new_plan_sp = thread->QueueThreadPlanForStepOverRange(
            abort_other_plans, sc.line_entry, sc, stop_other_threads,
            avoid_no_debug);
      } else {
        new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
            true, abort_other_plans, stop_other_threads);
      }
    }

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

void SBThread::StepInto(lldb::RunMode stop_other_threads) {
  StepInto(NULL, stop_other_threads);
}

void SBThread::StepInto(const char *target_name,
                        lldb::RunMode stop_other_threads) {
  SBError error;
  StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
}

void SBThread::StepInto(const char *target_name, uint32_t end_line,
                        SBError &error, lldb::RunMode stop_other_threads) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf(
        "SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
        static_cast<void *>(exe_ctx.GetThreadPtr()),
        target_name ? target_name : "<NULL>",
        Thread::RunModeAsCString(stop_other_threads));

  if (exe_ctx.HasThreadScope()) {
    bool abort_other_plans = false;

    Thread *thread = exe_ctx.GetThreadPtr();
    StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
    ThreadPlanSP new_plan_sp;

    if (frame_sp && frame_sp->HasDebugInformation()) {
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      AddressRange range;
      if (end_line == LLDB_INVALID_LINE_NUMBER)
        range = sc.line_entry.range;
      else {
        if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
          return;
      }

      const LazyBool step_out_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      const LazyBool step_in_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      new_plan_sp = thread->QueueThreadPlanForStepInRange(
          abort_other_plans, range, sc, target_name, stop_other_threads,
          step_in_avoids_code_without_debug_info,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, stop_other_threads);
    }

    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

void SBThread::StepOut() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::StepOut ()",
                static_cast<void *>(exe_ctx.GetThreadPtr()));

  if (exe_ctx.HasThreadScope()) {
    bool abort_other_plans = false;
    bool stop_other_threads = false;

    Thread *thread = exe_ctx.GetThreadPtr();

    const LazyBool avoid_no_debug = eLazyBoolCalculate;
    ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
        abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
        eVoteNoOpinion, 0, avoid_no_debug));

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (!sb_frame.IsValid()) {
    if (log)
      log->Printf(
          "SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
          static_cast<void *>(exe_ctx.GetThreadPtr()));
    return;
  }

  StackFrameSP frame_sp(sb_frame.GetFrameSP());
  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
  }

  if (exe_ctx.HasThreadScope()) {
    bool abort_other_plans = false;
    bool stop_other_threads = false;
    Thread *thread = exe_ctx.GetThreadPtr();
    if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
      log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another "
                  "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.",
                  static_cast<void *>(exe_ctx.GetThreadPtr()),
                  sb_frame.GetThread().GetThreadID(), thread->GetID());
    }

    ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
        abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
        eVoteNoOpinion, frame_sp->GetFrameIndex()));

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

void SBThread::StepInstruction(bool step_over) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::StepInstruction (step_over=%i)",
                static_cast<void *>(exe_ctx.GetThreadPtr()), step_over);

  if (exe_ctx.HasThreadScope()) {
    Thread *thread = exe_ctx.GetThreadPtr();
    ThreadPlanSP new_plan_sp(
        thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

void SBThread::RunToAddress(lldb::addr_t addr) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
                static_cast<void *>(exe_ctx.GetThreadPtr()), addr);

  if (exe_ctx.HasThreadScope()) {
    bool abort_other_plans = false;
    bool stop_other_threads = true;

    Address target_addr(addr);

    Thread *thread = exe_ctx.GetThreadPtr();

    ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
        abort_other_plans, target_addr, stop_other_threads));

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}

SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
                                lldb::SBFileSpec &sb_file_spec, uint32_t line) {
  SBError sb_error;
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  char path[PATH_MAX];

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  StackFrameSP frame_sp(sb_frame.GetFrameSP());

  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    sb_file_spec->GetPath(path, sizeof(path));
    log->Printf("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, "
                "file+line = %s:%u)",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData(),
                path, line);
  }

  if (exe_ctx.HasThreadScope()) {
    Target *target = exe_ctx.GetTargetPtr();
    Thread *thread = exe_ctx.GetThreadPtr();

    if (line == 0) {
      sb_error.SetErrorString("invalid line argument");
      return sb_error;
    }

    if (!frame_sp) {
      frame_sp = thread->GetSelectedFrame();
      if (!frame_sp)
        frame_sp = thread->GetStackFrameAtIndex(0);
    }

    SymbolContext frame_sc;
    if (!frame_sp) {
      sb_error.SetErrorString("no valid frames in thread to step");
      return sb_error;
    }

    // If we have a frame, get its line
    frame_sc = frame_sp->GetSymbolContext(
        eSymbolContextCompUnit | eSymbolContextFunction |
        eSymbolContextLineEntry | eSymbolContextSymbol);

    if (frame_sc.comp_unit == NULL) {
      sb_error.SetErrorStringWithFormat(
          "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
      return sb_error;
    }

    FileSpec step_file_spec;
    if (sb_file_spec.IsValid()) {
      // The file spec passed in was valid, so use it
      step_file_spec = sb_file_spec.ref();
    } else {
      if (frame_sc.line_entry.IsValid())
        step_file_spec = frame_sc.line_entry.file;
      else {
        sb_error.SetErrorString("invalid file argument or no file for frame");
        return sb_error;
      }
    }

    // Grab the current function, then we will make sure the "until" address is
    // within the function.  We discard addresses that are out of the current
    // function, and then if there are no addresses remaining, give an
    // appropriate
    // error message.

    bool all_in_function = true;
    AddressRange fun_range = frame_sc.function->GetAddressRange();

    std::vector<addr_t> step_over_until_addrs;
    const bool abort_other_plans = false;
    const bool stop_other_threads = false;
    const bool check_inlines = true;
    const bool exact = false;

    SymbolContextList sc_list;
    const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext(
        step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry,
        sc_list);
    if (num_matches > 0) {
      SymbolContext sc;
      for (uint32_t i = 0; i < num_matches; ++i) {
        if (sc_list.GetContextAtIndex(i, sc)) {
          addr_t step_addr =
              sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
          if (step_addr != LLDB_INVALID_ADDRESS) {
            if (fun_range.ContainsLoadAddress(step_addr, target))
              step_over_until_addrs.push_back(step_addr);
            else
              all_in_function = false;
          }
        }
      }
    }

    if (step_over_until_addrs.empty()) {
      if (all_in_function) {
        step_file_spec.GetPath(path, sizeof(path));
        sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
                                          line);
      } else
        sb_error.SetErrorString("step until target not in current function");
    } else {
      ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
          abort_other_plans, &step_over_until_addrs[0],
          step_over_until_addrs.size(), stop_other_threads,
          frame_sp->GetFrameIndex()));

      sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
    }
  } else {
    sb_error.SetErrorString("this SBThread object is invalid");
  }
  return sb_error;
}

SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
  return StepUsingScriptedThreadPlan(script_class_name, true);
}

SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
                                              bool resume_immediately) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  SBError sb_error;

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log) {
    log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: class name: %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()), script_class_name);
  }

  if (!exe_ctx.HasThreadScope()) {
    sb_error.SetErrorString("this SBThread object is invalid");
    return sb_error;
  }

  Thread *thread = exe_ctx.GetThreadPtr();
  ThreadPlanSP thread_plan_sp =
      thread->QueueThreadPlanForStepScripted(false, script_class_name, false);

  if (!thread_plan_sp) {
    sb_error.SetErrorStringWithFormat(
        "Error queueing thread plan for class: %s", script_class_name);
    return sb_error;
  }

  if (!resume_immediately) {
    return sb_error;
  }

  if (thread_plan_sp)
    sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
  else {
    sb_error.SetErrorStringWithFormat(
        "Error resuming thread plan for class: %s.", script_class_name);
    if (log)
      log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing "
                  "thread plan for class: %s",
                  static_cast<void *>(exe_ctx.GetThreadPtr()),
                  script_class_name);
  }

  return sb_error;
}

SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  SBError sb_error;

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::JumpToLine (file+line = %s:%u)",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                file_spec->GetPath().c_str(), line);

  if (!exe_ctx.HasThreadScope()) {
    sb_error.SetErrorString("this SBThread object is invalid");
    return sb_error;
  }

  Thread *thread = exe_ctx.GetThreadPtr();

  Status err = thread->JumpToLine(file_spec.get(), line, true);
  sb_error.SetError(err);
  return sb_error;
}

SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
  SBError sb_error;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::ReturnFromFrame (frame=%d)",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                frame.GetFrameID());

  if (exe_ctx.HasThreadScope()) {
    Thread *thread = exe_ctx.GetThreadPtr();
    sb_error.SetError(
        thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
  }

  return sb_error;
}

SBError SBThread::UnwindInnermostExpression() {
  SBError sb_error;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::UnwindExpressionEvaluation",
                static_cast<void *>(exe_ctx.GetThreadPtr()));

  if (exe_ctx.HasThreadScope()) {
    Thread *thread = exe_ctx.GetThreadPtr();
    sb_error.SetError(thread->UnwindInnermostExpression());
    if (sb_error.Success())
      thread->SetSelectedFrameByIndex(0, false);
  }

  return sb_error;
}

bool SBThread::Suspend() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  bool result = false;
  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
      result = true;
    } else {
      if (log)
        log->Printf("SBThread(%p)::Suspend() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }
  if (log)
    log->Printf("SBThread(%p)::Suspend() => %i",
                static_cast<void *>(exe_ctx.GetThreadPtr()), result);
  return result;
}

bool SBThread::Resume() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  bool result = false;
  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      const bool override_suspend = true;
      exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
      result = true;
    } else {
      if (log)
        log->Printf("SBThread(%p)::Resume() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }
  if (log)
    log->Printf("SBThread(%p)::Resume() => %i",
                static_cast<void *>(exe_ctx.GetThreadPtr()), result);
  return result;
}

bool SBThread::IsSuspended() {
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope())
    return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
  return false;
}

bool SBThread::IsStopped() {
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope())
    return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
  return false;
}

SBProcess SBThread::GetProcess() {
  SBProcess sb_process;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    // Have to go up to the target so we can get a shared pointer to our
    // process...
    sb_process.SetSP(exe_ctx.GetProcessSP());
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream frame_desc_strm;
    sb_process.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::GetProcess () => SBProcess(%p): %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                static_cast<void *>(sb_process.GetSP().get()),
                frame_desc_strm.GetData());
  }

  return sb_process;
}

uint32_t SBThread::GetNumFrames() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  uint32_t num_frames = 0;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetNumFrames() => error: process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log)
    log->Printf("SBThread(%p)::GetNumFrames () => %u",
                static_cast<void *>(exe_ctx.GetThreadPtr()), num_frames);

  return num_frames;
}

SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBFrame sb_frame;
  StackFrameSP frame_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
      sb_frame.SetFrameSP(frame_sp);
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::GetFrameAtIndex() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
  }

  return sb_frame;
}

lldb::SBFrame SBThread::GetSelectedFrame() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBFrame sb_frame;
  StackFrameSP frame_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame();
      sb_frame.SetFrameSP(frame_sp);
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::GetSelectedFrame() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
  }

  return sb_frame;
}

lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBFrame sb_frame;
  StackFrameSP frame_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      Thread *thread = exe_ctx.GetThreadPtr();
      frame_sp = thread->GetStackFrameAtIndex(idx);
      if (frame_sp) {
        thread->SetSelectedFrame(frame_sp.get());
        sb_frame.SetFrameSP(frame_sp);
      }
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::SetSelectedFrame() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
  }
  return sb_frame;
}

bool SBThread::EventIsThreadEvent(const SBEvent &event) {
  return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL;
}

SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
  return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
}

SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
  return Thread::ThreadEventData::GetThreadFromEvent(event.get());
}

bool SBThread::operator==(const SBThread &rhs) const {
  return m_opaque_sp->GetThreadSP().get() ==
         rhs.m_opaque_sp->GetThreadSP().get();
}

bool SBThread::operator!=(const SBThread &rhs) const {
  return m_opaque_sp->GetThreadSP().get() !=
         rhs.m_opaque_sp->GetThreadSP().get();
}

bool SBThread::GetStatus(SBStream &status) const {
  Stream &strm = status.ref();

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
  } else
    strm.PutCString("No status");

  return true;
}

bool SBThread::GetDescription(SBStream &description) const {
    return GetDescription(description, false);
}

bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
  Stream &strm = description.ref();

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm,
                                                    LLDB_INVALID_THREAD_ID,
                                                    stop_format);
    // strm.Printf("SBThread: tid = 0x%4.4" PRIx64,
    // exe_ctx.GetThreadPtr()->GetID());
  } else
    strm.PutCString("No value");

  return true;
}

SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
  SBThread sb_origin_thread;

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      ThreadSP real_thread(exe_ctx.GetThreadSP());
      if (real_thread) {
        ConstString type_const(type);
        Process *process = exe_ctx.GetProcessPtr();
        if (process) {
          SystemRuntime *runtime = process->GetSystemRuntime();
          if (runtime) {
            ThreadSP new_thread_sp(
                runtime->GetExtendedBacktraceThread(real_thread, type_const));
            if (new_thread_sp) {
              // Save this in the Process' ExtendedThreadList so a strong
              // pointer retains the
              // object.
              process->GetExtendedThreadList().AddThread(new_thread_sp);
              sb_origin_thread.SetThread(new_thread_sp);
              if (log) {
                const char *queue_name = new_thread_sp->GetQueueName();
                if (queue_name == NULL)
                  queue_name = "";
                log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => new "
                            "extended Thread "
                            "created (%p) with queue_id 0x%" PRIx64
                            " queue name '%s'",
                            static_cast<void *>(exe_ctx.GetThreadPtr()),
                            static_cast<void *>(new_thread_sp.get()),
                            new_thread_sp->GetQueueID(), queue_name);
              }
            }
          }
        }
      }
    } else {
      if (log)
        log->Printf("SBThread(%p)::GetExtendedBacktraceThread() => error: "
                    "process is running",
                    static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log && sb_origin_thread.IsValid() == false)
    log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a "
                "Valid thread",
                static_cast<void *>(exe_ctx.GetThreadPtr()));
  return sb_origin_thread;
}

uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->GetExtendedBacktraceOriginatingIndexID();
  return LLDB_INVALID_INDEX32;
}

bool SBThread::SafeToCallFunctions() {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp->SafeToCallFunctions();
  return true;
}

lldb_private::Thread *SBThread::operator->() {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp.get();
  else
    return NULL;
}

lldb_private::Thread *SBThread::get() {
  ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
  if (thread_sp)
    return thread_sp.get();
  else
    return NULL;
}
