// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <object/thread_dispatcher.h>

#include <assert.h>
#include <err.h>
#include <inttypes.h>
#include <platform.h>
#include <string.h>
#include <trace.h>

#include <arch/debugger.h>
#include <arch/exception.h>

#include <kernel/thread.h>
#include <vm/kstack.h>
#include <vm/vm.h>
#include <vm/vm_address_region.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object_paged.h>

#include <zircon/rights.h>
#include <zircon/syscalls/debug.h>
#include <zircon/types.h>

#include <object/c_user_thread.h>
#include <object/excp_port.h>
#include <object/handle.h>
#include <object/process_dispatcher.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>

using fbl::AutoLock;

#define LOCAL_TRACE 0

// static
zx_status_t ThreadDispatcher::Create(fbl::RefPtr<ProcessDispatcher> process, uint32_t flags,
                                     fbl::StringPiece name,
                                     fbl::RefPtr<Dispatcher>* out_dispatcher,
                                     zx_rights_t* out_rights) {
    fbl::AllocChecker ac;
    auto disp = fbl::AdoptRef(new (&ac) ThreadDispatcher(fbl::move(process), flags));
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    auto result = disp->Initialize(name.data(), name.length());
    if (result != ZX_OK)
        return result;

    *out_rights = ZX_DEFAULT_THREAD_RIGHTS;
    *out_dispatcher = fbl::move(disp);
    return ZX_OK;
}

ThreadDispatcher::ThreadDispatcher(fbl::RefPtr<ProcessDispatcher> process,
                                   uint32_t flags)
    : process_(fbl::move(process)) {
    LTRACE_ENTRY_OBJ;
}

ThreadDispatcher::~ThreadDispatcher() {
    LTRACE_ENTRY_OBJ;

    DEBUG_ASSERT(&thread_ != get_current_thread());

    switch (state_) {
    case State::DEAD: {
        // join the LK thread before doing anything else to clean up LK state and ensure
        // the thread we're destroying has stopped.
        LTRACEF("joining LK thread to clean up state\n");
        __UNUSED auto ret = thread_join(&thread_, nullptr, ZX_TIME_INFINITE);
        LTRACEF("done joining LK thread\n");
        DEBUG_ASSERT_MSG(ret == ZX_OK, "thread_join returned something other than ZX_OK\n");
        break;
    }
    case State::INITIAL:
        // this gets a pass, we can destruct a partially constructed thread
        break;
    case State::INITIALIZED:
        // as we've been initialized previously, forget the LK thread.
        // note that thread_forget is not called for self since the thread is not running
        thread_forget(&thread_);
        break;
    default:
        DEBUG_ASSERT_MSG(false, "bad state %s, this %p\n", StateToString(state_), this);
    }

    // free the kernel stack
    vm_free_kstack(&kstack_mapping_, &kstack_vmar_);
#if __has_feature(safe_stack)
    vm_free_kstack(&unsafe_kstack_mapping_, &unsafe_kstack_vmar_);
#endif

    event_destroy(&exception_event_);
}

// complete initialization of the thread object outside of the constructor
zx_status_t ThreadDispatcher::Initialize(const char* name, size_t len) {
    LTRACE_ENTRY_OBJ;

    AutoLock lock(get_lock());

    DEBUG_ASSERT(state_ == State::INITIAL);

    // Make sure LK's max name length agrees with ours.
    static_assert(THREAD_NAME_LENGTH == ZX_MAX_NAME_LEN, "name length issue");
    if (len >= ZX_MAX_NAME_LEN)
        len = ZX_MAX_NAME_LEN - 1;

    char thread_name[THREAD_NAME_LENGTH];
    memcpy(thread_name, name, len);
    memset(thread_name + len, 0, ZX_MAX_NAME_LEN - len);

    // Map the kernel stack somewhere
    void* stack_top;
    auto status = vm_allocate_kstack(false, &stack_top, &kstack_mapping_, &kstack_vmar_);
    if (status != ZX_OK)
        return status;
#if __has_feature(safe_stack)
    status = vm_allocate_kstack(true, &stack_top,
                                &unsafe_kstack_mapping_, &unsafe_kstack_vmar_);
    if (status != ZX_OK)
        return status;
#endif

    // create an underlying LK thread
    thread_t* lkthread = thread_create_etc(
        &thread_, thread_name, StartRoutine, this, DEFAULT_PRIORITY,
        reinterpret_cast<void*>(kstack_mapping_->base()),
#if __has_feature(safe_stack)
        reinterpret_cast<void*>(unsafe_kstack_mapping_->base()),
#else
        nullptr,
#endif
        DEFAULT_STACK_SIZE, nullptr);

    if (!lkthread) {
        TRACEF("error creating thread\n");
        return ZX_ERR_NO_MEMORY;
    }
    DEBUG_ASSERT(lkthread == &thread_);

    // register an event handler with the LK kernel
    thread_set_user_callback(&thread_, &ThreadUserCallback);

    // set the per-thread pointer
    lkthread->user_thread = reinterpret_cast<void*>(this);

    // associate the proc's address space with this thread
    process_->aspace()->AttachToThread(lkthread);

    // we've entered the initialized state
    SetStateLocked(State::INITIALIZED);

    return ZX_OK;
}

zx_status_t ThreadDispatcher::set_name(const char* name, size_t len) {
    canary_.Assert();

    // ignore characters after the first NUL
    len = strnlen(name, len);

    if (len >= ZX_MAX_NAME_LEN)
        len = ZX_MAX_NAME_LEN - 1;

    AutoSpinLock lock(&name_lock_);
    memcpy(thread_.name, name, len);
    memset(thread_.name + len, 0, ZX_MAX_NAME_LEN - len);
    return ZX_OK;
}

void ThreadDispatcher::get_name(char out_name[ZX_MAX_NAME_LEN]) const {
    canary_.Assert();

    AutoSpinLock lock(&name_lock_);
    memset(out_name, 0, ZX_MAX_NAME_LEN);
    strlcpy(out_name, thread_.name, ZX_MAX_NAME_LEN);
}

// start a thread
zx_status_t ThreadDispatcher::Start(uintptr_t entry, uintptr_t sp,
                                    uintptr_t arg1, uintptr_t arg2,
                                    bool initial_thread) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    AutoLock lock(get_lock());

    if (state_ != State::INITIALIZED)
        return ZX_ERR_BAD_STATE;

    // save the user space entry state
    user_entry_ = entry;
    user_sp_ = sp;
    user_arg1_ = arg1;
    user_arg2_ = arg2;

    // add ourselves to the process, which may fail if the process is in a dead state
    auto ret = process_->AddThread(this, initial_thread);
    if (ret < 0)
        return ret;

    // bump the ref on this object that the LK thread state will now own until the lk thread has exited
    AddRef();

    // mark ourselves as running and resume the kernel thread
    SetStateLocked(State::RUNNING);

    thread_.user_tid = get_koid();
    thread_.user_pid = process_->get_koid();
    thread_resume(&thread_);

    return ZX_OK;
}

// called in the context of our thread
void ThreadDispatcher::Exit() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    // only valid to call this on the current thread
    DEBUG_ASSERT(get_current_thread() == &thread_);

    {
        AutoLock lock(get_lock());

        DEBUG_ASSERT(state_ == State::RUNNING || state_ == State::DYING);

        SetStateLocked(State::DYING);
    }

    // exit here
    // this will recurse back to us in ::Exiting()
    thread_exit(0);

    __UNREACHABLE;
}

void ThreadDispatcher::Kill() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    AutoLock lock(get_lock());

    switch (state_) {
    case State::INITIAL:
    case State::INITIALIZED:
        // thread was never started, leave in this state
        break;
    case State::RUNNING:
    case State::SUSPENDED:
        // deliver a kernel kill signal to the thread
        thread_kill(&thread_);

        // enter the dying state
        SetStateLocked(State::DYING);
        break;
    case State::DYING:
    case State::DEAD:
        // already going down
        break;
    }
}

zx_status_t ThreadDispatcher::Suspend() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    AutoLock lock(get_lock());

    LTRACEF("%p: state %s\n", this, StateToString(state_));

    if (state_ != State::RUNNING && state_ != State::SUSPENDED)
        return ZX_ERR_BAD_STATE;

    DEBUG_ASSERT(suspend_count_ >= 0);
    suspend_count_++;
    if (suspend_count_ == 1)
        return thread_suspend(&thread_);

    // It was already suspended.
    return ZX_OK;
}

zx_status_t ThreadDispatcher::Resume() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    AutoLock lock(get_lock());

    LTRACEF("%p: state %s\n", this, StateToString(state_));

    // TODO(brettw) ZX-1072 :The suspend_count_ == 0 check can be removed and converted to an
    // assertion when the bug is fixed. In that case, the suspend token shouldn't be calling Resume
    // unless it's previously suspended it. Currently callers can bypass this invariant using the
    // legacy suspend/resume API so give a good error.
    // DEBUG_ASSERT(suspend_count_ > 0)
    if ((state_ != State::RUNNING && state_ != State::SUSPENDED) || suspend_count_ == 0)
        return ZX_ERR_BAD_STATE;

    suspend_count_--;
    if (suspend_count_ == 0)
        thread_resume(&thread_);
    // Otherwise there's still an out-standing Suspend() call so keep it suspended.
    return ZX_OK;
}

static void ThreadCleanupDpc(dpc_t* d) {
    LTRACEF("dpc %p\n", d);

    ThreadDispatcher* t = reinterpret_cast<ThreadDispatcher*>(d->arg);
    DEBUG_ASSERT(t);

    delete t;
}

void ThreadDispatcher::Exiting() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    // Notify a debugger if attached. Do this before marking the thread as
    // dead: the debugger expects to see the thread in the DYING state, it may
    // try to read thread registers. The debugger still has to handle the case
    // where the process is also dying (and thus the thread could transition
    // DYING->DEAD from underneath it), but that's life (or death :-)).
    // N.B. OnThreadExitForDebugger will block in ExceptionHandlerExchange, so
    // don't hold the process's |state_lock_| across the call.
    {
        fbl::RefPtr<ExceptionPort> eport(process_->debugger_exception_port());
        if (eport) {
            eport->OnThreadExitForDebugger(this);
        }
    }

    // Mark the thread as dead. Do this before removing the thread from the
    // process because if this is the last thread then the process will be
    // marked dead, and we don't want to have a state where the process is
    // dead but one thread is not.
    {
        AutoLock lock(get_lock());

        DEBUG_ASSERT(state_ == State::DYING);

        // put ourselves into the dead state
        SetStateLocked(State::DEAD);
    }

    // remove ourselves from our parent process's view
    process_->RemoveThread(this);

    // drop LK's reference
    if (Release()) {
        // We're the last reference, so will need to destruct ourself while running, which is not possible
        // Use a dpc to pull this off
        cleanup_dpc_.func = ThreadCleanupDpc;
        cleanup_dpc_.arg = this;

        // disable interrupts before queuing the dpc to prevent starving the DPC thread if it starts running
        // before we're completed.
        // disabling interrupts effectively raises us to maximum priority on this cpu.
        // note this is only safe because we're about to exit the thread permanently so the context
        // switch will effectively reenable interrupts in the new thread.
        arch_disable_ints();

        // queue without reschdule since us exiting is a reschedule event already
        dpc_queue(&cleanup_dpc_, false);
    }

    // after this point the thread will stop permanently
    LTRACE_EXIT_OBJ;
}

void ThreadDispatcher::Suspending() {
    LTRACE_ENTRY_OBJ;

    // Update the state before sending any notifications out. We want the
    // receiver to see the new state.
    {
        AutoLock lock(get_lock());

        DEBUG_ASSERT(state_ == State::RUNNING || state_ == State::DYING);
        if (state_ == State::RUNNING) {
            SetStateLocked(State::SUSPENDED);
        }
    }

    LTRACE_EXIT_OBJ;
}

void ThreadDispatcher::Resuming() {
    LTRACE_ENTRY_OBJ;

    // Update the state before sending any notifications out. We want the
    // receiver to see the new state.
    {
        AutoLock lock(get_lock());

        DEBUG_ASSERT(state_ == State::SUSPENDED || state_ == State::DYING);
        if (state_ == State::SUSPENDED) {
            SetStateLocked(State::RUNNING);
        }
    }

    LTRACE_EXIT_OBJ;
}

// low level LK callback in thread's context just before exiting
void ThreadDispatcher::ThreadUserCallback(enum thread_user_state_change new_state, void* arg) {
    ThreadDispatcher* t = reinterpret_cast<ThreadDispatcher*>(arg);

    switch (new_state) {
    case THREAD_USER_STATE_EXIT:
        t->Exiting();
        return;
    case THREAD_USER_STATE_SUSPEND:
        t->Suspending();
        return;
    case THREAD_USER_STATE_RESUME:
        t->Resuming();
        return;
    }
}

// low level LK entry point for the thread
int ThreadDispatcher::StartRoutine(void* arg) {
    LTRACE_ENTRY;

    ThreadDispatcher* t = (ThreadDispatcher*)arg;

    // Notify debugger if attached.
    // This is done by first obtaining our own reference to the port so the
    // test can be done safely. Note that this function doesn't return so we
    // need the reference to go out of scope before then.
    {
        fbl::RefPtr<ExceptionPort> debugger_port(t->process_->debugger_exception_port());
        if (debugger_port) {
            debugger_port->OnThreadStartForDebugger(t);
        }
    }

    LTRACEF("arch_enter_uspace SP: %#" PRIxPTR " PC: %#" PRIxPTR
            ", ARG1: %#" PRIxPTR ", ARG2: %#" PRIxPTR "\n",
            t->user_sp_, t->user_entry_, t->user_arg1_, t->user_arg2_);

    // switch to user mode and start the process
    arch_enter_uspace(t->user_entry_, t->user_sp_,
                      t->user_arg1_, t->user_arg2_);

    __UNREACHABLE;
}

void ThreadDispatcher::SetStateLocked(State state) {
    canary_.Assert();

    LTRACEF("thread %p: state %u (%s)\n", this, static_cast<unsigned int>(state), StateToString(state));

    DEBUG_ASSERT(get_lock()->IsHeld());

    state_ = state;

    switch (state) {
    case State::RUNNING:
        UpdateStateLocked(ZX_THREAD_SUSPENDED, ZX_THREAD_RUNNING);
        break;
    case State::SUSPENDED:
        UpdateStateLocked(ZX_THREAD_RUNNING, ZX_THREAD_SUSPENDED);
        break;
    case State::DEAD:
        UpdateStateLocked(ZX_THREAD_RUNNING | ZX_THREAD_SUSPENDED, ZX_THREAD_TERMINATED);
        break;
    default:
        // Nothing to do.
        // In particular, for the DYING state we don't modify the SUSPENDED
        // or RUNNING signals: For observer purposes they'll only be interested
        // in the transition from {SUSPENDED,RUNNING} to DEAD.
        break;
    }
}

zx_status_t ThreadDispatcher::SetExceptionPort(fbl::RefPtr<ExceptionPort> eport) {
    canary_.Assert();

    DEBUG_ASSERT(eport->type() == ExceptionPort::Type::THREAD);

    // Lock |state_lock_| to ensure the thread doesn't transition to dead
    // while we're setting the exception handler.
    AutoLock state_lock(get_lock());
    if (state_ == State::DEAD)
        return ZX_ERR_NOT_FOUND;
    if (exception_port_)
        return ZX_ERR_BAD_STATE;
    exception_port_ = eport;

    return ZX_OK;
}

bool ThreadDispatcher::ResetExceptionPort(bool quietly) {
    canary_.Assert();

    fbl::RefPtr<ExceptionPort> eport;

    // Remove the exception handler first. If the thread resumes execution
    // we don't want it to hit another exception and get back into
    // ExceptionHandlerExchange.
    {
        AutoLock lock(get_lock());
        exception_port_.swap(eport);
        if (eport == nullptr) {
            // Attempted to unbind when no exception port is bound.
            return false;
        }
        // This method must guarantee that no caller will return until
        // OnTargetUnbind has been called on the port-to-unbind.
        // This becomes important when a manual unbind races with a
        // PortDispatcher::on_zero_handles auto-unbind.
        //
        // If OnTargetUnbind were called outside of the lock, it would lead to
        // a race (for threads A and B):
        //
        //   A: Calls ResetExceptionPort; acquires the lock
        //   A: Sees a non-null exception_port_, swaps it into the eport local.
        //      exception_port_ is now null.
        //   A: Releases the lock
        //
        //   B: Calls ResetExceptionPort; acquires the lock
        //   B: Sees a null exception_port_ and returns. But OnTargetUnbind()
        //      hasn't yet been called for the port.
        //
        // So, call it before releasing the lock
        eport->OnTargetUnbind();
    }

    if (!quietly)
        OnExceptionPortRemoval(eport);
    return true;
}

fbl::RefPtr<ExceptionPort> ThreadDispatcher::exception_port() {
    canary_.Assert();

    AutoLock lock(get_lock());
    return exception_port_;
}

zx_status_t ThreadDispatcher::ExceptionHandlerExchange(
    fbl::RefPtr<ExceptionPort> eport,
    const zx_exception_report_t* report,
    const arch_exception_context_t* arch_context,
    ExceptionStatus* out_estatus) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    // Note: As far as userspace is concerned there is no state change that we would notify state
    // tracker observers of, currently.
    //
    // Send message, wait for reply. Note that there is a "race" that we need handle: We need to
    // send the exception report before going to sleep, but what if the receiver of the report gets
    // it and processes it before we are asleep? This is handled by locking state_lock_ in places
    // where the handler can see/modify thread state.

    {
        AutoLock lock(get_lock());

        // Mark that we're in an exception.
        thread_.exception_context = arch_context;

        // For GetExceptionReport.
        exception_report_ = report;

        // For OnExceptionPortRemoval in case the port is unbound.
        DEBUG_ASSERT(exception_wait_port_ == nullptr);
        exception_wait_port_ = eport;

        exception_status_ = ExceptionStatus::UNPROCESSED;
    }

    // There's no need to send the message under the lock, but we do need to
    // make sure our exception state is up to date before sending the message:
    // Otherwise a debugger could get the packet and observe our state before
    // we've updated it. Thus send the packet after updating our state.
    zx_status_t status = eport->SendPacket(this, report->header.type);
    if (status != ZX_OK) {
        // Can't send the request to the exception handler. Report the error, which will probably
        // kill the process.
        LTRACEF("SendPacket returned %d\n", status);
        return status;
    }

    // Continue to wait for the exception response if we get suspended.
    // If it is suspended, the suspension will be processed after the
    // exception response is received (requiring a second resume).
    // Exceptions and suspensions are essentially treated orthogonally.

    {
        AutoBlocked by(Blocked::EXCEPTION);

        do {
            status = event_wait_with_mask(&exception_event_, THREAD_SIGNAL_SUSPEND);
        } while (status == ZX_ERR_INTERNAL_INTR_RETRY);
    }

    AutoLock lock(get_lock());

    // Note: If |status| != ZX_OK, then |exception_status_| is still
    // ExceptionStatus::UNPROCESSED.
    switch (status) {
    case ZX_OK:
        // It's critical that at this point the event no longer be armed.
        // Otherwise the next time we get an exception we'll fall right through
        // without waiting for an exception response.
        // Note: The event could be signaled after event_wait_deadline returns
        // if the thread was killed while the event was signaled.
        DEBUG_ASSERT(!event_signaled(&exception_event_));
        DEBUG_ASSERT(exception_status_ != ExceptionStatus::IDLE &&
                     exception_status_ != ExceptionStatus::UNPROCESSED);
        break;
    case ZX_ERR_INTERNAL_INTR_KILLED:
        // Thread was killed.
        break;
    default:
        ASSERT_MSG(false, "unexpected exception result: %d\n", status);
        __UNREACHABLE;
    }

    exception_wait_port_.reset();
    exception_report_ = nullptr;
    thread_.exception_context = nullptr;

    *out_estatus = exception_status_;
    exception_status_ = ExceptionStatus::IDLE;

    LTRACEF("returning status %d, estatus %d\n",
            status, static_cast<int>(*out_estatus));
    return status;
}

// TODO(brettw) ZX-1072 Remove this when all callers are updated to use
// the exception port variant below.
zx_status_t ThreadDispatcher::MarkExceptionHandled(ExceptionStatus estatus) {
    canary_.Assert();

    LTRACEF("obj %p, estatus %d\n", this, static_cast<int>(estatus));
    DEBUG_ASSERT(estatus != ExceptionStatus::IDLE &&
                 estatus != ExceptionStatus::UNPROCESSED);

    AutoLock lock(get_lock());
    if (!InExceptionLocked())
        return ZX_ERR_BAD_STATE;

    // The thread can be in several states at this point. Alas this is a bit
    // complicated because there is a window in the middle of
    // ExceptionHandlerExchange between the thread going to sleep and after
    // the thread waking up where we can obtain the lock. Things are further
    // complicated by the fact that OnExceptionPortRemoval could get there
    // first, or we might get called a second time for the same exception.
    // It's critical that we don't re-arm the event after the thread wakes up.
    // To keep things simple we take a first-one-wins approach.
    DEBUG_ASSERT(exception_status_ != ExceptionStatus::IDLE);
    if (exception_status_ != ExceptionStatus::UNPROCESSED)
        return ZX_ERR_BAD_STATE;

    exception_status_ = estatus;
    event_signal(&exception_event_, true);
    return ZX_OK;
}

zx_status_t ThreadDispatcher::MarkExceptionHandled(PortDispatcher* eport,
                                                   ExceptionStatus estatus) {
    canary_.Assert();

    LTRACEF("obj %p, estatus %d\n", this, static_cast<int>(estatus));
    DEBUG_ASSERT(estatus != ExceptionStatus::IDLE &&
                 estatus != ExceptionStatus::UNPROCESSED);

    AutoLock lock(get_lock());
    if (!InExceptionLocked())
        return ZX_ERR_BAD_STATE;

    // The exception port isn't used directly but is instead proof that the caller has permission to
    // resume from the exception. So validate that it corresponds to the task being resumed.
    if (!exception_wait_port_->PortMatches(eport, false))
        return ZX_ERR_ACCESS_DENIED;

    // The thread can be in several states at this point. Alas this is a bit complicated because
    // there is a window in the middle of ExceptionHandlerExchange between the thread going to sleep
    // and after the thread waking up where we can obtain the lock. Things are further complicated
    // by the fact that OnExceptionPortRemoval could get there first, or we might get called a
    // second time for the same exception. It's critical that we don't re-arm the event after the
    // thread wakes up. To keep things simple we take a first-one-wins approach.
    DEBUG_ASSERT(exception_status_ != ExceptionStatus::IDLE);
    if (exception_status_ != ExceptionStatus::UNPROCESSED)
        return ZX_ERR_BAD_STATE;

    exception_status_ = estatus;
    event_signal(&exception_event_, true);
    return ZX_OK;
}

void ThreadDispatcher::OnExceptionPortRemoval(const fbl::RefPtr<ExceptionPort>& eport) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;
    AutoLock lock(get_lock());
    if (!InExceptionLocked())
        return;
    DEBUG_ASSERT(exception_status_ != ExceptionStatus::IDLE);
    if (exception_wait_port_ == eport) {
        // Leave things alone if already processed. See MarkExceptionHandled.
        if (exception_status_ == ExceptionStatus::UNPROCESSED) {
            exception_status_ = ExceptionStatus::TRY_NEXT;
            event_signal(&exception_event_, true);
        }
    }
}

bool ThreadDispatcher::InExceptionLocked() {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;
    DEBUG_ASSERT(get_lock()->IsHeld());
    return thread_stopped_in_exception(&thread_);
}

zx_status_t ThreadDispatcher::GetInfoForUserspace(zx_info_thread_t* info) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    *info = {};

    State state;
    Blocked blocked_reason;
    ExceptionPort::Type excp_port_type;
    // We need to fetch all these values under lock, but once we have them
    // we no longer need the lock.
    {
        AutoLock state_lock(get_lock());
        state = state_;
        blocked_reason = blocked_reason_;
        if (InExceptionLocked() &&
            // A port type of !NONE here indicates to the caller that the
            // thread is waiting for an exception response. So don't return
            // !NONE if the thread just woke up but hasn't reacquired
            // |state_lock_|.
            exception_status_ == ExceptionStatus::UNPROCESSED) {
            DEBUG_ASSERT(exception_wait_port_ != nullptr);
            excp_port_type = exception_wait_port_->type();
        } else {
            // Either we're not in an exception, or we're in the window where
            // event_wait_deadline has woken up but |state_lock_| has
            // not been reacquired.
            DEBUG_ASSERT(exception_wait_port_ == nullptr ||
                         exception_status_ != ExceptionStatus::UNPROCESSED);
            excp_port_type = ExceptionPort::Type::NONE;
        }
    }

    switch (state) {
    case ThreadDispatcher::State::INITIAL:
    case ThreadDispatcher::State::INITIALIZED:
        info->state = ZX_THREAD_STATE_NEW;
        break;
    case ThreadDispatcher::State::RUNNING:
        // The thread may be "running" but be blocked in a syscall or
        // exception handler.
        switch (blocked_reason) {
        case Blocked::NONE:
            info->state = ZX_THREAD_STATE_RUNNING;
            break;
        case Blocked::EXCEPTION:
            info->state = ZX_THREAD_STATE_BLOCKED_EXCEPTION;
            break;
        case Blocked::SLEEPING:
            info->state = ZX_THREAD_STATE_BLOCKED_SLEEPING;
            break;
        case Blocked::FUTEX:
            info->state = ZX_THREAD_STATE_BLOCKED_FUTEX;
            break;
        case Blocked::PORT:
            info->state = ZX_THREAD_STATE_BLOCKED_PORT;
            break;
        case Blocked::CHANNEL:
            info->state = ZX_THREAD_STATE_BLOCKED_CHANNEL;
            break;
        case Blocked::WAIT_ONE:
            info->state = ZX_THREAD_STATE_BLOCKED_WAIT_ONE;
            break;
        case Blocked::WAIT_MANY:
            info->state = ZX_THREAD_STATE_BLOCKED_WAIT_MANY;
            break;
        case Blocked::INTERRUPT:
            info->state = ZX_THREAD_STATE_BLOCKED_INTERRUPT;
            break;
        default:
            DEBUG_ASSERT_MSG(false, "unexpected blocked reason: %d",
                             static_cast<int>(blocked_reason));
            break;
        }
        break;
    case ThreadDispatcher::State::SUSPENDED:
        info->state = ZX_THREAD_STATE_SUSPENDED;
        break;
    case ThreadDispatcher::State::DYING:
        info->state = ZX_THREAD_STATE_DYING;
        break;
    case ThreadDispatcher::State::DEAD:
        info->state = ZX_THREAD_STATE_DEAD;
        break;
    default:
        DEBUG_ASSERT_MSG(false, "unexpected run state: %d",
                         static_cast<int>(state));
        break;
    }

    switch (excp_port_type) {
    case ExceptionPort::Type::NONE:
        info->wait_exception_port_type = ZX_EXCEPTION_PORT_TYPE_NONE;
        break;
    case ExceptionPort::Type::DEBUGGER:
        info->wait_exception_port_type = ZX_EXCEPTION_PORT_TYPE_DEBUGGER;
        break;
    case ExceptionPort::Type::THREAD:
        info->wait_exception_port_type = ZX_EXCEPTION_PORT_TYPE_THREAD;
        break;
    case ExceptionPort::Type::PROCESS:
        info->wait_exception_port_type = ZX_EXCEPTION_PORT_TYPE_PROCESS;
        break;
    case ExceptionPort::Type::JOB:
        info->wait_exception_port_type = ZX_EXCEPTION_PORT_TYPE_JOB;
        break;
    default:
        DEBUG_ASSERT_MSG(false, "unexpected exception port type: %d",
                         static_cast<int>(excp_port_type));
        break;
    }

    return ZX_OK;
}

zx_status_t ThreadDispatcher::GetStatsForUserspace(zx_info_thread_stats_t* info) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    *info = {};

    info->total_runtime = runtime_ns();
    return ZX_OK;
}

zx_status_t ThreadDispatcher::GetExceptionReport(zx_exception_report_t* report) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;
    AutoLock lock(get_lock());
    if (!InExceptionLocked())
        return ZX_ERR_BAD_STATE;
    DEBUG_ASSERT(exception_report_ != nullptr);
    *report = *exception_report_;
    return ZX_OK;
}

// Note: buffer must be sufficiently aligned

zx_status_t ThreadDispatcher::ReadState(zx_thread_state_topic_t state_kind,
                                        void* buffer, size_t buffer_len) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    // We can't be reading regs while the thread transitions from
    // SUSPENDED to RUNNING.
    AutoLock state_lock(get_lock());

    if (state_ != State::SUSPENDED && !InExceptionLocked())
        return ZX_ERR_BAD_STATE;

    switch (state_kind) {
    case ZX_THREAD_STATE_GENERAL_REGS: {
        if (buffer_len != sizeof(zx_thread_state_general_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_get_general_regs(
            &thread_, static_cast<zx_thread_state_general_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_FP_REGS: {
        if (buffer_len != sizeof(zx_thread_state_fp_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_get_fp_regs(
            &thread_, static_cast<zx_thread_state_fp_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_VECTOR_REGS: {
        if (buffer_len != sizeof(zx_thread_state_vector_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_get_vector_regs(
            &thread_, static_cast<zx_thread_state_vector_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_SINGLE_STEP: {
        if (buffer_len != sizeof(zx_thread_state_single_step_t))
            return ZX_ERR_INVALID_ARGS;
        bool single_step;
        zx_status_t status = arch_get_single_step(&thread_, &single_step);
        if (status != ZX_OK)
            return status;
        *static_cast<zx_thread_state_single_step_t*>(buffer) =
            static_cast<zx_thread_state_single_step_t>(single_step);
        return ZX_OK;
    }
    default:
        return ZX_ERR_INVALID_ARGS;
    }
}

// Note: buffer must be sufficiently aligned

zx_status_t ThreadDispatcher::WriteState(zx_thread_state_topic_t state_kind,
                                         const void* buffer, size_t buffer_len) {
    canary_.Assert();

    LTRACE_ENTRY_OBJ;

    // We can't be reading regs while the thread transitions from
    // SUSPENDED to RUNNING.
    AutoLock state_lock(get_lock());

    if (state_ != State::SUSPENDED && !InExceptionLocked())
        return ZX_ERR_BAD_STATE;

    switch (state_kind) {
    case ZX_THREAD_STATE_GENERAL_REGS: {
        if (buffer_len != sizeof(zx_thread_state_general_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_set_general_regs(&thread_,
                                     static_cast<const zx_thread_state_general_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_FP_REGS: {
        if (buffer_len != sizeof(zx_thread_state_fp_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_set_fp_regs(&thread_,
                                static_cast<const zx_thread_state_fp_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_VECTOR_REGS: {
        if (buffer_len != sizeof(zx_thread_state_vector_regs_t))
            return ZX_ERR_INVALID_ARGS;
        return arch_set_vector_regs(&thread_,
                                    static_cast<const zx_thread_state_vector_regs_t*>(buffer));
    }
    case ZX_THREAD_STATE_SINGLE_STEP: {
        if (buffer_len != sizeof(zx_thread_state_single_step_t))
            return ZX_ERR_INVALID_ARGS;
        const zx_thread_state_single_step_t* single_step =
            static_cast<const zx_thread_state_single_step_t*>(buffer);
        if (*single_step != 0 && *single_step != 1)
            return ZX_ERR_INVALID_ARGS;
        return arch_set_single_step(&thread_, !!*single_step);
    }
    default:
        return ZX_ERR_INVALID_ARGS;
    }
}

zx_status_t ThreadDispatcher::SetPriority(int32_t priority) {
    AutoLock state_lock(get_lock());
    if ((state_ == State::INITIAL) ||
        (state_ == State::DYING) ||
        (state_ == State::DEAD)) {
        return ZX_ERR_BAD_STATE;
    }
    // The priority was already validated by the Profile dispatcher.
    thread_set_priority(&thread_, priority);
    return ZX_OK;
}

void get_user_thread_process_name(const void* user_thread,
                                  char out_name[ZX_MAX_NAME_LEN]) {
    const ThreadDispatcher* ut =
        reinterpret_cast<const ThreadDispatcher*>(user_thread);
    ut->process()->get_name(out_name);
}

const char* StateToString(ThreadDispatcher::State state) {
    switch (state) {
    case ThreadDispatcher::State::INITIAL:
        return "initial";
    case ThreadDispatcher::State::INITIALIZED:
        return "initialized";
    case ThreadDispatcher::State::RUNNING:
        return "running";
    case ThreadDispatcher::State::SUSPENDED:
        return "suspended";
    case ThreadDispatcher::State::DYING:
        return "dying";
    case ThreadDispatcher::State::DEAD:
        return "dead";
    }
    return "unknown";
}

zx_koid_t ThreadDispatcher::get_related_koid() const {
    canary_.Assert();

    return process_->get_koid();
}
