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

#include <fbl/alloc_checker.h>
#include <ktl/move.h>
#include <lib/counters.h>

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

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), response_event_(EVENT_FLAG_AUTOUNSIGNAL) {
    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<fbl::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<fbl::Mutex> guard{get_lock()};
    thread_rights_ = thread_rights;
    process_rights_ = process_rights;
}

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

    Guard<fbl::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<fbl::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::WrapRefPtr(thread_->process()), process_rights_);
    if (!(*handle)) {
        return ZX_ERR_NO_MEMORY;
    }
    return ZX_OK;
}

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

    response_event_.Signal();
}

void ExceptionDispatcher::GetResumeThreadOnClose(bool* resume_on_close) const {
    canary_.Assert();

    Guard<fbl::Mutex> guard{get_lock()};
    *resume_on_close = resume_on_close_;
}

void ExceptionDispatcher::SetResumeThreadOnClose(bool resume_on_close) {
    canary_.Assert();

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

zx_status_t ExceptionDispatcher::WaitForResponse() {
    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<fbl::Mutex> guard{get_lock()};
    status = resume_on_close_ ? ZX_OK : ZX_ERR_NEXT;
    resume_on_close_ = false;
    return status;
}

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

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