blob: 93ab35a1933c83407574c0c21cc3da2243c33477 [file] [log] [blame]
// Copyright 2021 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/fdf/arena.h>
#include <lib/fdf/channel.h>
#include <lib/fdf/dispatcher.h>
#include <lib/fdf/internal.h>
#include "src/devices/bin/driver_runtime/arena.h"
#include "src/devices/bin/driver_runtime/channel.h"
#include "src/devices/bin/driver_runtime/dispatcher.h"
#include "src/devices/bin/driver_runtime/driver_context.h"
#include "src/devices/bin/driver_runtime/handle.h"
// fdf_arena_t interface
__EXPORT fdf_status_t fdf_arena_create(uint32_t options, const char* tag, size_t tag_len,
fdf_arena_t** out_arena) {
return fdf_arena::Create(options, tag, tag_len, out_arena);
}
__EXPORT void* fdf_arena_allocate(fdf_arena_t* arena, size_t bytes) {
return arena->Allocate(bytes);
}
__EXPORT void* fdf_arena_free(fdf_arena_t* arena, void* data) { return arena->Free(data); }
__EXPORT bool fdf_arena_contains(fdf_arena_t* arena, const void* data, size_t num_bytes) {
return arena->Contains(data, num_bytes);
}
__EXPORT void fdf_arena_destroy(fdf_arena_t* arena) { arena->Destroy(); }
// fdf_channel_t interface
__EXPORT
fdf_status_t fdf_channel_create(uint32_t options, fdf_handle_t* out0, fdf_handle_t* out1) {
return driver_runtime::Channel::Create(options, out0, out1);
}
__EXPORT
fdf_status_t fdf_channel_write(fdf_handle_t channel_handle, uint32_t options, fdf_arena_t* arena,
void* data, uint32_t num_bytes, zx_handle_t* handles,
uint32_t num_handles) {
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status =
driver_runtime::Handle::GetObject<driver_runtime::Channel>(channel_handle, &channel);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(status == ZX_OK);
return channel->Write(options, arena, data, num_bytes, handles, num_handles);
}
__EXPORT
fdf_status_t fdf_channel_read(fdf_handle_t channel_handle, uint32_t options, fdf_arena_t** arena,
void** data, uint32_t* num_bytes, zx_handle_t** handles,
uint32_t* num_handles) {
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status =
driver_runtime::Handle::GetObject<driver_runtime::Channel>(channel_handle, &channel);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(status == ZX_OK);
return channel->Read(options, arena, data, num_bytes, handles, num_handles);
}
__EXPORT
fdf_status_t fdf_channel_wait_async(struct fdf_dispatcher* dispatcher,
fdf_channel_read_t* channel_read, uint32_t options) {
if (!channel_read) {
return ZX_ERR_INVALID_ARGS;
}
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status =
driver_runtime::Handle::GetObject<driver_runtime::Channel>(channel_read->channel, &channel);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(status == ZX_OK);
return channel->WaitAsync(dispatcher, channel_read, options);
}
__EXPORT fdf_status_t fdf_channel_call(fdf_handle_t channel_handle, uint32_t options,
zx_time_t deadline, const fdf_channel_call_args_t* args) {
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status =
driver_runtime::Handle::GetObject<driver_runtime::Channel>(channel_handle, &channel);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(status == ZX_OK);
return channel->Call(options, deadline, args);
}
__EXPORT fdf_status_t fdf_channel_cancel_wait(fdf_handle_t channel_handle) {
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status =
driver_runtime::Handle::GetObject<driver_runtime::Channel>(channel_handle, &channel);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(status == ZX_OK);
return channel->CancelWait();
}
__EXPORT void fdf_handle_close(fdf_handle_t channel_handle) {
if (channel_handle == FDF_HANDLE_INVALID) {
return;
}
if (!driver_runtime::Handle::IsFdfHandle(channel_handle)) {
zx_handle_close(channel_handle);
return;
}
driver_runtime::Handle* handle = driver_runtime::Handle::MapValueToHandle(channel_handle);
// TODO(fxbug.dev/87046): we may want to consider killing the process.
ZX_ASSERT(handle);
fbl::RefPtr<driver_runtime::Channel> channel;
fdf_status_t status = handle->GetObject<driver_runtime::Channel>(&channel);
if (status != ZX_OK) {
return;
}
channel->Close();
// Drop the handle.
handle->TakeOwnership();
}
// fdf_dispatcher_t interface
__EXPORT fdf_status_t fdf_dispatcher_create(uint32_t options, const char* scheduler_role,
size_t scheduler_role_len,
fdf_dispatcher_shutdown_observer_t* observer,
fdf_dispatcher_t** out_dispatcher) {
driver_runtime::Dispatcher* dispatcher;
auto status = driver_runtime::Dispatcher::Create(options, scheduler_role, scheduler_role_len,
observer, &dispatcher);
if (status != ZX_OK) {
return status;
}
*out_dispatcher = static_cast<fdf_dispatcher*>(dispatcher);
return ZX_OK;
}
__EXPORT async_dispatcher_t* fdf_dispatcher_get_async_dispatcher(fdf_dispatcher_t* dispatcher) {
return dispatcher->GetAsyncDispatcher();
}
__EXPORT fdf_dispatcher_t* fdf_dispatcher_from_async_dispatcher(async_dispatcher_t* dispatcher) {
return static_cast<fdf_dispatcher*>(fdf_dispatcher::FromAsyncDispatcher(dispatcher));
}
__EXPORT uint32_t fdf_dispatcher_get_options(const fdf_dispatcher_t* dispatcher) {
return dispatcher->options();
}
__EXPORT void fdf_dispatcher_shutdown_async(fdf_dispatcher_t* dispatcher) {
return dispatcher->ShutdownAsync();
}
__EXPORT void fdf_dispatcher_destroy(fdf_dispatcher_t* dispatcher) { return dispatcher->Destroy(); }
__EXPORT fdf_dispatcher_t* fdf_dispatcher_get_current_dispatcher() {
return static_cast<fdf_dispatcher_t*>(driver_context::GetCurrentDispatcher());
}
__EXPORT void fdf_internal_push_driver(const void* driver) { driver_context::PushDriver(driver); }
__EXPORT void fdf_internal_pop_driver() { driver_context::PopDriver(); }
__EXPORT const void* fdf_internal_get_current_driver() {
return driver_context::GetCurrentDriver();
}
__EXPORT void fdf_internal_destroy_all_dispatchers() {
return driver_runtime::DispatcherCoordinator::DestroyAllDispatchers();
}
__EXPORT void fdf_internal_wait_until_dispatcher_idle(fdf_dispatcher_t* dispatcher) {
return dispatcher->WaitUntilIdle();
}
__EXPORT fdf_status_t fdf_internal_shutdown_dispatchers_async(
const void* driver, fdf_internal_driver_shutdown_observer_t* observer) {
return driver_runtime::DispatcherCoordinator::ShutdownDispatchersAsync(driver, observer);
}
__EXPORT void fdf_internal_wait_until_all_dispatchers_idle() {
return driver_runtime::DispatcherCoordinator::WaitUntilDispatchersIdle();
}
__EXPORT void fdf_internal_wait_until_all_dispatchers_destroyed() {
return driver_runtime::DispatcherCoordinator::WaitUntilDispatchersDestroyed();
}
__EXPORT bool fdf_internal_dispatcher_has_queued_tasks(fdf_dispatcher_t* dispatcher) {
return dispatcher->HasQueuedTasks();
}