blob: eee63c4e38300a610dc5612821361170c1e77503 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/async/cpp/exception.h>
#include <utility>
#include <zircon/assert.h>
namespace async {
ExceptionBase::ExceptionBase(zx_handle_t task, uint32_t options,
async_exception_handler_t* handler)
: exception_{{ASYNC_STATE_INIT}, handler, task, options} {
ZX_DEBUG_ASSERT(handler);
}
ExceptionBase::~ExceptionBase() {
if (dispatcher_) {
// Failure to unbind here may result in a dangling pointer...
zx_status_t status = async_unbind_exception_port(dispatcher_, &exception_);
ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status);
}
}
zx_status_t ExceptionBase::Bind(async_dispatcher_t* dispatcher) {
if (dispatcher_)
return ZX_ERR_ALREADY_EXISTS;
dispatcher_ = dispatcher;
zx_status_t status = async_bind_exception_port(dispatcher, &exception_);
if (status != ZX_OK) {
dispatcher_ = nullptr;
}
return status;
}
zx_status_t ExceptionBase::Unbind() {
if (!dispatcher_)
return ZX_ERR_NOT_FOUND;
async_dispatcher_t* dispatcher = dispatcher_;
dispatcher_ = nullptr;
zx_status_t status = async_unbind_exception_port(dispatcher, &exception_);
// |dispatcher| is required to be single-threaded, Unbind() is
// only supposed to be called on |dispatcher|'s thread, and
// we verified that the port was bound before calling
// async_unbind_exception_port().
ZX_DEBUG_ASSERT(status != ZX_ERR_NOT_FOUND);
return status;
}
zx_status_t ExceptionBase::Resume(zx_handle_t task, uint32_t options) {
if (!dispatcher_)
return ZX_ERR_NOT_FOUND;
return async_resume_from_exception(dispatcher_, &exception_, task, options);
}
Exception::Exception(zx_handle_t task, uint32_t options,
Handler handler)
: ExceptionBase(task, options, &Exception::CallHandler),
handler_(std::move(handler)) {}
Exception::~Exception() = default;
void Exception::CallHandler(async_dispatcher_t* dispatcher,
async_exception_t* exception,
zx_status_t status,
const zx_port_packet_t* report) {
auto self = Dispatch<Exception>(exception);
self->handler_(dispatcher, self, status, report);
}
} // namespace async