// 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 <lib/counters.h>
#include <lib/crypto/global_prng.h>
#include <lib/ktrace.h>
#include <string.h>
#include <trace.h>
#include <zircon/listnode.h>
#include <zircon/rights.h>

#include <arch/defines.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <fbl/ref_ptr.h>
#include <kernel/thread.h>
#include <object/diagnostics.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 <vm/vm.h>
#include <vm/vm_aspace.h>
#include <vm/vm_object.h>

#define LOCAL_TRACE 0

namespace {

const uint32_t kPolicyIdToPolicyException[] = {
    ZX_EXCP_POLICY_CODE_BAD_HANDLE,             // ZX_POL_BAD_HANDLE,
    ZX_EXCP_POLICY_CODE_WRONG_OBJECT,           // ZX_POL_WRONG_OBJECT
    ZX_EXCP_POLICY_CODE_VMAR_WX,                // ZX_POL_VMAR_WX
    ZX_EXCP_POLICY_CODE_NEW_ANY,                // ZX_POL_NEW_ANY
    ZX_EXCP_POLICY_CODE_NEW_VMO,                // ZX_POL_NEW_VMO
    ZX_EXCP_POLICY_CODE_NEW_CHANNEL,            // ZX_POL_NEW_CHANNEL
    ZX_EXCP_POLICY_CODE_NEW_EVENT,              // ZX_POL_NEW_EVENT
    ZX_EXCP_POLICY_CODE_NEW_EVENTPAIR,          // ZX_POL_NEW_EVENTPAIR
    ZX_EXCP_POLICY_CODE_NEW_PORT,               // ZX_POL_NEW_PORT
    ZX_EXCP_POLICY_CODE_NEW_SOCKET,             // ZX_POL_NEW_SOCKET
    ZX_EXCP_POLICY_CODE_NEW_FIFO,               // ZX_POL_NEW_FIFO
    ZX_EXCP_POLICY_CODE_NEW_TIMER,              // ZX_POL_NEW_TIMER
    ZX_EXCP_POLICY_CODE_NEW_PROCESS,            // ZX_POL_NEW_PROCESS
    ZX_EXCP_POLICY_CODE_NEW_PROFILE,            // ZX_POL_NEW_PROFILE
    ZX_EXCP_POLICY_CODE_NEW_PAGER,              // ZX_POL_NEW_PAGER
    ZX_EXCP_POLICY_CODE_AMBIENT_MARK_VMO_EXEC,  // ZX_POL_AMBIENT_MARK_VMO_EXEC
};

static_assert(std::size(kPolicyIdToPolicyException) == ZX_POL_MAX,
              "must update mapping from policy id to synth_code generated by policy exception");

}  // namespace

KCOUNTER(dispatcher_process_create_count, "dispatcher.process.create")
KCOUNTER(dispatcher_process_destroy_count, "dispatcher.process.destroy")

zx_status_t ProcessDispatcher::Create(fbl::RefPtr<JobDispatcher> job, ktl::string_view name,
                                      uint32_t flags, KernelHandle<ProcessDispatcher>* handle,
                                      zx_rights_t* rights,
                                      KernelHandle<VmAddressRegionDispatcher>* root_vmar_handle,
                                      zx_rights_t* root_vmar_rights) {
  fbl::AllocChecker ac;
  fbl::RefPtr<ShareableProcessState> shareable_state =
      fbl::AdoptRef(new (&ac) ShareableProcessState);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  KernelHandle new_handle(
      fbl::AdoptRef(new (&ac) ProcessDispatcher(ktl::move(shareable_state), job, name, flags)));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t result = new_handle.dispatcher()->Initialize();
  if (result != ZX_OK)
    return result;

  // Create a dispatcher for the root VMAR.
  KernelHandle<VmAddressRegionDispatcher> new_vmar_handle;
  result = VmAddressRegionDispatcher::Create(new_handle.dispatcher()->aspace()->RootVmar(),
                                             ARCH_MMU_FLAG_PERM_USER, &new_vmar_handle,
                                             root_vmar_rights);
  if (result != ZX_OK)
    return result;

  // Only now that the process has been fully created and initialized can we register it with its
  // parent job. We don't want anyone to see it in a partially initalized state.
  if (!job->AddChildProcess(new_handle.dispatcher())) {
    return ZX_ERR_BAD_STATE;
  }

  *rights = default_rights();
  *handle = ktl::move(new_handle);
  *root_vmar_handle = ktl::move(new_vmar_handle);

  return ZX_OK;
}

ProcessDispatcher::ProcessDispatcher(fbl::RefPtr<ShareableProcessState> shared_state,
                                     fbl::RefPtr<JobDispatcher> job, ktl::string_view name,
                                     uint32_t flags)
    : shared_state_(ktl::move(shared_state)),
      job_(ktl::move(job)),
      policy_(job_->GetPolicy()),
      exceptionate_(ZX_EXCEPTION_CHANNEL_TYPE_PROCESS),
      debug_exceptionate_(ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER),
      name_(name.data(), name.length()) {
  LTRACE_ENTRY_OBJ;

  [[maybe_unused]] uint32_t count = shared_state_->IncrementShareCount();
  DEBUG_ASSERT(count == 0);

  kcounter_add(dispatcher_process_create_count, 1);
}

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(!aspace_ || aspace_->is_destroyed());

  kcounter_add(dispatcher_process_destroy_count, 1);

  // Remove ourselves from the parent job's raw ref to us. Note that this might
  // have been 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<Mutex> guard{get_lock()};
    if (state_ != State::INITIAL) {
      // Initalized proceses are kept alive by their threads, see
      // RemoveThread() for the details.
      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<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<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::ExitCurrent();

  __UNREACHABLE;
}

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

  // fxbug.dev/30829: Call RemoveChildProcess outside of |get_lock()|.
  bool became_dead = false;

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

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

    if (state_ != State::DYING) {
      DEBUG_ASSERT(retcode_ == 0);
      retcode_ = retcode;
    }

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

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

  LTRACE_ENTRY_OBJ;

  Guard<Mutex> guard{get_lock()};

  // If we're dying don't try to suspend.
  if (state_ == State::DYING || state_ == State::DEAD)
    return ZX_ERR_BAD_STATE;

  DEBUG_ASSERT(suspend_count_ >= 0);
  suspend_count_++;
  if (suspend_count_ == 1) {
    for (auto& thread : thread_list_) {
      // Thread suspend can only fail if the thread is already dying, which is fine here
      // since it will be removed from this process shortly, so continue to suspend whether
      // the thread suspend succeeds or fails.
      zx_status_t status = thread.Suspend();
      DEBUG_ASSERT(status == ZX_OK || thread.IsDyingOrDead());
    }
  }

  return ZX_OK;
}

void ProcessDispatcher::Resume() {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;

  Guard<Mutex> guard{get_lock()};

  // If we're in the process of dying don't try to resume, just let it continue to clean up.
  if (state_ == State::DYING || state_ == State::DEAD)
    return;

  DEBUG_ASSERT(suspend_count_ > 0);
  suspend_count_--;
  if (suspend_count_ == 0) {
    for (auto& thread : thread_list_) {
      thread.Resume();
    }
  }
}

void ProcessDispatcher::KillAllThreadsLocked() {
  LTRACE_ENTRY_OBJ;

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

zx_status_t ProcessDispatcher::AddInitializedThread(ThreadDispatcher* t, bool initial_thread,
                                                    const ThreadDispatcher::EntryState& entry) {
  LTRACE_ENTRY_OBJ;

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

  // Now that we know our state is okay we can attempt to start the thread running. This is okay
  // since as long as the thread doesn't refuse to start running then we cannot fail from here
  // and so we will update our thread_list_ and state before we drop the lock, making this
  // whole process atomic to any observers.
  zx_status_t result = t->MakeRunnable(entry, suspend_count_ > 0);
  if (result != ZX_OK) {
    return result;
  }

  // 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) {
    DEBUG_ASSERT_MSG(start_time_ == 0, "start_time_ %ld", start_time_);
    start_time_ = current_time();
    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;

  // fxbug.dev/30829: Call RemoveChildProcess outside of |get_lock()|.
  bool became_dead = false;

  {
    // we're going to check for state and possibly transition below
    Guard<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;
    }

    TaskRuntimeStats child_runtime;
    if (t->GetRuntimeStats(&child_runtime) == ZX_OK) {
      aggregated_runtime_stats_.Add(child_runtime);
    }
  }

  if (became_dead)
    FinishDeadTransition();
}

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

ProcessDispatcher::State ProcessDispatcher::state() const {
  Guard<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;

  // It doesn't matter whether the lock is held or not while shutting down
  // the exceptionates, this is just the most convenient place to do it.
  exceptionate_.Shutdown();
  debug_exceptionate_.Shutdown();

  // clean up shared state, including the handle table
  LTRACEF_LEVEL(2, "removing shared state reference from proc %p\n", this);
  shared_state_->DecrementShareCount();

  // Tear down the address space. It may not exist if Initialize() failed.
  if (aspace_) {
    zx_status_t result = aspace_->Destroy();
    ASSERT_MSG(result == ZX_OK, "%d\n", result);
  }

  // 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. fxbug.dev/30829
  job_->RemoveChildProcess(this);

  // If we are critical to a job, we need to take action. Similar to the above
  // comment, we avoid performing the actual call into the job whilst still
  // holding the lock.
  fbl::RefPtr<JobDispatcher> kill_job;
  {
    Guard<Mutex> guard{get_lock()};
    if (critical_to_job_ != nullptr) {
      // Check if we accept any return code, or require it be non-zero.
      if (!retcode_nonzero_ || retcode_ != 0) {
        kill_job = critical_to_job_;
      }
    }
  }
  if (kill_job) {
    kill_job->CriticalProcessKill(fbl::RefPtr<ProcessDispatcher>(this));
  }
}

void ProcessDispatcher::GetInfo(zx_info_process_t* info) const {
  canary_.Assert();

  State state;
  zx_time_t start_time;
  int64_t return_code;
  zx_info_process_flags_t flags = 0u;
  // retcode_ depends on the state: make sure they're consistent.
  {
    Guard<Mutex> guard{get_lock()};
    state = state_;
    start_time = start_time_;
    return_code = retcode_;
    // TODO: Protect with rights if necessary.
    if (debug_exceptionate_.HasValidChannel()) {
      flags |= ZX_INFO_PROCESS_FLAG_DEBUGGER_ATTACHED;
    }
  }

  switch (state) {
    case State::DEAD:
    case State::DYING:
      flags |= ZX_INFO_PROCESS_FLAG_EXITED;
      __FALLTHROUGH;
    case State::RUNNING:
      flags |= ZX_INFO_PROCESS_FLAG_STARTED;
      break;
    case State::INITIAL:
    default:
      break;
  }

  *info = zx_info_process_t{
      .return_code = return_code,
      .start_time = start_time,
      .flags = flags,
      .padding1 = {},
  };
}

zx_status_t ProcessDispatcher::GetStats(zx_info_task_stats_t* stats) const {
  DEBUG_ASSERT(stats != nullptr);
  Guard<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::AccumulateRuntimeTo(zx_info_task_runtime_t* info) const {
  Guard<Mutex> guard{get_lock()};
  aggregated_runtime_stats_.AccumulateRuntimeTo(info);
  for (const auto& thread : thread_list_) {
    zx_status_t err = thread.AccumulateRuntimeTo(info);
    if (err != ZX_OK) {
      return err;
    }
  }

  return ZX_OK;
}

zx_status_t ProcessDispatcher::GetAspaceMaps(VmAspace* current_aspace,
                                             user_out_ptr<zx_info_maps_t> maps, size_t max,
                                             size_t* actual, size_t* available) const {
  // Do not check the state_ since we need to call GetVmAspaceMaps without the dispatcher lock held,
  // and so any check will become stale anyway. Should the process be dead, or transition to the
  // dead state during the operation, then the associated aspace will also be destroyed, which will
  // be noticed and result in a ZX_ERR_BAD_STATE being returned from GetVmAspaceMaps.
  return GetVmAspaceMaps(current_aspace, aspace_, maps, max, actual, available);
}

zx_status_t ProcessDispatcher::GetVmos(VmAspace* current_aspace, VmoInfoWriter& vmos, size_t max,
                                       size_t* actual_out, size_t* available_out) {
  {
    Guard<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 = GetProcessVmos(this, vmos, max, &actual, &available);
  if (s != ZX_OK) {
    return s;
  }

  size_t actual2 = 0;
  size_t available2 = 0;
  DEBUG_ASSERT(max >= actual);
  vmos.AddOffset(actual);
  s = GetVmAspaceVmos(current_aspace, aspace_, vmos, 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) const {
  Guard<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 = ktl::move(threads);
  return ZX_OK;
}

zx_status_t ProcessDispatcher::SetCriticalToJob(fbl::RefPtr<JobDispatcher> critical_to_job,
                                                bool retcode_nonzero) {
  Guard<Mutex> guard{get_lock()};

  if (critical_to_job_) {
    // The process is already critical to a job.
    return ZX_ERR_ALREADY_BOUND;
  }

  auto job_copy = job_;
  for (auto& job = job_copy; job; job = job->parent()) {
    if (job == critical_to_job) {
      critical_to_job_ = critical_to_job;
      break;
    }
  }

  if (!critical_to_job_) {
    // The provided job is not the parent of this process, or an ancestor.
    return ZX_ERR_INVALID_ARGS;
  }

  retcode_nonzero_ = retcode_nonzero;
  return ZX_OK;
}

Exceptionate* ProcessDispatcher::exceptionate(Exceptionate::Type type) {
  canary_.Assert();
  return type == Exceptionate::Type::kDebug ? &debug_exceptionate_ : &exceptionate_;
}

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

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

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

  Guard<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::RefPtr(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()->EnumerateChildrenRecursive(&finder);
  return finder.get_pd();
}

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

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

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

zx_status_t ProcessDispatcher::set_debug_addr(uintptr_t addr) {
  Guard<Mutex> guard{get_lock()};
  debug_addr_ = addr;
  return ZX_OK;
}

uintptr_t ProcessDispatcher::get_dyn_break_on_load() const {
  Guard<Mutex> guard{get_lock()};
  return dyn_break_on_load_;
}

zx_status_t ProcessDispatcher::set_dyn_break_on_load(uintptr_t break_on_load) {
  Guard<Mutex> guard{get_lock()};
  dyn_break_on_load_ = break_on_load;
  return ZX_OK;
}

zx_status_t ProcessDispatcher::EnforceBasicPolicy(uint32_t condition) {
  const auto action = policy_.QueryBasicPolicy(condition);
  switch (action) {
    case ZX_POL_ACTION_ALLOW:
      // Not calling IncrementCounter here because this is the common case (fast path).
      return ZX_OK;
    case ZX_POL_ACTION_DENY:
      JobPolicy::IncrementCounter(action, condition);
      return ZX_ERR_ACCESS_DENIED;
    case ZX_POL_ACTION_ALLOW_EXCEPTION:
      Thread::Current::SignalPolicyException(kPolicyIdToPolicyException[condition], 0u);
      JobPolicy::IncrementCounter(action, condition);
      return ZX_OK;
    case ZX_POL_ACTION_DENY_EXCEPTION:
      Thread::Current::SignalPolicyException(kPolicyIdToPolicyException[condition], 0u);
      JobPolicy::IncrementCounter(action, condition);
      return ZX_ERR_ACCESS_DENIED;
    case ZX_POL_ACTION_KILL:
      Kill(ZX_TASK_RETCODE_POLICY_KILL);
      JobPolicy::IncrementCounter(action, condition);
      // Because we've killed, this return value will never make it out to usermode. However,
      // callers of this method will see and act on it.
      return ZX_ERR_ACCESS_DENIED;
  };
  panic("unexpected policy action %u\n", action);
}

TimerSlack ProcessDispatcher::GetTimerSlackPolicy() const { return policy_.GetTimerSlack(); }

TaskRuntimeStats ProcessDispatcher::GetAggregatedRuntime() const {
  Guard<Mutex> guard{get_lock()};
  return aggregated_runtime_stats_;
}

uintptr_t ProcessDispatcher::cache_vdso_code_address() {
  Guard<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";
}

void ProcessDispatcher::OnProcessStartForJobDebugger(ThreadDispatcher* t,
                                                     const arch_exception_context_t* context) {
  auto job = job_;
  while (job) {
    if (t->HandleSingleShotException(job->exceptionate(Exceptionate::Type::kDebug),
                                     ZX_EXCP_PROCESS_STARTING, *context)) {
      break;
    }

    job = job->parent();
  }
}
