// Copyright 2019 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/exception_dispatcher.h"

#include <assert.h>
#include <lib/counters.h>

#include <fbl/alloc_checker.h>
#include <ktl/move.h>
#include <object/process_dispatcher.h>

#include <ktl/enforce.h>

KCOUNTER(dispatcher_exception_create_count, "dispatcher.exception.create")
KCOUNTER(dispatcher_exception_destroy_count, "dispatcher.exception.destroy")

zx_exception_report_t ExceptionDispatcher::BuildArchReport(
    uint32_t type, const arch_exception_context_t& context) {
  zx_exception_report_t report = {};
  report.header.size = sizeof(report);
  report.header.type = type;
  arch_fill_in_exception_context(&context, &report);
  return report;
}

fbl::RefPtr<ExceptionDispatcher> ExceptionDispatcher::Create(
    fbl::RefPtr<ThreadDispatcher> thread, zx_excp_type_t exception_type,
    const zx_exception_report_t* report, const arch_exception_context_t* arch_context) {
  fbl::AllocChecker ac;
  fbl::RefPtr<ExceptionDispatcher> exception = fbl::AdoptRef(
      new (&ac) ExceptionDispatcher(ktl::move(thread), exception_type, report, arch_context));
  if (!ac.check()) {
    // ExceptionDispatchers are small so if we get to this point a lot of
    // other things will be failing too, but we could potentially pre-
    // allocate space for an ExceptionDispatcher in each thread if we want
    // to eliminate this case.
    return nullptr;
  }

  return exception;
}

ExceptionDispatcher::ExceptionDispatcher(fbl::RefPtr<ThreadDispatcher> thread,
                                         zx_excp_type_t exception_type,
                                         const zx_exception_report_t* report,
                                         const arch_exception_context_t* arch_context)
    : thread_(ktl::move(thread)),
      exception_type_(exception_type),
      report_(report),
      arch_context_(arch_context) {
  kcounter_add(dispatcher_exception_create_count, 1);
}

ExceptionDispatcher::~ExceptionDispatcher() { kcounter_add(dispatcher_exception_destroy_count, 1); }

bool ExceptionDispatcher::FillReport(zx_exception_report_t* report) const {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};
  if (report_) {
    *report = *report_;
    return true;
  }
  return false;
}

void ExceptionDispatcher::SetTaskRights(zx_rights_t thread_rights, zx_rights_t process_rights) {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};
  thread_rights_ = thread_rights;
  process_rights_ = process_rights;
}

zx_status_t ExceptionDispatcher::MakeThreadHandle(HandleOwner* handle) const {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};

  if (thread_rights_ == 0) {
    return ZX_ERR_ACCESS_DENIED;
  }

  *handle = Handle::Make(thread_, thread_rights_);
  if (!(*handle)) {
    return ZX_ERR_NO_MEMORY;
  }
  return ZX_OK;
}

zx_status_t ExceptionDispatcher::MakeProcessHandle(HandleOwner* handle) const {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};

  if (process_rights_ == 0) {
    return ZX_ERR_ACCESS_DENIED;
  }

  // We have a RefPtr to |thread_| so it can't die, and the thread keeps its
  // process alive, so we know the process is safe to wrap in a RefPtr.
  *handle = Handle::Make(fbl::RefPtr(thread_->process()), process_rights_);
  if (!(*handle)) {
    return ZX_ERR_NO_MEMORY;
  }
  return ZX_OK;
}

void ExceptionDispatcher::on_zero_handles() {
  canary_.Assert();

  response_event_.Signal();
}

uint32_t ExceptionDispatcher::GetDisposition() const {
  canary_.Assert();

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

void ExceptionDispatcher::SetDisposition(uint32_t disposition) {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};
  disposition_ = disposition;
}

bool ExceptionDispatcher::IsSecondChance() const {
  canary_.Assert();

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

void ExceptionDispatcher::SetWhetherSecondChance(bool second_chance) {
  canary_.Assert();

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

zx_status_t ExceptionDispatcher::WaitForHandleClose() {
  canary_.Assert();

  zx_status_t status;
  do {
    // Continue to wait for the exception response if we get suspended.
    // Both the suspension and the exception need to be closed out before
    // the thread can resume.
    status = response_event_.WaitWithMask(THREAD_SIGNAL_SUSPEND);
  } while (status == ZX_ERR_INTERNAL_INTR_RETRY);

  if (status == ZX_ERR_INTERNAL_INTR_KILLED) {
    // If the thread was killed it doesn't matter whether the handler
    // wanted to resume or not.
    return ZX_ERR_INTERNAL_INTR_KILLED;
  } else if (status != ZX_OK) {
    // Our event wait should only ever return one of the internal errors
    // handled above or the ZX_OK we send in on_zero_handles().
    ASSERT_MSG(false, "unexpected exception event result: %d\n", status);
    __UNREACHABLE;
  }

  // Return the close action and reset it for next time.
  Guard<Mutex> guard{get_lock()};
  switch (disposition_) {
    case ZX_EXCEPTION_STATE_HANDLED:
      status = ZX_OK;
      break;
    case ZX_EXCEPTION_STATE_THREAD_EXIT:
      status = ZX_ERR_STOP;
      break;
    case ZX_EXCEPTION_STATE_TRY_NEXT:
    default:
      status = ZX_ERR_NEXT;
      break;
  }
  disposition_ = ZX_EXCEPTION_STATE_TRY_NEXT;
  return status;
}

void ExceptionDispatcher::DiscardHandleClose() {
  canary_.Assert();

  response_event_.Unsignal();

  Guard<Mutex> guard{get_lock()};
  disposition_ = ZX_EXCEPTION_STATE_TRY_NEXT;
}

void ExceptionDispatcher::Clear() {
  canary_.Assert();

  Guard<Mutex> guard{get_lock()};
  report_ = nullptr;
  arch_context_ = nullptr;
}
