// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2008-2015 Travis Geiselbrecht
//
// 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

/**
 * @file
 * @brief  Kernel threading
 *
 * This file is the core kernel threading interface.
 *
 * @defgroup thread Threads
 * @{
 */
#include "kernel/thread.h"

#include <assert.h>
#include <debug.h>
#include <inttypes.h>
#include <lib/arch/intrin.h>
#include <lib/counters.h>
#include <lib/fit/defer.h>
#include <lib/fxt/interned_string.h>
#include <lib/heap.h>
#include <lib/kconcurrent/chainlock.h>
#include <lib/kconcurrent/chainlock_transaction.h>
#include <lib/ktrace.h>
#include <lib/lazy_init/lazy_init.h>
#include <lib/thread_sampler/thread_sampler.h>
#include <lib/version.h>
#include <lib/zircon-internal/macros.h>
#include <platform.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/errors.h>
#include <zircon/listnode.h>
#include <zircon/time.h>
#include <zircon/types.h>

#include <arch/debugger.h>
#include <arch/exception.h>
#include <arch/interrupt.h>
#include <arch/ops.h>
#include <arch/thread.h>
#include <kernel/auto_preempt_disabler.h>
#include <kernel/cpu.h>
#include <kernel/dpc.h>
#include <kernel/idle_power_thread.h>
#include <kernel/lockdep.h>
#include <kernel/mp.h>
#include <kernel/percpu.h>
#include <kernel/restricted.h>
#include <kernel/scheduler.h>
#include <kernel/stats.h>
#include <kernel/timer.h>
#include <ktl/algorithm.h>
#include <ktl/atomic.h>
#include <lk/main.h>
#include <lockdep/lockdep.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>
#include <pretty/hexdump.h>
#include <vm/kstack.h>
#include <vm/vm.h>
#include <vm/vm_address_region.h>
#include <vm/vm_aspace.h>

#include "lib/zx/time.h"

#include <ktl/enforce.h>

#define LOCAL_TRACE 0

// kernel counters.
// The counters below never decrease.
//
// counts the number of Threads successfully created.
KCOUNTER(thread_create_count, "thread.create")
// counts the number of detached Threads that exited. Never decreases.
KCOUNTER(thread_detached_exit_count, "thread.detached_exit")
// counts the number of Threads joined. Never decreases.
KCOUNTER(thread_join_count, "thread.join")
// counts the number of calls to suspend() that succeeded.
KCOUNTER(thread_suspend_count, "thread.suspend")
// counts the number of calls to resume() that succeeded.
KCOUNTER(thread_resume_count, "thread.resume")
// counts the number of times a thread's timeslice extension was activated (see
// |PreemptionState::SetTimesliceExtension|).
KCOUNTER(thread_timeslice_extended, "thread.timeslice_extended")
// counts the number of calls to restricted_kick() that succeeded.
KCOUNTER(thread_restricted_kick_count, "thread.restricted_kick")
// counts the number of failed samples
KCOUNTER(thread_sampling_failed, "thread.sampling_failed")

// The global thread list. This is a lazy_init type, since initial thread code
// manipulates the list before global constructors are run. This is initialized by
// thread_init_early.
static lazy_init::LazyInit<Thread::List> thread_list TA_GUARDED(Thread::get_list_lock());

Thread::MigrateList Thread::migrate_list_;

// master thread spinlock
MonitoredSpinLock thread_lock __CPU_ALIGN_EXCLUSIVE{"thread_lock"_intern};

// The global preempt disabled token singleton
PreemptDisabledToken preempt_disabled_token;

const char* ToString(enum thread_state state) {
  switch (state) {
    case THREAD_INITIAL:
      return "initial";
    case THREAD_READY:
      return "ready";
    case THREAD_RUNNING:
      return "running";
    case THREAD_BLOCKED:
      return "blocked";
    case THREAD_BLOCKED_READ_LOCK:
      return "blocked read lock";
    case THREAD_SLEEPING:
      return "sleeping";
    case THREAD_SUSPENDED:
      return "suspended";
    case THREAD_DEATH:
      return "death";
    default:
      return "[unknown]";
  }
}

static void init_thread_lock_state(Thread* t) {
#if WITH_LOCK_DEP
  lockdep::SystemInitThreadLockState(&t->lock_state());
#endif
}

void WaitQueueCollection::ThreadState::Block(Thread* const current_thread,
                                             Interruptible interruptible, zx_status_t status) {
  blocked_status_ = status;
  interruptible_ = interruptible;
  Scheduler::Block(current_thread);
  interruptible_ = Interruptible::No;
}

void WaitQueueCollection::ThreadState::Unsleep(Thread* thread, zx_status_t status) {
  blocked_status_ = status;
  Scheduler::Unblock(thread);
}

WaitQueueCollection::ThreadState::~ThreadState() {
  DEBUG_ASSERT(blocking_wait_queue_ == nullptr);

  // owned_wait_queues_ is a fbl:: list of unmanaged pointers.  It will debug
  // assert if it is not empty when it destructs; we do not need to do so
  // here.
}

// Default constructor/destructor.
Thread::Thread() {}

Thread::~Thread() {
  // At this point, the thread must not be on the global thread list or migrate
  // list.
  DEBUG_ASSERT(!thread_list_node_.InContainer());
  DEBUG_ASSERT(!migrate_list_node_.InContainer());
}

void Thread::set_name(ktl::string_view name) {
  // |name| must fit in ZX_MAX_NAME_LEN bytes, minus 1 for the trailing NUL.
  name = name.substr(0, ZX_MAX_NAME_LEN - 1);
  memcpy(name_, name.data(), name.size());
  memset(name_ + name.size(), 0, ZX_MAX_NAME_LEN - name.size());
}

void construct_thread(Thread* t, const char* name) {
  // Placement new to trigger any special construction requirements of the
  // Thread structure.
  //
  // TODO(johngro): now that we have converted Thread over to C++, consider
  // switching to using C++ constructors/destructors and new/delete to handle
  // all of this instead of using construct_thread and free_thread_resources
  new (t) Thread();

  t->set_name(name);
  init_thread_lock_state(t);
}

void TaskState::Init(thread_start_routine entry, void* arg) {
  entry_ = entry;
  arg_ = arg;
}

zx_status_t TaskState::Join(Thread* const current_thread, zx_time_t deadline) {
  return retcode_wait_queue_.Block(current_thread, deadline, Interruptible::No);
}

bool TaskState::TryWakeJoiners(zx_status_t status) {
  ktl::optional<uint32_t> result;

  // Attempt to lock the queue first.
  if (retcode_wait_queue_.get_lock().Acquire() == ChainLock::LockResult::kOk) {
    // We got the lock, make sure we drop it before exiting.
    retcode_wait_queue_.get_lock().AssertAcquired();

    // Now, try to lock and wake all of our waiting threads.
    result = retcode_wait_queue_.WakeAllLocked(status);

    // No matter what just happened, we need to drop the queue's lock.
    retcode_wait_queue_.get_lock().Release();
  }

  // If we got a result, then we succeeded in waking the threads we wanted to
  // wake.
  return result != ktl::nullopt;
}

static void free_thread_resources(Thread* t) {
  // free the thread structure itself.  Manually trigger the struct's
  // destructor so that DEBUG_ASSERTs present in the owned_wait_queues member
  // get triggered.
  bool thread_needs_free = t->free_struct();
  t->~Thread();
  if (thread_needs_free) {
    free(t);
  }
}

zx_status_t Thread::Current::Fault(Thread::Current::FaultType type, vaddr_t va, uint flags) {
  if (is_kernel_address(va)) {
    // Kernel addresses should never fault.
    return ZX_ERR_NOT_FOUND;
  }

  // If this thread is a kernel thread, then it must be running a unit test that set `aspace_`
  // explicitly, so use `aspace_` to resolve the fault.
  //
  // If this is a user thread in restricted mode, then `aspace_` is set to the restricted address
  // space and should be used to resolve the fault.
  //
  // Otherwise, this is a user thread running in normal mode. Therefore, we must consult the
  // process' aspace_at function to resolve the fault.
  Thread* t = Thread::Current::Get();
  VmAspace* containing_aspace;
  bool in_restricted = t->restricted_state_ && t->restricted_state_->in_restricted();
  if (!t->user_thread_ || in_restricted) {
    containing_aspace = t->aspace_;
  } else {
    containing_aspace = t->user_thread_->process()->aspace_at(va);
  }

  // Call the appropriate fault function on the containing address space.
  switch (type) {
    case Thread::Current::FaultType::PageFault:
      return containing_aspace->PageFault(va, flags);
    case Thread::Current::FaultType::SoftFault:
      return containing_aspace->SoftFault(va, flags);
    case Thread::Current::FaultType::AccessedFault:
      DEBUG_ASSERT(flags == 0);
      return containing_aspace->AccessedFault(va);
  }
  // This should be unreachable, and is here mainly to satisfy GCC.
  return ZX_ERR_NOT_FOUND;
}

void Thread::Trampoline() {
  // Handle the special case of starting a new thread for the first time,
  // releasing the previous thread's lock as well as the current thread's lock
  // in the process, before restoring interrupts and dropping into the thread's
  // entry point.
  Scheduler::TrampolineLockHandoff();
  arch_enable_ints();

  // Call into the thread's entry point, and call exit when finished.
  const TaskState& task_state = Thread::Current::Get()->task_state_;
  int ret = task_state.entry()(task_state.arg());
  Thread::Current::Exit(ret);
}

/**
 * @brief  Create a new thread
 *
 * This function creates a new thread.  The thread is initially suspended, so you
 * need to call thread_resume() to execute it.
 *
 * @param  t               If not nullptr, use the supplied Thread
 * @param  name            Name of thread
 * @param  entry           Entry point of thread
 * @param  arg             Arbitrary argument passed to entry(). It can be null.
 *                         in which case |user_thread| will be used.
 * @param  priority        Execution priority for the thread.
 * @param  alt_trampoline  If not nullptr, an alternate trampoline for the thread
 *                         to start on.
 *
 * Thread priority is an integer from 0 (lowest) to 31 (highest).  Some standard
 * priorities are defined in <kernel/thread.h>:
 *
 *  HIGHEST_PRIORITY
 *  DPC_PRIORITY
 *  HIGH_PRIORITY
 *  DEFAULT_PRIORITY
 *  LOW_PRIORITY
 *  IDLE_PRIORITY
 *  LOWEST_PRIORITY
 *
 * Stack size is set to DEFAULT_STACK_SIZE
 *
 * @return  Pointer to thread object, or nullptr on failure.
 */
Thread* Thread::CreateEtc(Thread* t, const char* name, thread_start_routine entry, void* arg,
                          const SchedulerState::BaseProfile& profile,
                          thread_trampoline_routine alt_trampoline) {
  unsigned int flags = 0;

  if (!t) {
    t = static_cast<Thread*>(memalign(alignof(Thread), sizeof(Thread)));
    if (!t) {
      return nullptr;
    }
    flags |= THREAD_FLAG_FREE_STRUCT;
  }

  // assert that t is at least as aligned as the Thread is supposed to be
  DEBUG_ASSERT(IS_ALIGNED(t, alignof(Thread)));

  construct_thread(t, name);

  {
    // Do not hold the thread's lock while we initialize it.  We are going to
    // perform some operations (like dynamic memory allocation) which will
    // require us to obtain potentially contested mutexes, something we cannot
    // safely do while holding any spinlocks, or chainlocks.
    //
    // Not holding the thread's lock here _should_ be OK.  We are basically in
    // the process of constructing the thread, no one else knows about this
    // memory just yet.  There are a limited number of ways that other CPUs in
    // the system could find out about this thread, and they should all involve
    // synchronizing via a lock which should establish proper memory ordering
    // semantics.
    //
    // 1) After we add the thread to the global thread list, debug code could
    //    find the thread, but only after synchronizing via the global thread
    //    list lock.
    // 2) After we add the thread to the scheduler (after CreateEtc), other CPUs
    //    can find out about it, but only after synchronizing via the
    //    scheduler's queue lock.
    //
    struct FakeChainLockTransaction {
      // Lie to the analyzer about the fact that we are in a CLT, so we can lie
      // to the analyzer about holding the thread's lock.
      FakeChainLockTransaction() TA_ACQ(chainlock_transaction_token) {}
      ~FakeChainLockTransaction() TA_REL(chainlock_transaction_token) {}
    } fake_clt{};
    t->get_lock().MarkNeedsRelease();  // This is a lie, we don't hold the lock.  See above.

    t->task_state_.Init(entry, arg);
    Scheduler::InitializeThread(t, profile);

    zx_status_t status = t->stack_.Init();
    if (status != ZX_OK) {
      t->get_lock().MarkReleased();
      free_thread_resources(t);
      return nullptr;
    }

    // save whether or not we need to free the thread struct and/or stack
    t->flags_ = flags;

    if (likely(alt_trampoline == nullptr)) {
      alt_trampoline = &Thread::Trampoline;
    }

    // set up the initial stack frame
    arch_thread_initialize(t, (vaddr_t)alt_trampoline);

    t->get_lock().MarkReleased();
  }

  // Add it to the global thread list.  Be sure to grab the locks in the proper
  // order; global thread list lock first, then the thread's lock second.
  {
    Guard<SpinLock, IrqSave> list_guard{&list_lock_};
    SingletonChainLockGuardNoIrqSave thread_guard{t->get_lock(), CLT_TAG("Thread::CreateEtc")};
    thread_list->push_front(t);
  }

  kcounter_add(thread_create_count, 1);
  return t;
}

Thread* Thread::Create(const char* name, thread_start_routine entry, void* arg, int priority) {
  return Thread::CreateEtc(nullptr, name, entry, arg, SchedulerState::BaseProfile{priority},
                           nullptr);
}

Thread* Thread::Create(const char* name, thread_start_routine entry, void* arg,
                       const SchedulerState::BaseProfile& profile) {
  return Thread::CreateEtc(nullptr, name, entry, arg, profile, nullptr);
}

/**
 * @brief  Make a suspended thread executable.
 *
 * This function is called to start a thread which has just been
 * created with thread_create() or which has been suspended with
 * thread_suspend(). It can not fail.
 */
void Thread::Resume() {
  canary_.Assert();

  // We cannot allow a resume to happen if we are holding any spinlocks, unless
  // local preemption has been disabled.  If we have local preemption enabled,
  // and a spinlock held, then it is theoretically possible for our current CPU
  // to be chosen as the target for the thread being resumed, triggering a local
  // preemption event.  This is illegal; being preempted while holding a
  // spinlock means that we might lose our CPU while holding a spinlock.
  //
  // So, assert this here.  Either we have no spinlocks, or preemption has
  // already been disabled (presumably to the point where we have dropped all of
  // our spinlocks)
  DEBUG_ASSERT_MSG((arch_num_spinlocks_held() == 0) ||
                       (Thread::Current::Get()->preemption_state().PreemptIsEnabled() == false),
                   "It is illegal to Resume a thread when any spinlocks are held unless local "
                   "preemption is disabled.  (spinlocks held %u, preemption enabled %d)",
                   arch_num_spinlocks_held(),
                   Thread::Current::Get()->preemption_state().PreemptIsEnabled());

  // Explicitly disable preemption (if it has not been already) before grabbing
  // the target thread's lock.  This will ensure that we have dropped the target
  // thread's lock before any local reschedule takes place, helping to avoid
  // lock thrash as the target thread becomes scheduled for the first time.
  ChainLockTransactionPreemptDisableAndIrqSave clt{CLT_TAG("Thread::Resume")};
  lock_.AcquireUnconditionally();
  clt.Finalize();

  if (state() == THREAD_DEATH) {
    // The thread is dead, resuming it is a no-op.
    lock_.Release();
    return;
  }

  // Emit the thread metadata the first time the thread is resumed so that trace
  // events written by this thread have the correct name and process association.
  if (state() == THREAD_INITIAL) {
    KTRACE_KERNEL_OBJECT("kernel:meta", tid(), ZX_OBJ_TYPE_THREAD, name(),
                         ("process", ktrace::Koid(pid())));
  }

  // Clear the suspend signal in case there is a pending suspend
  signals_.fetch_and(~THREAD_SIGNAL_SUSPEND, ktl::memory_order_relaxed);
  if (state() == THREAD_INITIAL || state() == THREAD_SUSPENDED) {
    // Wake up the new thread, putting it in a run queue on a cpu.
    Scheduler::Unblock(this);
  } else {
    lock_.Release();
  }

  kcounter_add(thread_resume_count, 1);
}

zx_status_t Thread::DetachAndResume() {
  zx_status_t status = Detach();
  if (status != ZX_OK) {
    return status;
  }
  Resume();
  return ZX_OK;
}

/**
 * @brief  Suspend or Kill an initialized/ready/running thread
 *
 * @return ZX_OK on success, ZX_ERR_BAD_STATE if the thread is dead
 */
zx_status_t Thread::SuspendOrKillInternal(SuspendOrKillOp op) {
  canary_.Assert();
  DEBUG_ASSERT(!IsIdle());

  const bool suspend_op = op == SuspendOrKillOp::Suspend;
  const zx_status_t wakeup_status =
      suspend_op ? ZX_ERR_INTERNAL_INTR_RETRY : ZX_ERR_INTERNAL_INTR_KILLED;
  auto set_signals = fit::defer([this, suspend_op]() {
    if (suspend_op) {
      signals_.fetch_or(THREAD_SIGNAL_SUSPEND, ktl::memory_order_relaxed);
      kcounter_add(thread_suspend_count, 1);
    } else {
      signals_.fetch_or(THREAD_SIGNAL_KILL, ktl::memory_order_relaxed);
    }
  });

  // Disable preemption to defer rescheduling until the transaction is completed.
  ChainLockTransactionPreemptDisableAndIrqSave clt{CLT_TAG("Thread::SuspendOrKillInternal")};
  for (;; clt.Relax()) {
    lock_.AcquireUnconditionally();
    const thread_state cur_state = state();

    // If this is a kill operation, and we are killing ourself, just set our
    // signal bits and get out.  We will process the pending signal (eventually)
    // as we unwind.
    if ((suspend_op == false) && (this == Thread::Current::Get())) {
      clt.Finalize();
      DEBUG_ASSERT(cur_state == THREAD_RUNNING);
      set_signals.call();
      lock_.Release();
      return ZX_OK;
    }

    // If the thread is in the DEATH state, it cannot be suspended.  Do not set
    // any signals, or increment any kcounters on our way out.
    if (cur_state == THREAD_DEATH) {
      clt.Finalize();
      set_signals.cancel();
      lock_.Release();
      return ZX_ERR_BAD_STATE;
    }

    // If the thread is sleeping, or it is blocked, then we can only wake it up
    // for the kill or suspend operation if it is currently interruptible.
    // Check this; if the thread is not interruptible, simply set the signals
    // and get out. Someday, when the thread finally unblocks, it can deal with
    // the signals.
    const bool is_blocked =
        (cur_state == THREAD_BLOCKED) || (cur_state == THREAD_BLOCKED_READ_LOCK);
    if ((is_blocked || (cur_state == THREAD_SLEEPING)) &&
        (wait_queue_state_.interruptible() == Interruptible::No)) {
      clt.Finalize();
      set_signals.call();
      lock_.Release();
      return ZX_OK;
    }

    // Unblocking a thread who is blocked in a wait queue requires that we hold
    // the entire PI chain starting from the thread before proceeding.
    // Attempting to obtain this chain of locks might result in a conflict which
    // requires us to back off, releasing all locks (including the initial
    // thread's) before trying again.
    WaitQueue* const wq = wait_queue_state_.blocking_wait_queue();
    if (is_blocked && (OwnedWaitQueue::LockPiChain(*this) == ChainLock::LockResult::kBackoff)) {
      lock_.Release();
      continue;
    }

    // OK, we have now obtained all of our locks and are committed to the
    // operation.  We can go ahead and set our signal state and increment our
    // kcounters now.
    clt.Finalize();
    set_signals.call();

    switch (cur_state) {
      case THREAD_INITIAL:
        // TODO(johngro); Figure out what to do about this.  The original
        // versions of suspend and kill seem to disagree about whether or not it
        // is safe to be suspending or killing a thread at this point.  The
        // original suspend had the comment below, indicating that it should be
        // OK to unblock the thread. The Kill code, however, had this comment:
        //
        // ```
        // thread hasn't been started yet.
        // not really safe to wake it up, since it's only in this state because it's under
        // construction by the creator thread.
        // ```
        //
        // indicating that the thread was not yet safe to wake.  It really feels
        // like this should be an ASSERT (people should not be
        // suspending/killing threads in the initial state), or it should just
        // leave the thread as is.  The signal is set, and will be handled when
        // the thread ends up running for the first time.

        // Thread hasn't been started yet, add it to the run queue to transition
        // properly through the INITIAL -> READY state machine first, then it
        // will see the signal and go to SUSPEND before running user code.
        //
        // Though the state here is still INITIAL, the higher-level code has
        // already executed ThreadDispatcher::Start() so all the userspace
        // entry data has been initialized and will be ready to go as soon as
        // the thread is unsuspended.
        Scheduler::Unblock(this);
        return ZX_OK;
      case THREAD_READY:
        // thread is ready to run and not blocked or suspended.
        // will wake up and deal with the signal soon.
        break;
      case THREAD_RUNNING:
        // thread is running (on another cpu)
        // The following call is not essential.  It just makes the
        // thread suspension/kill happen sooner rather than at the next
        // timer interrupt or syscall.
        mp_interrupt(MP_IPI_TARGET_MASK, cpu_num_to_mask(scheduler_state_.curr_cpu_));
        break;
      case THREAD_BLOCKED:
      case THREAD_BLOCKED_READ_LOCK:
        // thread is blocked on something and marked interruptible.  We are
        // holding the entire PI chain at this point, and calling UnblockThread
        // on our blocking wait queue will release then entire PI chain for us
        // as part of the unblock operation.
        wq->get_lock().AssertAcquired();
        wq->UnblockThread(this, wakeup_status);
        return ZX_OK;
      case THREAD_SLEEPING:
        // thread is sleeping and interruptible
        wait_queue_state_.Unsleep(this, wakeup_status);
        return ZX_OK;
      case THREAD_SUSPENDED:
        // If this is a kill operation, and the thread is suspended, resume it
        // so it can get the kill signal.  Otherwise, do nothing.  The thread
        // was already suspended, and it still is.
        if (suspend_op == false) {
          Scheduler::Unblock(this);
          return ZX_OK;
        }
        break;
      default:
        panic("Unexpected thread state %u", cur_state);
    }

    lock_.Release();
    return ZX_OK;
  }
}

zx_status_t Thread::RestrictedKick() {
  LTRACE_ENTRY;

  canary_.Assert();
  DEBUG_ASSERT(!IsIdle());

  bool kicking_myself = (Thread::Current::Get() == this);

  // Hold the thread's lock while we examine its state and figure out what to
  // do.
  cpu_mask_t ipi_mask{0};
  {
    SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::RestrictedKick")};

    if (state() == THREAD_DEATH) {
      return ZX_ERR_BAD_STATE;
    }

    signals_.fetch_or(THREAD_SIGNAL_RESTRICTED_KICK, ktl::memory_order_relaxed);

    if (state() == THREAD_RUNNING && !kicking_myself) {
      // thread is running (on another cpu)
      // Send an IPI after dropping this thread's lock to make sure that the
      // thread processes the new signals. If the thread executes a regular
      // syscall or is rescheduled the signals will also be processed then, but
      // there's no upper bound on how long that could take.
      //
      // TODO(johngro) - what about a thread which is in a transient state
      // (active migration or being stolen).  Should we skip the IPI and just
      // make sure to force the scheduler to always re-evaluate pending signals
      // after exiting a transient state?
      ipi_mask = cpu_num_to_mask(scheduler_state_.curr_cpu_);
    }
  }

  if (ipi_mask != 0) {
    mp_interrupt(MP_IPI_TARGET_MASK, ipi_mask);
  }

  kcounter_add(thread_restricted_kick_count, 1);
  return ZX_OK;
}

// Signal an exception on the current thread, to be handled when the
// current syscall exits.  Unlike other signals, this is synchronous, in
// the sense that a thread signals itself.  This exists primarily so that
// we can unwind the stack in order to get the state of userland's
// callee-saved registers at the point where userland invoked the
// syscall.
void Thread::Current::SignalPolicyException(uint32_t policy_exception_code,
                                            uint32_t policy_exception_data) {
  Thread* t = Thread::Current::Get();
  SingletonChainLockGuardIrqSave guard{t->lock_, CLT_TAG("Thread::Current::SignalPolicyException")};
  t->signals_.fetch_or(THREAD_SIGNAL_POLICY_EXCEPTION, ktl::memory_order_relaxed);
  t->extra_policy_exception_code_ = policy_exception_code;
  t->extra_policy_exception_data_ = policy_exception_data;
}

void Thread::EraseFromListsLocked() {
  thread_list->erase(*this);
  if (migrate_list_node_.InContainer()) {
    migrate_list_.erase(*this);
  }
}

zx_status_t Thread::Join(int* out_retcode, zx_time_t deadline) {
  canary_.Assert();

  // No thread should be attempting to join itself.
  Thread* const current_thread = Thread::Current::Get();
  DEBUG_ASSERT(this != current_thread);

  for (bool finished = false; !finished;) {
    ChainLockTransactionIrqSave clt{CLT_TAG("Thread::Join")};
    for (;; clt.Relax()) {
      // Start by locking the global thread list lock, and the target thread's lock.
      Guard<SpinLock, NoIrqSave> list_guard{&list_lock_};
      UnconditionalChainLockGuard guard{lock_};

      if (flags_ & THREAD_FLAG_DETACHED) {
        // the thread is detached, go ahead and exit
        return ZX_ERR_BAD_STATE;
      }

      // If we need to wait for our thread to die, we need exchange our current
      // locks (the target thread's lock and the list lock) for the current thread
      // and the wait_queue's lock.  If this operation fails with a back-off
      // error, we need to drop all of our locks and try again.
      if (state() != THREAD_DEATH) {
        ktl::array lock_set{&current_thread->get_lock(), &task_state_.get_lock()};
        if (AcquireChainLockSet(lock_set) == ChainLock::LockResult::kBackoff) {
          continue;
        }
        current_thread->get_lock().AssertAcquired();
        task_state_.get_lock().AssertAcquired();

        // We now have all of the locks we need for this operation.
        clt.Finalize();

        // Now go ahead and drop our other locks, and block in the wait queue.
        // This will release the wait queue's lock for us, and will release and
        // re-acquire our thread's lock (as we block and eventually become
        // rescheduled).  Once we are done waiting, drop the current thread's
        // lock, then either start again, or propagate any wait error we encounter
        // up the stack.
        guard.Release();
        list_guard.Release();
        const zx_status_t status = task_state_.Join(current_thread, deadline);
        current_thread->get_lock().Release();
        if (status != ZX_OK) {
          return status;
        }

        // break out of the lock-acquisition loop, but do not set the finished
        // flag.  This way, we will start a ChainLockTransaction on the new
        // check of the thread's state instead of attempting to use our already
        // finalized transaction.
        break;
      }

      canary_.Assert();
      DEBUG_ASSERT(state() == THREAD_DEATH);
      wait_queue_state_.AssertNotBlocked();

      // save the return code
      if (out_retcode) {
        *out_retcode = task_state_.retcode();
      }

      // remove it from global lists
      EraseFromListsLocked();

      // Our canary_ will be cleared out in free_thread_resources, which
      // explicitly invokes ~Thread.  Set the finished flag and break out of our
      // retry loop, dropping our locks in the process.
      finished = true;
      break;
    }
  }

  free_thread_resources(this);

  kcounter_add(thread_join_count, 1);

  return ZX_OK;
}

zx_status_t Thread::Detach() {
  canary_.Assert();

  ChainLockTransactionPreemptDisableAndIrqSave clt{CLT_TAG("Thread::Detach")};
  for (;; clt.Relax()) {
    // Lock the target thread's state before proceeding.
    UnconditionalChainLockGuard guard{lock_};

    // Try to wake our joiners with the error "BAD_STATE" (the thread is now
    // detached and can no longer be joined).  If we fail, we need to drop our
    // locks and try again.  If we succeed, our transaction will be finalized
    // and we can finish updating all of our state.
    if (task_state_.TryWakeJoiners(ZX_ERR_BAD_STATE) == false) {
      continue;
    }

    // If the target thread is not yet dead, flag it as detached and get out.
    if (state() != THREAD_DEATH) {
      flags_ |= THREAD_FLAG_DETACHED;
      return ZX_OK;
    }

    // Looks like the thread has already died.  Make sure the DETACHED flag has
    // been cleared (so that Join continues), then drop our lock and Join to
    // finish the cleanup.
    flags_ &= ~THREAD_FLAG_DETACHED;  // makes sure Join continues
    break;
  }

  return Join(nullptr, 0);
}

// called back in the DPC worker thread to free the stack and/or the thread structure
// itself for a thread that is exiting on its own.
void Thread::FreeDpc(Dpc* dpc) {
  Thread* t = dpc->arg<Thread>();

  t->canary_.Assert();

  // grab and release the thread's lock, which effectively serializes us with
  // the thread that is queuing itself for destruction.  It ensures that:
  //
  // 1) The thread is no longer on any lists or referenced in any way.
  // 2) The thread is no longer assigned to any scheduler, and it has already
  //    entered the scheduler for the final time.
  {
    SingletonChainLockGuardIrqSave guard{t->get_lock(), CLT_TAG("Thread::FreeDpc")};
    DEBUG_ASSERT(t->state() == THREAD_DEATH);
    ktl::atomic_signal_fence(ktl::memory_order_seq_cst);
  }

  free_thread_resources(t);
}

/**
 * @brief Remove this thread from the scheduler, discarding
 * its execution state.
 *
 * This is almost certainly not the function you want.  In the general case,
 * this is incredibly unsafe.
 *
 * This will free any resources allocated by thread_create.
 */
void Thread::Forget() {
  DEBUG_ASSERT(Thread::Current::Get() != this);

  {
    Guard<SpinLock, IrqSave> list_guard{&list_lock_};
    SingletonChainLockGuardNoIrqSave guard{lock_, CLT_TAG("Thread::Forget")};
    DEBUG_ASSERT(!wait_queue_state_.InWaitQueue());
    EraseFromListsLocked();
  }

  free_thread_resources(this);
}

/**
 * @brief  Terminate the current thread
 *
 * Current thread exits with the specified return code.
 *
 * This function does not return.
 */
__NO_RETURN void Thread::Current::Exit(int retcode) {
  // create a dpc on the stack to queue up a free.
  // must be put at top scope in this function to force the compiler to keep it from
  // reusing the stack before the function exits
  Dpc free_dpc;

  Thread* const current_thread = Thread::Current::Get();
  current_thread->canary_.Assert();
  DEBUG_ASSERT(!current_thread->IsIdle());

  if (current_thread->user_thread_) {
    DEBUG_ASSERT(!arch_ints_disabled());
    current_thread->user_thread_->ExitingCurrent();
  }

  // Start by locking this thread, and setting the flag which indicates that it
  // can no longer be the owner of any OwnedWaitQueues in the system.  This will
  // ensure that the OWQ code no longer allows the thread to become the owner of
  // any queues.
  //
  AnnotatedAutoPreemptDisabler aapd;
  InterruptDisableGuard irqd;
  {
    SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                           CLT_TAG("Thread::Current::Exit deny WQ ownership")};
    current_thread->can_own_wait_queues_ = false;
  }

  // Now that that we can no longer own queues, we can disown any queues that we
  // currently happen to own.
  OwnedWaitQueue::DisownAllQueues(current_thread);

  // Now, to complete the exit operation, we must be holding this thread's lock in
  // addition to the global thread list lock.
  bool queue_free_dpc{false};
  {
    Guard<SpinLock, NoIrqSave> list_guard{&list_lock_};
    SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                           CLT_TAG("Thread::Current::Exit finish in list_guard")};

    // enter the dead state and finish any migration.
    Scheduler::RunInLockedCurrentScheduler([current_thread]() {
      ChainLockTransaction::AssertActive();
      current_thread->get_lock().AssertHeld();
      current_thread->set_death();
    });
    current_thread->task_state_.set_retcode(retcode);
    current_thread->CallMigrateFnLocked(Thread::MigrateStage::Exiting);

    // if we're detached, then do our teardown here
    if (current_thread->flags_ & THREAD_FLAG_DETACHED) {
      kcounter_add(thread_detached_exit_count, 1);

      // remove it from global lists and drop the global list lock.
      current_thread->EraseFromListsLocked();
      list_guard.Release();

      // Remember to queue a dpc to free the stack and, optionally, the thread
      // structure
      //
      // We are detached and will need to queue a DPC in order to clean up our
      // thread structure and stack after we are gone.  Queueing a DPC will
      // involve signaling the DPC thread, so we (technically) need to drop our
      // thread's lock and end our current chain lock transaction  before doing
      // so.
      //
      // Preemption is disabled, interrupts are off, and DPC threads always run
      // on the CPU they were queued from.  Because of this, we can be sure that
      // the DPC thread is not going to preempt us and free our stack out from
      // under us before we manage to complete our final reschedule and context
      // switch.
      //
      // TODO(johngro): I cannot think of a way where waking up a DPC thread
      // should result in us deadlocking in a lock cycle.  Logically, our
      // current thread is no longer visible to anyone.
      //
      // 1) We are the currently running thread in a scheduler which cannot
      //    currently reschedule (until we drop into our final reschedule).
      // 2) We are not in any wait queues.
      // 3) We have become disconnected from our ThreadDispatcher and all
      //    handles referring to it.
      //
      // Waking the DPC thread would involve holding the DPC thread's lock and
      // its wait queues lock in order to remove the thread from the queue,
      // followed by holding our schedulers lock to insert the DPC thread.
      //
      // In _theory_ it should be OK to use our existing ChainLockTransaction to
      // queue the DPC while holding our thread's lock.  If we can prove that
      // this is safe, it may be a good idea to come back here later and queue
      // the DPC while holding the thread's lock, just to simplify the structure
      // of the code around here.
      if (current_thread->stack_.base() || (current_thread->flags_ & THREAD_FLAG_FREE_STRUCT)) {
        queue_free_dpc = true;
      }
    } else {
      // Looks like we didn't need the global list lock after all.  Drop it and
      // signal anyone who is waiting to join us.
      list_guard.Release();

      // Our thread is both running, and exiting.  It is not a member of any
      // wait queue, and cannot be rescheduled (preemption is disabled).  It
      // should not be possible for it to be involved in any lock cycles, so we
      // are free to keep trying to to wake our joiners until we finally
      // succeed.
      //
      // Do not drop our thread's lock here, we *must* hold it until after the
      // final reschedule is complete.  Failure to do this means that a joiner
      // thread might wake up and free our stack out from under us before our
      // final reschedule.
      //
      // TODO(johngro): TryWakeJoiners may need to lock a wait queue and more
      // than one thread in order to wake the current set of joiners.  We have
      // already finalized our transaction at this point, and are still holding
      // a lock.  Bending the rules here requires that we do something we really
      // don't want to be doing, which is to undo the Finalized state of the
      // transaction while we are still holding a lock.
      //
      // It would be *much* cleaner if we didn't have to do this.  We would
      // rather be in a position to drop our thread's lock and allow an
      // unconditional wake of our joiners instead.
      //
      // So, look introducing a new lock (the thread cleanup spinlock?) which
      // could provide us the protection we would need.  The idea would be:
      //
      // 1) Earlier in this function, obtain this new cleanup lock.
      // 2) When we get to here, drop the thread's lock for the wakeup
      //    operation.
      // 3) Once wakeup is complete, re-obtain the thread's lock.
      // 4) Drop the cleanup lock.
      // 5) Enter the final reschedule.
      //
      // On the joiner/cleanup side of things, the last joiner out of the door
      // would just need to:
      //
      // 1) Obtain the cleanup lock.
      // 2) Obtain the thread's lock.
      // 3) Drop all locks.  We have now synced up with everyone else and should
      //    be free to cleanup the memory now.
      ChainLockTransaction& active_clt = ChainLockTransaction::ActiveRef();
      active_clt.Restart(CLT_TAG("Thread::Current::Exit wake joiners"));
      while (current_thread->task_state_.TryWakeJoiners(ZX_OK) == false) {
        // Note, we are still holding the current thread's lock, so we cannot
        // fully relax the active CLT (which would demand that we hold zero
        // locks).  See the note above about potentially finding a way to be
        // able to drop the current thread's lock here.
        arch::Yield();
      }
    }

    if (!queue_free_dpc) {
      // Drop into the final reschedule while still holding our lock.  There
      // should be no coming back from this.  We may have gotten here because we
      // were still joinable, or because we were detached but had a statically
      // allocated stack/thread-struct, but either way, we don't need to drop and
      // re-acquire our thread's lock in order to finish exiting at this point.
      Scheduler::RescheduleInternal(current_thread);
      panic("somehow fell through thread_exit()\n");
    }
  }

  // It should not be possible to get to this point without needing to drop our
  // locks and queue a DPC to clean ourselves up.
  ASSERT(queue_free_dpc);
  free_dpc = Dpc(&Thread::FreeDpc, current_thread);
  [[maybe_unused]] zx_status_t status = free_dpc.Queue();
  DEBUG_ASSERT(status == ZX_OK);

  // Relock our thread one last time before dropping into our final reschedule
  // operation.
  SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                         CLT_TAG("Thread::Current::Exit final reschedule")};
  Scheduler::RescheduleInternal(current_thread);
  panic("somehow fell through thread_exit()\n");
}

void Thread::Current::Kill() {
  Thread* current_thread = Thread::Current::Get();

  current_thread->canary_.Assert();
  DEBUG_ASSERT(!current_thread->IsIdle());

  current_thread->Kill();
}

cpu_mask_t Thread::SetCpuAffinity(cpu_mask_t affinity) {
  canary_.Assert();
  return Scheduler::SetCpuAffinity<Affinity::Hard>(*this, affinity);
}

cpu_mask_t Thread::GetCpuAffinity() const {
  canary_.Assert();
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::GetCpuAffinity")};
  return scheduler_state_.hard_affinity();
}

cpu_mask_t Thread::SetSoftCpuAffinity(cpu_mask_t affinity) {
  canary_.Assert();
  return Scheduler::SetCpuAffinity<Affinity::Soft>(*this, affinity);
}

cpu_mask_t Thread::GetSoftCpuAffinity() const {
  canary_.Assert();
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::GetSoftCpuAffinity")};
  return scheduler_state_.soft_affinity_;
}

void Thread::Current::MigrateToCpu(const cpu_num_t target_cpu) {
  Thread::Current::Get()->SetCpuAffinity(cpu_num_to_mask(target_cpu));
}

void Thread::SetMigrateFn(MigrateFn migrate_fn) {
  Guard<SpinLock, IrqSave> list_guard{&get_list_lock()};
  SingletonChainLockGuardNoIrqSave thread_guard{lock_, CLT_TAG("Thread::SetMigrateFn")};
  SetMigrateFnLocked(ktl::move(migrate_fn));
}

void Thread::SetMigrateFnLocked(MigrateFn migrate_fn) {
  Scheduler::RunInThreadsSchedulerLocked(this, [this, &migrate_fn]() {
    ChainLockTransaction::AssertActive();
    get_lock().AssertHeld();
    get_list_lock().lock().AssertHeld();

    // We should never be assigning a new migration function while there is a
    // migration still in progress.
    DEBUG_ASSERT(!migrate_fn || !migrate_pending_);

    // If |migrate_fn_| was previously set, remove |this| from |migrate_list_|.
    if (migrate_fn_) {
      migrate_list_.erase(*this);
    }

    migrate_fn_ = ktl::move(migrate_fn);

    // Clear stale state when (un) setting the migrate fn.
    //
    // TODO(https://fxbug.dev/42164826): Cleanup the migrate fn feature and associated state
    // and clearly define and check invariants.
    migrate_pending_ = false;

    // If |migrate_fn_| is valid, add |this| to |migrate_list_|.
    if (migrate_fn_) {
      migrate_list_.push_front(this);
    }
  });
}

void Thread::CallMigrateFnLocked(MigrateStage stage) {
  if (unlikely(migrate_fn_)) {
    switch (stage) {
      case MigrateStage::Before:
        if (!migrate_pending_) {
          // We are leaving our last CPU and calling our migration function as we
          // go.  Assert that we are running on the proper CPU, and clear our last
          // cpu bookkeeping to indicate that the migration has started.
          DEBUG_ASSERT_MSG(scheduler_state().last_cpu_ == arch_curr_cpu_num(),
                           "Attempting to run Before stage of migration on a CPU "
                           "which is not the last CPU the thread ran on (last cpu = "
                           "%u, curr cpu = %u)\n",
                           scheduler_state().last_cpu_, arch_curr_cpu_num());
          migrate_pending_ = true;
          migrate_fn_(this, stage);
        }
        break;

      case MigrateStage::After:
        if (migrate_pending_) {
          migrate_pending_ = false;
          migrate_fn_(this, stage);
        }
        break;

      case MigrateStage::Exiting:
        migrate_fn_(this, stage);
        break;
    }
  }
}

// Go over every thread which has a migrate function assigned to it, and which
// last ran on the current CPU, but is not in the ready state.  The current CPU
// is becoming unavailable, and the currently running thread is the last change
// anything is going to have to run on this CPU for a while.  If there are
// threads out there which are blocked, but which need to record some per-cpu
// state (eg; VCPU threads), this will be their last chance to do so.  The next
// time they become scheduled to run, they are going to run on a different CPU.
void Thread::CallMigrateFnForCpu(cpu_num_t cpu) {
  DEBUG_ASSERT(arch_ints_disabled());
  Guard<SpinLock, NoIrqSave> list_guard{&list_lock_};

  for (auto& thread : migrate_list_) {
    SingletonChainLockGuardNoIrqSave thread_guard{thread.lock_,
                                                  CLT_TAG("Thread::CallMigrateFnForCpu")};
    if (thread.state() != THREAD_READY && thread.scheduler_state().last_cpu_ == cpu) {
      thread.CallMigrateFnLocked(Thread::MigrateStage::Before);
    }
  }
}

void Thread::SetContextSwitchFn(ContextSwitchFn context_switch_fn) {
  canary_.Assert();
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::SetContextSwitchFn")};
  SetContextSwitchFnLocked(ktl::move(context_switch_fn));
}

void Thread::SetContextSwitchFnLocked(ContextSwitchFn context_switch_fn) {
  canary_.Assert();
  context_switch_fn_ = ktl::move(context_switch_fn);
}

bool Thread::CheckKillSignal() {
  if (signals() & THREAD_SIGNAL_KILL) {
    // Ensure we don't recurse into thread_exit.
    DEBUG_ASSERT(state() != THREAD_DEATH);
    return true;
  } else {
    return false;
  }
}

zx_status_t Thread::CheckKillOrSuspendSignal() const {
  const auto current_signals = signals();
  if (unlikely(current_signals & THREAD_SIGNAL_KILL)) {
    return ZX_ERR_INTERNAL_INTR_KILLED;
  }
  if (unlikely(current_signals & THREAD_SIGNAL_SUSPEND)) {
    return ZX_ERR_INTERNAL_INTR_RETRY;
  }
  return ZX_OK;
}

// finish suspending the current thread
void Thread::Current::DoSuspend() {
  Thread* const current_thread = Thread::Current::Get();

  // Note: After calling this callback, we must not return without
  // calling the callback with THREAD_USER_STATE_RESUME.  That is
  // because those callbacks act as barriers which control when it is
  // safe for the zx_thread_read_state()/zx_thread_write_state()
  // syscalls to access the userland register state kept by Thread.
  if (current_thread->user_thread_) {
    DEBUG_ASSERT(!arch_ints_disabled());
    current_thread->user_thread_->Suspending();
  }

  bool do_exit{false};
  {
    // Hold the thread's lock while we set up the suspend operation.
    SingletonChainLockGuardIrqSave guard{current_thread->lock_,
                                         CLT_TAG("Thread::Current::DoSuspend")};

    // make sure we haven't been killed while the lock was dropped for the user callback
    if (current_thread->CheckKillSignal()) {
      // Exit the thread, but only after we have dropped our locks and
      // re-enabled IRQs.
      do_exit = true;
    }
    // Make sure the suspend signal wasn't cleared while we were running the
    // callback.
    else if (current_thread->signals() & THREAD_SIGNAL_SUSPEND) {
      Scheduler::RunInLockedCurrentScheduler([current_thread]() {
        ChainLockTransaction::AssertActive();
        current_thread->get_lock().AssertHeld();
        current_thread->set_suspended();
      });
      current_thread->signals_.fetch_and(~THREAD_SIGNAL_SUSPEND, ktl::memory_order_relaxed);

      // directly invoke the context switch, since we've already manipulated
      // this thread's state. Note that our thread's lock will be dropped and
      // re-acquired as we block and later become re-scheduled.
      Scheduler::RescheduleInternal(current_thread);

      // If the thread was killed while we were suspended, we should not allow
      // it to resume.  We shouldn't call user_callback() with
      // THREAD_USER_STATE_RESUME in this case, because there might not have
      // been any request to resume the thread.
      if (current_thread->CheckKillSignal()) {
        // Exit the thread, but only after we have dropped our locks and
        // re-enabled IRQs.
        do_exit = true;
      }
    }
  }

  if (do_exit) {
    Thread::Current::Exit(0);
  }

  if (current_thread->user_thread_) {
    DEBUG_ASSERT(!arch_ints_disabled() || !thread_lock.IsHeld());
    current_thread->user_thread_->Resuming();
  }
}

void Thread::SignalSampleStack(Timer* timer, zx_time_t, void* per_cpu_state) {
  // Regardless of if the thread is marked to be sampled or not we'll set the sample_stack thread
  // signal. This reduces the time we spend in the interrupt context and means we don't need to grab
  // a lock here. When we handle the thread signal in ProcessPendingSignals we'll check if the
  // thread actually needs to be sampled.
  Thread* current_thread = Thread::Current::Get();
  current_thread->canary_.Assert();
  current_thread->signals_.fetch_or(THREAD_SIGNAL_SAMPLE_STACK, ktl::memory_order_relaxed);

  // We set the timer here as opposed to when we handle the THREAD_SIGNAL_SAMPLE_STACK as a thread
  // could be suspended or killed before the sample signal is handled.
  reinterpret_cast<sampler::internal::PerCpuState*>(per_cpu_state)->SetTimer();
}

void Thread::Current::DoSampleStack(GeneralRegsSource source, void* gregs) {
  DEBUG_ASSERT(!arch_ints_disabled());
  Thread* current_thread = Thread::Current::Get();

  // Make sure the sample signal wasn't cleared while we were running the
  // callback.
  if (current_thread->signals() & THREAD_SIGNAL_SAMPLE_STACK) {
    current_thread->signals_.fetch_and(~THREAD_SIGNAL_SAMPLE_STACK, ktl::memory_order_relaxed);

    if (current_thread->user_thread() == nullptr) {
      // There's no user thread to sample, just move on.
      return;
    }

    const uint64_t expected_sampler = current_thread->user_thread()->SamplerId();

    // If a thread was marked to be sampled but was first suspended, it may now be long after the
    // sampling session has ended. sampler::SampleThread grabs the global state, checks if it's
    // valid and if the session is the one we were expecting to sample to before attempting a
    // sample.
    auto sampler_result = sampler::ThreadSamplerDispatcher::SampleThread(
        current_thread->pid(), current_thread->tid(), source, gregs, expected_sampler);
    // ZX_ERR_NOT_SUPPORTED indicates that we didn't take a sample, but that was intentional and we
    // should move on.
    if (sampler_result.is_error() && sampler_result.error_value() != ZX_ERR_NOT_SUPPORTED) {
      // Any other error means sampling failed for this thread and likely won't succeed in the
      // future. Likely either the global sampler is now disabled or the per cpu buffer is full.
      // Disable future attempts to sample.
      kcounter_add(thread_sampling_failed, 1);
      current_thread->user_thread()->DisableStackSampling();
    }
  }
}

bool Thread::SaveUserStateLocked() {
  DEBUG_ASSERT(this == Thread::Current::Get());
  DEBUG_ASSERT(user_thread_ != nullptr);

  if (user_state_saved_) {
    return false;
  }
  user_state_saved_ = true;
  arch_save_user_state(this);
  return true;
}

void Thread::RestoreUserStateLocked() {
  DEBUG_ASSERT(this == Thread::Current::Get());
  DEBUG_ASSERT(user_thread_ != nullptr);

  DEBUG_ASSERT(user_state_saved_);
  user_state_saved_ = false;
  arch_restore_user_state(this);
}

ScopedThreadExceptionContext::ScopedThreadExceptionContext(const arch_exception_context_t* context)
    : thread_(Thread::Current::Get()), context_(context) {
  SingletonChainLockGuardIrqSave guard{thread_->get_lock(),
                                       CLT_TAG("ScopedThreadExceptionContext")};

  // It's possible that the context and state have been installed/saved earlier in the call chain.
  // If so, then it's some other object's responsibility to remove/restore.
  need_to_remove_ = arch_install_exception_context(thread_, context_);
  need_to_restore_ = thread_->SaveUserStateLocked();
}

ScopedThreadExceptionContext::~ScopedThreadExceptionContext() {
  SingletonChainLockGuardIrqSave guard{thread_->get_lock(),
                                       CLT_TAG("~ScopedThreadExceptionContext")};

  // Did we save the state?  If so, then it's our job to restore it.
  if (need_to_restore_) {
    thread_->RestoreUserStateLocked();
  }
  // Did we install the exception context? If so, then it's out job to remove it.
  if (need_to_remove_) {
    arch_remove_exception_context(thread_);
  }
}

void Thread::Current::ProcessPendingSignals(GeneralRegsSource source, void* gregs) {
  // Prior to calling this method, interrupts must be disabled.  This method may enable interrupts,
  // but if it does, it will disable them prior to returning.
  //
  // TODO(maniscalco): Refer the reader to the to-be-written theory of operations documentation for
  // kernel thread signals.
  DEBUG_ASSERT(arch_ints_disabled());

  Thread* const current_thread = Thread::Current::Get();

  // IF we're currently in restricted mode, we may decide to exit to normal mode instead as part
  // of signal processing. Store this information in a local so that we can process all signals
  // before actually exiting.
  bool exit_to_normal_mode = false;

  // It's possible for certain signals to be asserted, processed, and then re-asserted during this
  // method so loop until there are no pending signals.
  unsigned int signals;
  while ((signals = current_thread->signals()) != 0) {
    // THREAD_SIGNAL_KILL
    //
    // We check this signal first because if asserted, the thread will terminate so there's no point
    // in checking other signals before kill.
    if (signals & THREAD_SIGNAL_KILL) {
      // We're going to call Exit, which generates a user-visible exception on user threads.  If
      // this thread has user mode component, call arch_set_suspended_general_regs() to make the
      // general registers available to a debugger during the exception.
      if (current_thread->user_thread_) {
        // TODO(https://fxbug.dev/42076855): Do we need to hold the thread's lock here?
        SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                               CLT_TAG("Thread::Current::ProcessPendingSignals")};
        arch_set_suspended_general_regs(current_thread, source, gregs);
      }

      // Thread::Current::Exit may only be called with interrupts enabled.  Note, this is thread is
      // committed to terminating and will never return so we don't need to worry about disabling
      // interrupts post-Exit.
      arch_enable_ints();
      Thread::Current::Exit(0);

      __UNREACHABLE;
    }

    const bool has_user_thread = current_thread->user_thread_ != nullptr;

    // THREAD_SIGNAL_POLICY_EXCEPTION
    //
    if (signals & THREAD_SIGNAL_POLICY_EXCEPTION) {
      DEBUG_ASSERT(has_user_thread);
      // TODO(https://fxbug.dev/42077109): Consider wrapping this up in a method
      // (e.g. Thread::Current::ClearSignals) and think hard about whether relaxed is sufficient.
      current_thread->signals_.fetch_and(~THREAD_SIGNAL_POLICY_EXCEPTION,
                                         ktl::memory_order_relaxed);

      uint32_t policy_exception_code;
      uint32_t policy_exception_data;
      {
        // TODO(https://fxbug.dev/42076855): Do we need to hold the thread's lock here?
        SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                               CLT_TAG("Thread::Current::ProcessPendingSignals")};

        // Policy exceptions are user-visible so must make the general register state available to
        // a debugger.
        arch_set_suspended_general_regs(current_thread, source, gregs);

        policy_exception_code = current_thread->extra_policy_exception_code_;
        policy_exception_data = current_thread->extra_policy_exception_data_;
      }

      // Call arch_dispatch_user_policy_exception with interrupts enabled, but be sure to disable
      // them afterwards.
      arch_enable_ints();
      zx_status_t status =
          arch_dispatch_user_policy_exception(policy_exception_code, policy_exception_data);
      ZX_ASSERT_MSG(status == ZX_OK, "arch_dispatch_user_policy_exception() failed: status=%d\n",
                    status);
      arch_disable_ints();

      {
        // TODO(https://fxbug.dev/42076855): Do we need to hold the thread's lock here?
        SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                               CLT_TAG("Thread::Current::ProcessPendingSignals")};
        arch_reset_suspended_general_regs(current_thread);
      }
    }

    // THREAD_SIGNAL_SUSPEND
    //
    if (signals & THREAD_SIGNAL_SUSPEND) {
      if (has_user_thread) {
        bool saved;
        {
          // TODO(https://fxbug.dev/42076855): Do we need to hold the thread's lock here?
          SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                                 CLT_TAG("Thread::Current::ProcessPendingSignals")};

          // This thread has been asked to suspend.  When a user thread is suspended, its full
          // register state (not just the general purpose registers) is accessible to a debugger.
          arch_set_suspended_general_regs(current_thread, source, gregs);
          saved = current_thread->SaveUserStateLocked();
        }

        // The enclosing function, is called at the boundary of kernel and user mode (e.g. just
        // before returning from a syscall, timer interrupt, or architectural exception/fault).
        // We're about the perform a save.  If the save fails (returns false), then we likely have a
        // mismatched save/restore pair, which is a bug.
        DEBUG_ASSERT(saved);

        arch_enable_ints();
        Thread::Current::DoSuspend();
        arch_disable_ints();

        {
          // TODO(https://fxbug.dev/42076855): Do we need to hold the thread's lock here?
          SingletonChainLockGuardNoIrqSave guard{current_thread->lock_,
                                                 CLT_TAG("Thread::Current::ProcessPendingSignals")};

          if (saved) {
            current_thread->RestoreUserStateLocked();
          }
          arch_reset_suspended_general_regs(current_thread);
        }
      } else {
        // No user mode component so we don't need to save any register state.
        arch_enable_ints();
        Thread::Current::DoSuspend();
        arch_disable_ints();
      }
    }

    // THREAD_SIGNAL_RESTRICTED_KICK
    //
    if (signals & THREAD_SIGNAL_RESTRICTED_KICK) {
      current_thread->signals_.fetch_and(~THREAD_SIGNAL_RESTRICTED_KICK, ktl::memory_order_relaxed);
      if (arch_get_restricted_flag()) {
        exit_to_normal_mode = true;
      } else {
        // If we aren't currently in restricted mode,Remember that we have a restricted kick pending
        // for the next time we try to enter restricted mode.
        current_thread->set_restricted_kick_pending(true);
      }
    }

    if (signals & THREAD_SIGNAL_SAMPLE_STACK) {
      // Sampling the user stack may page fault as we try to do usercopies.
      arch_enable_ints();
      Thread::Current::DoSampleStack(source, gregs);
      arch_disable_ints();
    }
  }

  // Interrupts must remain disabled for the remainder of this function. If for any reason we need
  // to enable interrupts in handling we have to re-enter the loop above in order to process signals
  // that may have been raised.

  if (exit_to_normal_mode) {
    switch (source) {
      case GeneralRegsSource::Iframe: {
        const iframe_t* iframe = reinterpret_cast<const iframe_t*>(gregs);
        RestrictedLeaveIframe(iframe, ZX_RESTRICTED_REASON_KICK);

        __UNREACHABLE;
      }
#if defined(__x86_64__)
      case GeneralRegsSource::Syscall: {
        const syscall_regs_t* syscall_regs = reinterpret_cast<const syscall_regs_t*>(gregs);
        RestrictedLeaveSyscall(syscall_regs, ZX_RESTRICTED_REASON_KICK);

        __UNREACHABLE;
      }
#endif  // defined(__x86_64__)
      default:
        DEBUG_ASSERT_MSG(false, "invalid source %u\n", static_cast<uint32_t>(source));
    }
  }
}

bool Thread::Current::CheckForRestrictedKick() {
  LTRACE_ENTRY;

  DEBUG_ASSERT(arch_ints_disabled());

  Thread* current_thread = Thread::Current::Get();
  if (current_thread->restricted_kick_pending()) {
    current_thread->set_restricted_kick_pending(false);
    return true;
  }

  return false;
}

/**
 * @brief Yield the cpu to another thread
 *
 * This function places the current thread at the end of the run queue
 * and yields the cpu to another waiting thread (if any.)
 *
 * This function will return at some later time. Possibly immediately if
 * no other threads are waiting to execute.
 */
void Thread::Current::Yield() {
  Thread* current_thread = Thread::Current::Get();

  current_thread->canary_.Assert();
  DEBUG_ASSERT(!arch_blocking_disallowed());

  SingletonChainLockGuardIrqSave guard{current_thread->lock_, CLT_TAG("Thread::Current::Yield")};
  DEBUG_ASSERT(current_thread->state() == THREAD_RUNNING);

  CPU_STATS_INC(yields);
  Scheduler::Yield(current_thread);
}

/**
 * @brief Preempt the current thread from an interrupt
 *
 * This function places the current thread at the head of the run
 * queue and then yields the cpu to another thread.
 */
void Thread::Current::Preempt() {
  Thread* current_thread = Thread::Current::Get();

  current_thread->canary_.Assert();
  DEBUG_ASSERT(!arch_blocking_disallowed());

  if (!current_thread->IsIdle()) {
    // only track when a meaningful preempt happens
    CPU_STATS_INC(irq_preempts);
  }

  Scheduler::Preempt();
}

/**
 * @brief Reevaluate the run queue on the current cpu.
 *
 * This function places the current thread at the head of the run
 * queue and then yields the cpu to another thread. Similar to
 * thread_preempt, but intended to be used at non interrupt context.
 */
void Thread::Current::Reschedule() {
  Thread* current_thread = Thread::Current::Get();

  current_thread->canary_.Assert();
  DEBUG_ASSERT(!arch_blocking_disallowed());

  SingletonChainLockGuardIrqSave guard{current_thread->lock_,
                                       CLT_TAG("Thread::Current::Reschedule")};

  DEBUG_ASSERT(current_thread->state() == THREAD_RUNNING);
  Scheduler::Reschedule(current_thread);
}

void PreemptionState::SetPreemptionTimerForExtension(zx_time_t deadline) {
  // Interrupts must be disabled when calling PreemptReset.
  InterruptDisableGuard interrupt_disable;
  percpu::Get(arch_curr_cpu_num()).timer_queue.PreemptReset(deadline);
  kcounter_add(thread_timeslice_extended, 1);
}

void PreemptionState::FlushPendingContinued(Flush flush) {
  // If we're flushing the local CPU, make sure OK to block since flushing
  // local may trigger a reschedule.
  DEBUG_ASSERT(((flush & FlushLocal) == 0) || !arch_blocking_disallowed());

  InterruptDisableGuard interrupt_disable;
  // Recheck, pending preemptions could have been flushed by a context switch
  // before interrupts were disabled.
  const cpu_mask_t pending_mask = preempts_pending_;

  // If there is a pending local preemption the scheduler will take care of
  // flushing all pending reschedules.
  const cpu_mask_t current_cpu_mask = cpu_num_to_mask(arch_curr_cpu_num());
  if ((pending_mask & current_cpu_mask) != 0 && (flush & FlushLocal) != 0) {
    // Clear the local preempt pending flag before calling preempt.  Failure
    // to do this can cause recursion during Scheduler::Preempt if any code
    // (such as debug tracing code) attempts to disable and re-enable
    // preemption during the scheduling operation.
    preempts_pending_ &= ~current_cpu_mask;

    // TODO(johngro): We cannot be holding the current thread's lock while we do
    // this.  Is there a good way to enforce this requirement via either static
    // annotation or dynamic checks?
    Scheduler::Preempt();
  } else if ((flush & FlushRemote) != 0) {
    // The current cpu is ignored by mp_reschedule if present in the mask.
    mp_reschedule(pending_mask, 0);
    preempts_pending_ &= current_cpu_mask;
  }
}

// timer callback to wake up a sleeping thread
void Thread::SleepHandler(Timer* timer, zx_time_t now, void* arg) {
  Thread* t = static_cast<Thread*>(arg);
  t->canary_.Assert();
  t->HandleSleep(timer, now);
}

void Thread::HandleSleep(Timer* timer, zx_time_t now) {
  // spin trylocking on the thread lock since the routine that set up the
  // callback, thread_sleep_etc, may be trying to simultaneously cancel this
  // timer while holding the thread_lock.
  ChainLockTransactionIrqSave clt{CLT_TAG("HandleSleep")};
  if (timer->TrylockOrCancel(lock_)) {
    return;
  }

  // We only need to be holding the thread's lock in order "unsleep" it.  It is
  // not waiting in a wait queue, so there is no WaitQueue lock which needs to
  // be held.
  clt.Finalize();

  if (state() != THREAD_SLEEPING) {
    lock_.Release();
    return;
  }

  // Unblock the thread, regardless of whether the sleep was interruptible.  Not
  // that calling Unsleep will cause the scheduler to drop the thread's lock for
  // us after it has been successfully assigned to a scheduler instance.
  wait_queue_state_.Unsleep(this, ZX_OK);
}

#define MIN_SLEEP_SLACK ZX_USEC(1)
#define MAX_SLEEP_SLACK ZX_SEC(1)
#define DIV_SLEEP_SLACK 10u

// computes the amount of slack the thread_sleep timer will use
static zx_duration_t sleep_slack(zx_time_t deadline, zx_time_t now) {
  if (deadline < now) {
    return MIN_SLEEP_SLACK;
  }
  zx_duration_t slack = zx_time_sub_time(deadline, now) / DIV_SLEEP_SLACK;
  return ktl::max(MIN_SLEEP_SLACK, ktl::min(slack, MAX_SLEEP_SLACK));
}

/**
 * @brief  Put thread to sleep; deadline specified in ns
 *
 * This function puts the current thread to sleep until the specified
 * deadline has occurred.
 *
 * Note that this function could continue to sleep after the specified deadline
 * if other threads are running.  When the deadline occurrs, this thread will
 * be placed at the head of the run queue.
 *
 * interruptible argument allows this routine to return early if the thread was signaled
 * for something.
 */
zx_status_t Thread::Current::SleepEtc(const Deadline& deadline, Interruptible interruptible,
                                      zx_time_t now) {
  Thread* current_thread = Thread::Current::Get();

  current_thread->canary_.Assert();
  DEBUG_ASSERT(!current_thread->IsIdle());
  DEBUG_ASSERT(!arch_blocking_disallowed());

  // Skip all of the work if the deadline has already passed.
  if (deadline.when() <= now) {
    return ZX_OK;
  }

  Timer timer;
  zx_status_t final_blocked_status;
  {
    SingletonChainLockGuardIrqSave guard{current_thread->lock_,
                                         CLT_TAG("Thread::Current::SleepEtc")};
    DEBUG_ASSERT(current_thread->state() == THREAD_RUNNING);

    // if we've been killed and going in interruptible, abort here
    if (interruptible == Interruptible::Yes && unlikely((current_thread->signals()))) {
      if (current_thread->signals() & THREAD_SIGNAL_KILL) {
        return ZX_ERR_INTERNAL_INTR_KILLED;
      } else {
        return ZX_ERR_INTERNAL_INTR_RETRY;
      }
    }

    // set a one shot timer to wake us up and reschedule
    timer.Set(deadline, &Thread::SleepHandler, current_thread);

    current_thread->set_sleeping();
    current_thread->wait_queue_state_.Block(current_thread, interruptible, ZX_OK);

    // Once we wake up again, we will be holding the current thread's lock once
    // again.  That said, the lock had been dropped, and was re-acquired while we
    // were blocked.  Stash our BlockedStatus while we are still holding our lock,
    // but make sure to drop the lock before we call into timer.Cancel().
    //
    // When we call into timer.Cancel(), if we discover a timer callback in
    // flight, we are going to spin until the timer callback flags itself as
    // completed, ensuring that it is safe for the Timer on our stack to be
    // destroyed.  The timer callback is going to need this lock as well, if it
    // gets run, however.  So, if we are still holding our lock when we call
    // cancel, we risk deadlock.
    //
    // always cancel the timer, since we may be racing with the timer tick on
    // other cpus
    final_blocked_status = current_thread->wait_queue_state_.BlockedStatus();
  }
  timer.Cancel();
  return final_blocked_status;
}

zx_status_t Thread::Current::Sleep(zx_time_t deadline) {
  const zx_time_t now = current_time();
  return SleepEtc(Deadline::no_slack(deadline), Interruptible::No, now);
}

zx_status_t Thread::Current::SleepRelative(zx_duration_t delay) {
  const zx_time_t now = current_time();
  const Deadline deadline = Deadline::no_slack(zx_time_add_duration(now, delay));
  return SleepEtc(deadline, Interruptible::No, now);
}

zx_status_t Thread::Current::SleepInterruptible(zx_time_t deadline) {
  const zx_time_t now = current_time();
  const TimerSlack slack(sleep_slack(deadline, now), TIMER_SLACK_LATE);
  const Deadline slackDeadline(deadline, slack);
  return SleepEtc(slackDeadline, Interruptible::Yes, now);
}

/**
 * @brief Return the number of nanoseconds a thread has been running for.
 *
 * This takes the thread's lock to ensure there are no races while calculating
 * the runtime of the thread.
 */
zx_duration_t Thread::Runtime() const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::Runtime")};

  zx_duration_t runtime = scheduler_state_.runtime_ns();
  if (state() == THREAD_RUNNING) {
    zx_duration_t recent =
        zx_time_sub_time(current_time(), scheduler_state_.last_started_running());
    runtime = zx_duration_add_duration(runtime, recent);
  }

  return runtime;
}

/**
 * @brief Get the last CPU the given thread was run on, or INVALID_CPU if the
 * thread has never run.
 */
cpu_num_t Thread::LastCpu() const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::LastCpu")};
  return scheduler_state_.last_cpu_;
}

/**
 * @brief Get the last CPU the given thread was run on, or INVALID_CPU if the
 * thread has never run.
 */
cpu_num_t Thread::LastCpuLocked() const { return scheduler_state_.last_cpu_; }

/**
 * @brief Construct a thread t around the current running state
 *
 * This should be called once per CPU initialization.  It will create
 * a thread that is pinned to the current CPU and running at the
 * highest priority.
 */
void thread_construct_first(Thread* t, const char* name) {
  DEBUG_ASSERT(arch_ints_disabled());

  construct_thread(t, name);

  auto InitThreadState = [](Thread* const t) TA_NO_THREAD_SAFETY_ANALYSIS {
    t->set_detached(true);

    // Setup the scheduler state.
    Scheduler::InitializeFirstThread(t);

    // Start out with preemption disabled to avoid attempts to reschedule until
    // threading is fulling enabled. This simplifies code paths shared between
    // initialization and runtime (e.g. logging). Preemption is enabled when the
    // idle thread for the current CPU is ready.
    t->preemption_state().PreemptDisable();

    arch_thread_construct_first(t);
  };

  // Take care not to touch any global locks when invoked by early init code
  // that runs before global ctors are called. The thread_list is safe to mutate
  // before global ctors are run.
  if (lk_global_constructors_called()) {
    Guard<SpinLock, IrqSave> list_guard{&Thread::get_list_lock()};
    SingletonChainLockGuardNoIrqSave thread_guard{t->get_lock(), CLT_TAG("thread_construct_first")};
    InitThreadState(t);
    thread_list->push_front(t);
  } else {
    InitThreadState(t);
    [t]() TA_NO_THREAD_SAFETY_ANALYSIS { thread_list->push_front(t); }();
  }
}

/**
 * @brief  Initialize threading system
 *
 * This function is called once, from kmain()
 */
void thread_init_early() {
  DEBUG_ASSERT(arch_curr_cpu_num() == 0);

  // Initialize the thread list. This needs to be done manually now, since initial thread code
  // manipulates the list before global constructors are run.
  []() TA_NO_THREAD_SAFETY_ANALYSIS { thread_list.Initialize(); }();

  // Init the boot percpu data.
  percpu::InitializeBoot();

  // create a thread to cover the current running state
  Thread* t = &percpu::Get(0).idle_power_thread.thread();
  thread_construct_first(t, "bootstrap");
}

/**
 * @brief Change name of current thread
 */
void Thread::Current::SetName(const char* name) {
  Thread* current_thread = Thread::Current::Get();
  strlcpy(current_thread->name_, name, sizeof(current_thread->name_));
}

/**
 * @brief Change the base profile of current thread
 *
 * Changes the base profile of the thread to the base profile supplied by the
 * users, dealing with any side effects in the process.
 *
 * @param profile The base profile to apply to the thread.
 */
void Thread::SetBaseProfile(const SchedulerState::BaseProfile& profile) {
  canary_.Assert();
  OwnedWaitQueue::SetThreadBaseProfileAndPropagate(*this, profile);
}

/**
 * @brief Set the pointer to the user-mode thread, this will receive callbacks:
 * ThreadDispatcher::Exiting()
 * ThreadDispatcher::Suspending() / Resuming()
 *
 * This also caches the assocatiated koids of the thread and process
 * dispatchers associated with the given ThreadDispatcher.
 */
void Thread::SetUsermodeThread(fbl::RefPtr<ThreadDispatcher> user_thread) {
  canary_.Assert();

  SingletonChainLockGuardIrqSave thread_guard{lock_, CLT_TAG("Thread::SetUsermodeThread")};
  DEBUG_ASSERT(state() == THREAD_INITIAL);
  DEBUG_ASSERT(!user_thread_);

  user_thread_ = ktl::move(user_thread);
  tid_ = user_thread_->get_koid();
  pid_ = user_thread_->process()->get_koid();

  // All user mode threads are detached since they are responsible for cleaning themselves up.
  // We can set this directly because we've checked that we are in the initial state.
  flags_ |= THREAD_FLAG_DETACHED;
}

/**
 * @brief  Become an idle thread
 *
 * This function marks the current thread as the idle thread -- the one which
 * executes when there is nothing else to do.  This function does not return.
 * This thread is called once at boot on the first cpu.
 */
void Thread::Current::BecomeIdle() {
  DEBUG_ASSERT(arch_ints_disabled());

  Thread* t = Thread::Current::Get();
  cpu_num_t curr_cpu = arch_curr_cpu_num();

  {
    // Hold our own lock while we fix up our bookkeeping
    SingletonChainLockGuardNoIrqSave thread_guard{t->lock_, CLT_TAG("Thread::Current::BecomeIdle")};

    // Set our name
    char name[16];
    snprintf(name, sizeof(name), "idle %u", curr_cpu);
    Thread::Current::SetName(name);

    // Mark ourself as idle
    t->flags_ |= THREAD_FLAG_IDLE;

    // Now that we are the idle thread, make sure that we drop out of the
    // scheduler's bookkeeping altogether.
    Scheduler::RemoveFirstThread(t);
    t->set_running();

    // Cpu is active.
    mp_set_curr_cpu_active(true);
    mp_set_cpu_idle(curr_cpu);

    // Pend a preemption to ensure a reschedule.
    arch_set_blocking_disallowed(true);
    t->preemption_state().PreemptSetPending();
    arch_set_blocking_disallowed(false);
  }

  // Signal that our current CPU is now ready before we re-enable interrupts,
  // re-enable preemption, and finally drop into our idle routine, and never
  // return.
  mp_signal_curr_cpu_ready();
  arch_enable_ints();
  t->preemption_state().PreemptReenable();
  DEBUG_ASSERT(t->preemption_state().PreemptIsEnabled());

  IdlePowerThread::Run(nullptr);
  __UNREACHABLE;
}

/**
 * @brief Create a thread around the current execution context, preserving |t|'s stack
 *
 * Prior to calling, |t->stack| must be properly constructed. See |vm_allocate_kstack|.
 */
void Thread::SecondaryCpuInitEarly() {
  DEBUG_ASSERT(arch_ints_disabled());
  DEBUG_ASSERT(stack_.base() != 0);
  DEBUG_ASSERT(IS_ALIGNED(this, alignof(Thread)));

  // At this point, the CPU isn't far enough along to allow threads to block. Set blocking
  // disallowed until to catch bugs where code might block before we're ready.
  arch_set_blocking_disallowed(true);

  percpu::InitializeSecondaryFinish();

  char name[16];
  snprintf(name, sizeof(name), "cpu_init %u", arch_curr_cpu_num());
  thread_construct_first(this, name);

  // Emitting the thread metadata usually happens during Thread::Resume(), however, cpu_init threads
  // are never resumed. Emit the metadata here so that the thread name is associated with its tid.
  KTRACE_KERNEL_OBJECT("kernel:meta", this->tid(), ZX_OBJ_TYPE_THREAD, this->name(),
                       ("process", ktrace::Koid(this->pid())));
}

/**
 * @brief The last routine called on the secondary cpu's bootstrap thread.
 */
void thread_secondary_cpu_entry() {
  DEBUG_ASSERT(arch_blocking_disallowed());

  mp_set_curr_cpu_active(true);

  percpu& current_cpu = percpu::GetCurrent();

  // Signal the idle/power thread to transition to active but don't wait for it, since it cannot run
  // until this thread either blocks or exits below. The idle thread will run immediately upon exit
  // and complete the transition, if necessary.
  const IdlePowerThread::TransitionResult result =
      current_cpu.idle_power_thread.TransitionOfflineToActive(ZX_TIME_INFINITE_PAST);

  // The first time a secondary CPU becomes active after boot the CPU power thread is already in the
  // active state. If the CPU power thread is not in its initial active state, it is being returned
  // to active from offline and needs to be revived to resume its normal function.
  if (result.starting_state != IdlePowerThread::State::Active) {
    Thread::ReviveIdlePowerThread(arch_curr_cpu_num());
  }

  // CAREFUL: This must happen after the idle/power thread is revived, since creating the DPC thread
  // can contend on VM locks and could cause this CPU to go idle.
  current_cpu.dpc_queue.InitForCurrentCpu();

  // Remove ourselves from the Scheduler's bookkeeping.
  {
    Thread& current = *Thread::Current::Get();
    SingletonChainLockGuardIrqSave guard{current.get_lock(), CLT_TAG("thread_secondary_cpu_entry")};
    Scheduler::RemoveFirstThread(&current);
  }

  mp_signal_curr_cpu_ready();

  // Exit from our bootstrap thread, and enter the scheduler on this cpu.
  Thread::Current::Exit(0);
}

/**
 * @brief Create an idle thread for a secondary CPU
 */
Thread* Thread::CreateIdleThread(cpu_num_t cpu_num) {
  DEBUG_ASSERT(cpu_num != 0 && cpu_num < SMP_MAX_CPUS);

  char name[16];
  snprintf(name, sizeof(name), "idle %u", cpu_num);

  Thread* t = Thread::CreateEtc(&percpu::Get(cpu_num).idle_power_thread.thread(), name,
                                IdlePowerThread::Run, nullptr,
                                SchedulerState::BaseProfile{IDLE_PRIORITY}, nullptr);
  if (t == nullptr) {
    return t;
  }

  {
    SingletonChainLockGuardIrqSave guard{t->lock_, CLT_TAG("Thread::CreateIdleThread")};

    t->flags_ |= THREAD_FLAG_IDLE | THREAD_FLAG_DETACHED;
    t->scheduler_state_.hard_affinity_ = cpu_num_to_mask(cpu_num);

    Scheduler::UnblockIdle(t);
  }
  return t;
}

void Thread::ReviveIdlePowerThread(cpu_num_t cpu_num) {
  DEBUG_ASSERT(cpu_num != 0 && cpu_num < SMP_MAX_CPUS);
  Thread* thread = &percpu::Get(cpu_num).idle_power_thread.thread();

  SingletonChainLockGuardIrqSave guard{thread->lock_, CLT_TAG("Thread::ReviveIdlePowerThread")};

  DEBUG_ASSERT(thread->flags() & THREAD_FLAG_IDLE);
  DEBUG_ASSERT(thread->scheduler_state().hard_affinity() == cpu_num_to_mask(cpu_num));
  DEBUG_ASSERT(thread->task_state().entry() == IdlePowerThread::Run);

  arch_thread_initialize(thread, reinterpret_cast<vaddr_t>(Thread::Trampoline));
  thread->preemption_state().Reset();
}

/**
 * @brief Return the name of the "owner" of the thread.
 *
 * Returns "kernel" if there is no owner.
 */

void Thread::OwnerName(char (&out_name)[ZX_MAX_NAME_LEN]) const {
  if (user_thread_) {
    [[maybe_unused]] zx_status_t status = user_thread_->process()->get_name(out_name);
    DEBUG_ASSERT(status == ZX_OK);
    return;
  }
  memcpy(out_name, "kernel", 7);
}

static const char* thread_state_to_str(enum thread_state state) {
  switch (state) {
    case THREAD_INITIAL:
      return "init";
    case THREAD_SUSPENDED:
      return "susp";
    case THREAD_READY:
      return "rdy";
    case THREAD_RUNNING:
      return "run";
    case THREAD_BLOCKED:
    case THREAD_BLOCKED_READ_LOCK:
      return "blok";
    case THREAD_SLEEPING:
      return "slep";
    case THREAD_DEATH:
      return "deth";
    default:
      return "unkn";
  }
}

/**
 * @brief  Dump debugging info about the specified thread.
 */
void ThreadDumper::DumpLocked(const Thread* t, bool full_dump) {
  if (!t->canary().Valid()) {
    dprintf(INFO, "dump_thread WARNING: thread at %p has bad magic\n", t);
  }

  zx_duration_t runtime = t->scheduler_state().runtime_ns();
  if (t->state() == THREAD_RUNNING) {
    zx_duration_t recent =
        zx_time_sub_time(current_time(), t->scheduler_state().last_started_running());
    runtime = zx_duration_add_duration(runtime, recent);
  }

  char oname[ZX_MAX_NAME_LEN];
  t->OwnerName(oname);

  char profile_str[64]{0};
  if (const SchedulerState::EffectiveProfile& ep = t->scheduler_state().effective_profile();
      ep.IsFair()) {
    snprintf(profile_str, sizeof(profile_str), "Fair (w %ld)", ep.fair.weight.raw_value());
  } else {
    DEBUG_ASSERT(ep.IsDeadline());
    snprintf(profile_str, sizeof(profile_str), "Deadline (c,d = %ld,%ld)",
             ep.deadline.capacity_ns.raw_value(), ep.deadline.deadline_ns.raw_value());
  }

  if (full_dump) {
    dprintf(INFO, "dump_thread: t %p (%s:%s)\n", t, oname, t->name());
    dprintf(INFO,
            "\tstate %s, curr/last cpu %d/%d, hard_affinity %#x, soft_cpu_affinity %#x, "
            "%s, remaining time slice %" PRIi64 "\n",
            thread_state_to_str(t->state()), (int)t->scheduler_state().curr_cpu(),
            (int)t->scheduler_state().last_cpu(), t->scheduler_state().hard_affinity(),
            t->scheduler_state().soft_affinity(), profile_str,
            t->scheduler_state().time_slice_ns());
    dprintf(INFO, "\truntime_ns %" PRIi64 ", runtime_s %" PRIi64 "\n", runtime,
            runtime / 1000000000);
    t->stack().DumpInfo(INFO);
    dprintf(INFO, "\tentry %p, arg %p, flags 0x%x %s%s%s%s\n", t->task_state_.entry_,
            t->task_state_.arg_, t->flags_, (t->flags_ & THREAD_FLAG_DETACHED) ? "Dt" : "",
            (t->flags_ & THREAD_FLAG_FREE_STRUCT) ? "Ft" : "",
            (t->flags_ & THREAD_FLAG_IDLE) ? "Id" : "", (t->flags_ & THREAD_FLAG_VCPU) ? "Vc" : "");

    dprintf(INFO, "\twait queue %p, blocked_status %d, interruptible %s, wait queues owned %s\n",
            t->wait_queue_state().blocking_wait_queue_, t->wait_queue_state().blocked_status_,
            t->wait_queue_state().interruptible_ == Interruptible::Yes ? "yes" : "no",
            t->wait_queue_state().owned_wait_queues_.is_empty() ? "no" : "yes");

    dprintf(INFO, "\taspace %p\n", t->GetAspaceRefLocked().get());
    dprintf(INFO, "\tuser_thread %p, pid %" PRIu64 ", tid %" PRIu64 "\n", t->user_thread_.get(),
            t->pid(), t->tid());
    arch_dump_thread(t);
  } else {
    printf("thr %p st %4s owq %d %s pid %" PRIu64 " tid %" PRIu64 " (%s:%s)\n", t,
           thread_state_to_str(t->state()), !t->wait_queue_state().owned_wait_queues_.is_empty(),
           profile_str, t->pid(), t->tid(), oname, t->name());
  }
}

void Thread::Dump(bool full) const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::Dump")};
  ThreadDumper::DumpLocked(this, full);
}

/**
 * @brief  Dump debugging info about all threads
 */
void Thread::DumpAllLocked(bool full) {
  for (const Thread& t : thread_list.Get()) {
    if (!t.canary().Valid()) {
      dprintf(INFO, "bad magic on thread struct %p, aborting.\n", &t);
      hexdump(&t, sizeof(Thread));
      break;
    }

    {
      SingletonChainLockGuardIrqSave guard{t.get_lock(), CLT_TAG("Thread::DumpAllLocked")};
      ThreadDumper::DumpLocked(&t, full);
    }
  }
}

void Thread::DumpAll(bool full) {
  Guard<SpinLock, IrqSave> list_guard{&list_lock_};
  DumpAllLocked(full);
}

void Thread::DumpTid(zx_koid_t tid, bool full) {
  Guard<SpinLock, IrqSave> list_guard{&list_lock_};
  DumpTidLocked(tid, full);
}

void Thread::DumpTidLocked(zx_koid_t tid, bool full) {
  for (const Thread& t : thread_list.Get()) {
    if (t.tid() != tid) {
      continue;
    }

    if (!t.canary().Valid()) {
      dprintf(INFO, "bad magic on thread struct %p, aborting.\n", &t);
      hexdump(&t, sizeof(Thread));
      break;
    }

    // TODO(johngro): Is it ok to stop searching now?  In theory, no two threads
    // should share a TID.
    t.Dump(full);
    break;
  }
}

Thread* thread_id_to_thread_slow(zx_koid_t tid) {
  for (Thread& t : thread_list.Get()) {
    if (t.tid() == tid) {
      return &t;
    }
  }

  return nullptr;
}

/** @} */

// Used by ktrace at the start of a trace to ensure that all
// the running threads, processes, and their names are known
void ktrace_report_live_threads() {
  Guard<SpinLock, IrqSave> guard{&Thread::get_list_lock()};
  for (Thread& t : thread_list.Get()) {
    t.canary().Assert();
    KTRACE_KERNEL_OBJECT_ALWAYS(t.tid(), ZX_OBJ_TYPE_THREAD, t.name(),
                                ("process", ktrace::Koid(t.pid())));
  }
}

void Thread::UpdateRuntimeStats(thread_state new_state) {
  if (user_thread_) {
    user_thread_->UpdateRuntimeStats(new_state);
  }
}

fbl::RefPtr<VmAspace> Thread::GetAspaceRef() const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::GetAspaceRef")};
  return GetAspaceRefLocked();
}

fbl::RefPtr<VmAspace> Thread::GetAspaceRefLocked() const {
  VmAspace* const cur_aspace = aspace_;
  if (!cur_aspace || scheduler_state().state() == THREAD_DEATH) {
    return nullptr;
  }

  cur_aspace->AddRef();
  return fbl::ImportFromRawPtr(cur_aspace);
}

namespace {

// TODO(maniscalco): Consider moving this method to the KernelStack class.
// That's probably a better home for it.
zx_status_t ReadStack(Thread* thread, vaddr_t ptr, vaddr_t* out, size_t sz) {
  if (!is_kernel_address(ptr) || (ptr < thread->stack().base()) ||
      (ptr > (thread->stack().top() - sz))) {
    return ZX_ERR_NOT_FOUND;
  }
  memcpy(out, reinterpret_cast<const void*>(ptr), sz);
  return ZX_OK;
}

void GetBacktraceCommon(Thread* thread, vaddr_t fp, Backtrace& out_bt) {
  // Be sure that all paths out of this function leave with |out_bt| either
  // properly filled in or empty.
  out_bt.reset();

  // Without frame pointers, dont even try.  The compiler should optimize out
  // the body of all the callers if it's not present.
  if (!WITH_FRAME_POINTERS) {
    return;
  }

  // Perhaps we don't yet have a thread context?
  if (thread == nullptr) {
    return;
  }

  if (fp == 0) {
    return;
  }

  vaddr_t pc;
  size_t n = 0;
  for (; n < Backtrace::kMaxSize; n++) {
    vaddr_t actual_fp = fp;

    // RISC-V has a nonstandard frame pointer which points to the CFA instead of
    // the previous frame pointer. Since the frame pointer and return address are
    // always just below the CFA, subtract 16 bytes to get to the actual frame pointer.
#if __riscv
    actual_fp -= 16;
#endif

    if (ReadStack(thread, actual_fp + 8, &pc, sizeof(vaddr_t))) {
      break;
    }
    out_bt.push_back(pc);
    if (ReadStack(thread, actual_fp, &fp, sizeof(vaddr_t))) {
      break;
    }
  }
}

}  // namespace

void Thread::Current::GetBacktrace(Backtrace& out_bt) {
  auto fp = reinterpret_cast<vaddr_t>(__GET_FRAME(0));
  GetBacktraceCommon(Thread::Current::Get(), fp, out_bt);

  // (https://fxbug.dev/42179766): Force the function to not tail call GetBacktraceCommon.
  // This will make sure the frame pointer we grabbed at the top
  // of the function is still valid across the call.
  asm("");
}

void Thread::Current::GetBacktrace(vaddr_t fp, Backtrace& out_bt) {
  GetBacktraceCommon(Thread::Current::Get(), fp, out_bt);
}

void Thread::GetBacktrace(Backtrace& out_bt) {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::GetBacktrace")};

  // Get the starting point if it's in a usable state.
  vaddr_t fp = 0;
  switch (state()) {
    case THREAD_BLOCKED:
    case THREAD_BLOCKED_READ_LOCK:
    case THREAD_SLEEPING:
    case THREAD_SUSPENDED:
      // Thread is blocked, so ask the arch code to get us a starting point.
      fp = arch_thread_get_blocked_fp(this);
      break;
    default:
      // Not in a valid state, can't get a backtrace.  Reset it so the caller
      // doesn't inadvertently use a previous value.
      out_bt.reset();
      return;
  }

  GetBacktraceCommon(this, fp, out_bt);
}

SchedulerState::EffectiveProfile Thread::SnapshotEffectiveProfile() const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::SnapshotEffectiveeProfile")};
  SchedulerState::EffectiveProfile ret = SnapshotEffectiveProfileLocked();
  return ret;
}

SchedulerState::BaseProfile Thread::SnapshotBaseProfile() const {
  SingletonChainLockGuardIrqSave guard{lock_, CLT_TAG("Thread::SnapshotBaseProfile")};
  SchedulerState::BaseProfile ret = SnapshotBaseProfileLocked();
  return ret;
}
