//===-- 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/SBSymbolContext.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Target/ThreadPlanStepInRange.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/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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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
{
    return m_opaque_sp->GetThreadSP().get() != NULL;
}

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


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

    StopReason reason = eStopReasonInvalid;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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 ()
{
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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)
{
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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();
    
    ExecutionContext exe_ctx (m_opaque_sp.get());
    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;
}

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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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",
                     static_cast<void*>(exe_ctx.GetThreadPtr()),
                     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));

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);


    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.range,
                                                                    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)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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 ())
        {
            const LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate;
            const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate;
            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
            new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
                                                              sc.line_entry.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);
        }

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

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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);



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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);


    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];

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    SBError sb_error;

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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 = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
    else
    {
        sb_error.SetErrorStringWithFormat("Error queuing 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;

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

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

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

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);


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


bool
SBThread::Suspend()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    ExecutionContext exe_ctx (m_opaque_sp.get());
    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));
    ExecutionContext exe_ctx (m_opaque_sp.get());
    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()
{
    ExecutionContext exe_ctx (m_opaque_sp.get());
    if (exe_ctx.HasThreadScope())
        return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended;
    return false;
}

bool
SBThread::IsStopped()
{
    ExecutionContext exe_ctx (m_opaque_sp.get());
    if (exe_ctx.HasThreadScope())
        return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
    return false;
}

SBProcess
SBThread::GetProcess ()
{
    SBProcess sb_process;
    ExecutionContext exe_ctx (m_opaque_sp.get());
    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    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;
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

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

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

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

    ExecutionContext exe_ctx (m_opaque_sp.get());
    if (exe_ctx.HasThreadScope())
    {
        exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm, LLDB_INVALID_THREAD_ID);
        //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));
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
    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;
}

