// 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/process_dispatcher.h>

#include <assert.h>
#include <inttypes.h>
#include <list.h>
#include <rand.h>
#include <string.h>
#include <trace.h>

#include <arch/defines.h>

#include <kernel/thread.h>
#include <vm/vm.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object.h>

#include <lib/crypto/global_prng.h>
#include <lib/ktrace.h>

#include <zircon/rights.h>

#include <object/diagnostics.h>
#include <object/futex_context.h>
#include <object/handle.h>
#include <object/job_dispatcher.h>
#include <object/thread_dispatcher.h>
#include <object/vm_address_region_dispatcher.h>
#include <object/vm_object_dispatcher.h>

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

#define LOCAL_TRACE 0

static zx_handle_t map_handle_to_value(const Handle* handle, uint32_t mixer) {
    // Ensure that the last bit of the result is not zero, and make sure
    // we don't lose any base_value bits or make the result negative
    // when shifting.
    DEBUG_ASSERT((mixer & ((1<<31) | 0x1)) == 0);
    DEBUG_ASSERT((handle->base_value() & 0xc0000000) == 0);

    auto handle_id = (handle->base_value() << 1) | 0x1;
    return static_cast<zx_handle_t>(mixer ^ handle_id);
}

static Handle* map_value_to_handle(zx_handle_t value, uint32_t mixer) {
    auto handle_id = (static_cast<uint32_t>(value) ^ mixer) >> 1;
    return Handle::FromU32(handle_id);
}

zx_status_t ProcessDispatcher::Create(
    fbl::RefPtr<JobDispatcher> job, fbl::StringPiece name, uint32_t flags,
    fbl::RefPtr<Dispatcher>* dispatcher, zx_rights_t* rights,
    fbl::RefPtr<VmAddressRegionDispatcher>* root_vmar_disp,
    zx_rights_t* root_vmar_rights) {
    fbl::AllocChecker ac;
    fbl::RefPtr<ProcessDispatcher> process =
        fbl::AdoptRef(new (&ac) ProcessDispatcher(job, name, flags));
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;

    if (!job->AddChildProcess(process))
        return ZX_ERR_BAD_STATE;

    zx_status_t result = process->Initialize();
    if (result != ZX_OK)
        return result;

    fbl::RefPtr<VmAddressRegion> vmar(process->aspace()->RootVmar());

    // Create a dispatcher for the root VMAR.
    fbl::RefPtr<Dispatcher> new_vmar_dispatcher;
    result = VmAddressRegionDispatcher::Create(vmar, ARCH_MMU_FLAG_PERM_USER,
                                               &new_vmar_dispatcher,
                                               root_vmar_rights);
    if (result != ZX_OK) {
        process->aspace_->Destroy();
        return result;
    }

    *rights = ZX_DEFAULT_PROCESS_RIGHTS;
    *dispatcher = fbl::move(process);
    *root_vmar_disp = DownCastDispatcher<VmAddressRegionDispatcher>(
            &new_vmar_dispatcher);

    return ZX_OK;
}

ProcessDispatcher::ProcessDispatcher(fbl::RefPtr<JobDispatcher> job,
                                     fbl::StringPiece name,
                                     uint32_t flags)
  : job_(fbl::move(job)), policy_(job_->GetPolicy()),
    name_(name.data(), name.length()) {
    LTRACE_ENTRY_OBJ;

    // Generate handle XOR mask with top bit and bottom two bits cleared
    uint32_t secret;
    auto prng = crypto::GlobalPRNG::GetInstance();
    prng->Draw(&secret, sizeof(secret));

    // Handle values cannot be negative values, so we mask the high bit.
    handle_rand_ = (secret << 2) & INT_MAX;
}

ProcessDispatcher::~ProcessDispatcher() {
    LTRACE_ENTRY_OBJ;

    DEBUG_ASSERT(state_ == State::INITIAL || state_ == State::DEAD);

    // Assert that the -> DEAD transition cleaned up what it should have.
    DEBUG_ASSERT(handles_.is_empty());
    DEBUG_ASSERT(exception_port_ == nullptr);
    DEBUG_ASSERT(debugger_exception_port_ == nullptr);

    // Remove ourselves from the parent job's raw ref to us. Note that this might
    // have beeen called when transitioning State::DEAD. The Job can handle double calls.
    job_->RemoveChildProcess(this);

    LTRACE_EXIT_OBJ;
}

void ProcessDispatcher::on_zero_handles() {
    // If the process is in the initial state and the last handle is closed
    // we never detach from the parent job, so run the shutdown sequence for
    // that case.
    {
        Guard<fbl::Mutex> guard{get_lock()};
        if (state_ != State::INITIAL) {
            // Use the normal cleanup path instead.
            return;
        }
        SetStateLocked(State::DEAD);
    }

    FinishDeadTransition();
}

void ProcessDispatcher::get_name(char out_name[ZX_MAX_NAME_LEN]) const {
    name_.get(ZX_MAX_NAME_LEN, out_name);
}

zx_status_t ProcessDispatcher::set_name(const char* name, size_t len) {
    return name_.set(name, len);
}

zx_status_t ProcessDispatcher::Initialize() {
    LTRACE_ENTRY_OBJ;

    Guard<fbl::Mutex> guard{get_lock()};

    DEBUG_ASSERT(state_ == State::INITIAL);

    // create an address space for this process, named after the process's koid.
    char aspace_name[ZX_MAX_NAME_LEN];
    snprintf(aspace_name, sizeof(aspace_name), "proc:%" PRIu64, get_koid());
    aspace_ = VmAspace::Create(VmAspace::TYPE_USER, aspace_name);
    if (!aspace_) {
        TRACEF("error creating address space\n");
        return ZX_ERR_NO_MEMORY;
    }

    return ZX_OK;
}

void ProcessDispatcher::Exit(int64_t retcode) {
    LTRACE_ENTRY_OBJ;

    DEBUG_ASSERT(ProcessDispatcher::GetCurrent() == this);

    {
        Guard<fbl::Mutex> guard{get_lock()};

        // check that we're in the RUNNING state or we're racing with something
        // else that has already pushed us until the DYING state
        DEBUG_ASSERT_MSG(state_ == State::RUNNING || state_ == State::DYING,
                "state is %s", StateToString(state_));

        // Set the exit status if there isn't already an exit in progress.
        if (state_ != State::DYING) {
            DEBUG_ASSERT(retcode_ == 0);
            retcode_ = retcode;
        }

        // enter the dying state, which should kill all threads
        SetStateLocked(State::DYING);
    }

    ThreadDispatcher::GetCurrent()->Exit();

    __UNREACHABLE;
}

void ProcessDispatcher::Kill() {
    LTRACE_ENTRY_OBJ;

    // ZX-880: Call RemoveChildProcess outside of |get_lock()|.
    bool became_dead = false;

    {
        Guard<fbl::Mutex> guard{get_lock()};

        // we're already dead
        if (state_ == State::DEAD)
            return;

        if (state_ != State::DYING) {
            // If there isn't an Exit already in progress, set a nonzero exit
            // status so e.g. crashing tests don't appear to have succeeded.
            DEBUG_ASSERT(retcode_ == 0);
            retcode_ = -1;
        }

        // if we have no threads, enter the dead state directly
        if (thread_list_.is_empty()) {
            SetStateLocked(State::DEAD);
            became_dead = true;
        } else {
            // enter the dying state, which should trigger a thread kill.
            // the last thread exiting will transition us to DEAD
            SetStateLocked(State::DYING);
        }
    }

    if (became_dead)
        FinishDeadTransition();
}

void ProcessDispatcher::KillAllThreadsLocked() {
    LTRACE_ENTRY_OBJ;

    for (auto& thread : thread_list_) {
        LTRACEF("killing thread %p\n", &thread);
        thread.Kill();
    }
}

zx_status_t ProcessDispatcher::AddThread(ThreadDispatcher* t, bool initial_thread) {
    LTRACE_ENTRY_OBJ;

    Guard<fbl::Mutex> guard{get_lock()};

    if (initial_thread) {
        if (state_ != State::INITIAL)
            return ZX_ERR_BAD_STATE;
    } else {
        // We must not add a thread when in the DYING or DEAD states.
        // Also, we want to ensure that this is not the first thread.
        if (state_ != State::RUNNING)
            return ZX_ERR_BAD_STATE;
    }

    // add the thread to our list
    DEBUG_ASSERT(thread_list_.is_empty() == initial_thread);
    thread_list_.push_back(t);

    DEBUG_ASSERT(t->process() == this);

    if (initial_thread)
        SetStateLocked(State::RUNNING);

    return ZX_OK;
}

// This is called within thread T's context when it is exiting.

void ProcessDispatcher::RemoveThread(ThreadDispatcher* t) {
    LTRACE_ENTRY_OBJ;

    // ZX-880: Call RemoveChildProcess outside of |get_lock()|.
    bool became_dead = false;

    {
        // we're going to check for state and possibly transition below
        Guard<fbl::Mutex> guard{get_lock()};

        // remove the thread from our list
        DEBUG_ASSERT(t != nullptr);
        thread_list_.erase(*t);

        // if this was the last thread, transition directly to DEAD state
        if (thread_list_.is_empty()) {
            LTRACEF("last thread left the process %p, entering DEAD state\n", this);
            SetStateLocked(State::DEAD);
            became_dead = true;
        }
    }

    if (became_dead)
        FinishDeadTransition();
}

zx_koid_t ProcessDispatcher::get_related_koid() const {
    return job_->get_koid();
}

ProcessDispatcher::State ProcessDispatcher::state() const {
    Guard<fbl::Mutex> guard{get_lock()};
    return state_;
}

fbl::RefPtr<JobDispatcher> ProcessDispatcher::job() {
    return job_;
}

void ProcessDispatcher::SetStateLocked(State s) {
    LTRACEF("process %p: state %u (%s)\n", this, static_cast<unsigned int>(s), StateToString(s));

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

    // look for some invalid state transitions
    if (state_ == State::DEAD && s != State::DEAD) {
        panic("ProcessDispatcher::SetStateLocked invalid state transition from DEAD to !DEAD\n");
        return;
    }

    // transitions to your own state are okay
    if (s == state_)
        return;

    state_ = s;

    if (s == State::DYING) {
        // send kill to all of our threads
        KillAllThreadsLocked();
    }
}

// Finish processing of the transition to State::DEAD. Some things need to be done
// outside of holding |get_lock()|. Beware this is called from several places
// including on_zero_handles().
void ProcessDispatcher::FinishDeadTransition() {
    DEBUG_ASSERT(!completely_dead_);
    completely_dead_ = true;

    // clean up the handle table
    LTRACEF_LEVEL(2, "cleaning up handle table on proc %p\n", this);

    fbl::DoublyLinkedList<Handle*> to_clean;
    {
        Guard<fbl::Mutex> guard{&handle_table_lock_};
        for (auto& handle : handles_) {
            handle.set_process_id(0u);
        }
        to_clean.swap(handles_);
    }

    // zx-1544: Here is where if we're the last holder of a handle of one of
    // our exception ports then ResetExceptionPort will get called (by
    // ExceptionPort::OnPortZeroHandles) and will need to grab |get_lock()|.
    // This needs to be done outside of |get_lock()|.
    while (!to_clean.is_empty()) {
        // Delete handle via HandleOwner dtor.
        HandleOwner ho(to_clean.pop_front());
    }

    LTRACEF_LEVEL(2, "done cleaning up handle table on proc %p\n", this);

    // tear down the address space
    aspace_->Destroy();

    // signal waiter
    LTRACEF_LEVEL(2, "signaling waiters\n");
    UpdateState(0u, ZX_TASK_TERMINATED);

    // The PROC_CREATE record currently emits a uint32_t koid.
    uint32_t koid = static_cast<uint32_t>(get_koid());
    ktrace(TAG_PROC_EXIT, koid, 0, 0, 0);

    // Call job_->RemoveChildProcess(this) outside of |get_lock()|. Otherwise
    // we risk a deadlock as we have |get_lock()| and RemoveChildProcess grabs
    // the job's |lock_|, whereas JobDispatcher::EnumerateChildren obtains the
    // locks in the opposite order. We want to keep lock acquisition order
    // consistent, and JobDispatcher::EnumerateChildren's order makes
    // sense. We don't need |get_lock()| when calling RemoveChildProcess
    // here. ZX-880
    // RemoveChildProcess is called soon after releasing |get_lock()| so that
    // the semantics of signaling ZX_JOB_NO_PROCESSES match that of
    // ZX_TASK_TERMINATED.
    job_->RemoveChildProcess(this);
}

// process handle manipulation routines
zx_handle_t ProcessDispatcher::MapHandleToValue(const Handle* handle) const {
    return map_handle_to_value(handle, handle_rand_);
}

zx_handle_t ProcessDispatcher::MapHandleToValue(const HandleOwner& handle) const {
    return map_handle_to_value(handle.get(), handle_rand_);
}

Handle* ProcessDispatcher::GetHandleLocked(zx_handle_t handle_value,
                                           bool skip_policy) {
    auto handle = map_value_to_handle(handle_value, handle_rand_);
    if (handle && handle->process_id() == get_koid())
        return handle;

    // Handle lookup failed.  We potentially generate an exception,
    // depending on the job policy.  Note that we don't use the return
    // value from QueryPolicy() here: ZX_POL_ACTION_ALLOW and
    // ZX_POL_ACTION_DENY are equivalent for ZX_POL_BAD_HANDLE.
    if (likely(!skip_policy))
        QueryPolicy(ZX_POL_BAD_HANDLE);
    return nullptr;
}

void ProcessDispatcher::AddHandle(HandleOwner handle) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    AddHandleLocked(fbl::move(handle));
}

void ProcessDispatcher::AddHandleLocked(HandleOwner handle) {
    handle->set_process_id(get_koid());
    handles_.push_front(handle.release());
}

HandleOwner ProcessDispatcher::RemoveHandle(zx_handle_t handle_value) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    return RemoveHandleLocked(handle_value);
}

HandleOwner ProcessDispatcher::RemoveHandleLocked(zx_handle_t handle_value) {
    auto handle = GetHandleLocked(handle_value);
    if (!handle)
        return nullptr;

    handle->set_process_id(0u);
    handles_.erase(*handle);

    return HandleOwner(handle);
}


zx_status_t ProcessDispatcher::RemoveHandles(user_in_ptr<const zx_handle_t> user_handles,
                                             size_t num_handles) {
    zx_status_t status = ZX_OK;
    size_t offset = 0;
    while (offset < num_handles) {
        // We process |num_handles| in chunks of |kMaxMessageHandles|
        // because we don't have a limit on how large |num_handles|
        // can be.
        auto chunk_size = fbl::min<size_t>(num_handles - offset, kMaxMessageHandles);

        zx_handle_t handles[kMaxMessageHandles];

        // If we fail |copy_array_from_user|, then we might discard some, but
        // not all, of the handles |user_handles| specified.
        if (user_handles.copy_array_from_user(handles, chunk_size, offset) != ZX_OK)
            return status;

        {
            Guard<fbl::Mutex> guard{handle_table_lock()};
            for (size_t ix = 0; ix != chunk_size; ++ix) {
                if (handles[ix] == ZX_HANDLE_INVALID)
                    continue;
                auto handle = RemoveHandleLocked(handles[ix]);
                if (!handle)
                    status = ZX_ERR_BAD_HANDLE;
            }
        }

        offset += chunk_size;
    }

    return status;
}

zx_koid_t ProcessDispatcher::GetKoidForHandle(zx_handle_t handle_value) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    Handle* handle = GetHandleLocked(handle_value);
    if (!handle)
        return ZX_KOID_INVALID;
    return handle->dispatcher()->get_koid();
}

zx_status_t ProcessDispatcher::GetDispatcherInternal(zx_handle_t handle_value,
                                                     fbl::RefPtr<Dispatcher>* dispatcher,
                                                     zx_rights_t* rights) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    Handle* handle = GetHandleLocked(handle_value);
    if (!handle)
        return ZX_ERR_BAD_HANDLE;

    *dispatcher = handle->dispatcher();
    if (rights)
        *rights = handle->rights();
    return ZX_OK;
}

zx_status_t ProcessDispatcher::GetDispatcherWithRightsInternal(zx_handle_t handle_value,
                                                               zx_rights_t desired_rights,
                                                               fbl::RefPtr<Dispatcher>* dispatcher_out,
                                                               zx_rights_t* out_rights) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    Handle* handle = GetHandleLocked(handle_value);
    if (!handle)
        return ZX_ERR_BAD_HANDLE;

    if (!handle->HasRights(desired_rights))
        return ZX_ERR_ACCESS_DENIED;

    *dispatcher_out = handle->dispatcher();
    if (out_rights)
        *out_rights = handle->rights();
    return ZX_OK;
}

zx_status_t ProcessDispatcher::GetInfo(zx_info_process_t* info) {
    memset(info, 0, sizeof(*info));

    State state;
    // retcode_ depends on the state: make sure they're consistent.
    {
        Guard<fbl::Mutex> guard{get_lock()};
        state = state_;
        info->return_code = retcode_;
        // TODO: Protect with rights if necessary.
        info->debugger_attached = debugger_exception_port_ != nullptr;
    }

    switch (state) {
    case State::DEAD:
    case State::DYING:
        info->exited = true;
        __FALLTHROUGH;
    case State::RUNNING:
        info->started = true;
        break;
    case State::INITIAL:
    default:
        break;
    }

    return ZX_OK;
}

zx_status_t ProcessDispatcher::GetStats(zx_info_task_stats_t* stats) {
    DEBUG_ASSERT(stats != nullptr);
    Guard<fbl::Mutex> guard{get_lock()};
    if (state_ == State::DEAD) {
        return ZX_ERR_BAD_STATE;
    }
    VmAspace::vm_usage_t usage;
    zx_status_t s = aspace_->GetMemoryUsage(&usage);
    if (s != ZX_OK) {
        return s;
    }
    stats->mem_mapped_bytes = usage.mapped_pages * PAGE_SIZE;
    stats->mem_private_bytes = usage.private_pages * PAGE_SIZE;
    stats->mem_shared_bytes = usage.shared_pages * PAGE_SIZE;
    stats->mem_scaled_shared_bytes = usage.scaled_shared_bytes;
    return ZX_OK;
}

zx_status_t ProcessDispatcher::GetAspaceMaps(
    user_out_ptr<zx_info_maps_t> maps, size_t max,
    size_t* actual, size_t* available) {
    Guard<fbl::Mutex> guard{get_lock()};
    if (state_ == State::DEAD) {
        return ZX_ERR_BAD_STATE;
    }
    return GetVmAspaceMaps(aspace_, maps, max, actual, available);
}

zx_status_t ProcessDispatcher::GetVmos(
    user_out_ptr<zx_info_vmo_t> vmos, size_t max,
    size_t* actual_out, size_t* available_out) {
    Guard<fbl::Mutex> guard{get_lock()};
    if (state_ != State::RUNNING) {
        return ZX_ERR_BAD_STATE;
    }
    size_t actual = 0;
    size_t available = 0;
    zx_status_t s = GetProcessVmosViaHandles(this, vmos, max, &actual, &available);
    if (s != ZX_OK) {
        return s;
    }
    size_t actual2 = 0;
    size_t available2 = 0;
    DEBUG_ASSERT(max >= actual);
    s = GetVmAspaceVmos(aspace_, vmos.element_offset(actual), max - actual,
                        &actual2, &available2);
    if (s != ZX_OK) {
        return s;
    }
    *actual_out = actual + actual2;
    *available_out = available + available2;
    return ZX_OK;
}

zx_status_t ProcessDispatcher::GetThreads(fbl::Array<zx_koid_t>* out_threads) {
    Guard<fbl::Mutex> guard{get_lock()};
    size_t n = thread_list_.size_slow();
    fbl::Array<zx_koid_t> threads;
    fbl::AllocChecker ac;
    threads.reset(new (&ac) zx_koid_t[n], n);
    if (!ac.check())
        return ZX_ERR_NO_MEMORY;
    size_t i = 0;
    for (auto& thread : thread_list_) {
        threads[i] = thread.get_koid();
        ++i;
    }
    DEBUG_ASSERT(i == n);
    *out_threads = fbl::move(threads);
    return ZX_OK;
}

zx_status_t ProcessDispatcher::SetExceptionPort(fbl::RefPtr<ExceptionPort> eport) {
    LTRACE_ENTRY_OBJ;
    bool debugger = false;
    switch (eport->type()) {
    case ExceptionPort::Type::DEBUGGER:
        debugger = true;
        break;
    case ExceptionPort::Type::PROCESS:
        break;
    default:
        DEBUG_ASSERT_MSG(false, "unexpected port type: %d",
                         static_cast<int>(eport->type()));
        break;
    }

    // Lock |get_lock()| to ensure the process doesn't transition to dead
    // while we're setting the exception handler.
    Guard<fbl::Mutex> guard{get_lock()};
    if (state_ == State::DEAD)
        return ZX_ERR_NOT_FOUND;
    if (debugger) {
        if (debugger_exception_port_)
            return ZX_ERR_ALREADY_BOUND;
        debugger_exception_port_ = eport;
    } else {
        if (exception_port_)
            return ZX_ERR_ALREADY_BOUND;
        exception_port_ = eport;
    }

    return ZX_OK;
}

bool ProcessDispatcher::ResetExceptionPort(bool debugger, bool quietly) {
    LTRACE_ENTRY_OBJ;
    fbl::RefPtr<ExceptionPort> eport;

    // Remove the exception handler first. As we resume threads we don't
    // want them to hit another exception and get back into
    // ExceptionHandlerExchange.
    {
        Guard<fbl::Mutex> guard{get_lock()};
        if (debugger) {
            debugger_exception_port_.swap(eport);
        } else {
            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> ProcessDispatcher::exception_port() {
    Guard<fbl::Mutex> guard{get_lock()};
    return exception_port_;
}

fbl::RefPtr<ExceptionPort> ProcessDispatcher::debugger_exception_port() {
    Guard<fbl::Mutex> guard{get_lock()};
    return debugger_exception_port_;
}

void ProcessDispatcher::OnExceptionPortRemoval(
        const fbl::RefPtr<ExceptionPort>& eport) {
    Guard<fbl::Mutex> guard{get_lock()};
    for (auto& thread : thread_list_) {
        thread.OnExceptionPortRemoval(eport);
    }
}

uint32_t ProcessDispatcher::ThreadCount() const {
    canary_.Assert();

    Guard<fbl::Mutex> guard{get_lock()};
    return static_cast<uint32_t>(thread_list_.size_slow());
}

size_t ProcessDispatcher::PageCount() const {
    canary_.Assert();

    Guard<fbl::Mutex> guard{get_lock()};
    if (state_ != State::RUNNING) {
        return 0;
    }
    return aspace_->AllocatedPages();
}

class FindProcessByKoid final : public JobEnumerator {
public:
    FindProcessByKoid(zx_koid_t koid) : koid_(koid) {}
    FindProcessByKoid(const FindProcessByKoid&) = delete;

    // To be called after enumeration.
    fbl::RefPtr<ProcessDispatcher> get_pd() { return pd_; }

private:
    bool OnProcess(ProcessDispatcher* process) final {
        if (process->get_koid() == koid_) {
            pd_ = fbl::WrapRefPtr(process);
            // Stop the enumeration.
            return false;
        }
        // Keep looking.
        return true;
    }

    const zx_koid_t koid_;
    fbl::RefPtr<ProcessDispatcher> pd_ = nullptr;
};

// static
fbl::RefPtr<ProcessDispatcher> ProcessDispatcher::LookupProcessById(zx_koid_t koid) {
    FindProcessByKoid finder(koid);
    GetRootJobDispatcher()->EnumerateChildren(&finder, /* recurse */ true);
    return finder.get_pd();
}

fbl::RefPtr<ThreadDispatcher> ProcessDispatcher::LookupThreadById(zx_koid_t koid) {
    LTRACE_ENTRY_OBJ;
    Guard<fbl::Mutex> guard{get_lock()};

    auto iter = thread_list_.find_if([koid](const ThreadDispatcher& t) { return t.get_koid() == koid; });
    return fbl::WrapRefPtr(iter.CopyPointer());
}

uintptr_t ProcessDispatcher::get_debug_addr() const {
    Guard<fbl::Mutex> guard{get_lock()};
    return debug_addr_;
}

zx_status_t ProcessDispatcher::set_debug_addr(uintptr_t addr) {
    if (addr == 0u)
        return ZX_ERR_INVALID_ARGS;
    Guard<fbl::Mutex> guard{get_lock()};
    // Only allow the value to be set to a nonzero or magic debug break once:
    // Once ld.so has set it that's it.
    if (!(debug_addr_ == 0u || debug_addr_ == ZX_PROCESS_DEBUG_ADDR_BREAK_ON_SET))
        return ZX_ERR_ACCESS_DENIED;
    debug_addr_ = addr;
    return ZX_OK;
}

zx_status_t ProcessDispatcher::QueryPolicy(uint32_t condition) const {
    auto action = GetSystemPolicyManager()->QueryBasicPolicy(policy_, condition);
    if (action & ZX_POL_ACTION_EXCEPTION) {
        thread_signal_policy_exception();
    }
    // TODO(cpu): check for the ZX_POL_KILL bit and return an error code
    // that abigen understands as termination.
    return (action & ZX_POL_ACTION_DENY) ? ZX_ERR_ACCESS_DENIED : ZX_OK;
}

uintptr_t ProcessDispatcher::cache_vdso_code_address() {
    Guard<fbl::Mutex> guard{get_lock()};
    vdso_code_address_ = aspace_->vdso_code_address();
    return vdso_code_address_;
}

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

bool ProcessDispatcher::IsHandleValid(zx_handle_t handle_value) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    return (GetHandleLocked(handle_value) != nullptr);
}

bool ProcessDispatcher::IsHandleValidNoPolicyCheck(zx_handle_t handle_value) {
    Guard<fbl::Mutex> guard{&handle_table_lock_};
    return (GetHandleLocked(handle_value, true) != nullptr);
}

void ProcessDispatcher::OnProcessStartForJobDebugger(ThreadDispatcher *t) {
    auto job = job_;
    while (job) {
      auto port = job->debugger_exception_port();
      if (port) {
        port->OnProcessStartForDebugger(t);
        break;
      } else {
        job = job->parent();
      }
    }
}
