blob: be292ac960fd4bbaed61d48bf03b71134159ec23 [file]
// Copyright 2026 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
use super::{AckBehavior, Diagnostics, WakeEvent, WakeResult, WakeVector};
use crate::user_copy::UserOutPtr;
use core::pin::Pin;
use core::ptr::NonNull;
use zx_status::Status;
use zx_types::{
zx_instant_boot_t, zx_status_t, zx_wake_source_report_entry_t, zx_wake_source_report_header_t,
};
unsafe extern "C" {
pub(super) fn cpp_wake_vector_get_diagnostics(
wake_vector: &WakeVector,
diagnostics_out: &mut Diagnostics,
);
}
/// Returns true if there are any pending wake events in the system.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_has_pending_wake_events() -> bool {
WakeEvent::has_pending_wake_events()
}
/// Initializes a `WakeEvent` in-place at `event`.
///
/// # Safety
///
/// `wake_vector` must remain valid for all calls to `rust_wake_event_initialize`.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_wake_event_new(
event: &mut core::mem::MaybeUninit<WakeEvent>,
wake_vector: NonNull<WakeVector>,
) {
// SAFETY: `wake_vector` is valid for all calls to `initialize`.
event.write(unsafe { WakeEvent::new(wake_vector) });
}
/// Drops a `WakeEvent` in-place at `event`.
///
/// # Safety
///
/// `event` must point to a valid, initialized `WakeEvent` that has already been destroyed via
/// `rust_wake_event_destroy` if it was initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rust_wake_event_drop(event: *mut WakeEvent) {
// SAFETY: Caller guarantees `event` is a valid initialized `WakeEvent` being destructed.
unsafe {
core::ptr::drop_in_place(event);
}
}
/// Registers `event` on the global wake event list.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_initialize(event: Pin<&WakeEvent>) {
event.initialize();
}
/// Removes `event` from the pending and global wake event lists.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_destroy(event: &WakeEvent) {
event.destroy();
}
/// Triggers `event` at `trigger_time`.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_trigger(
event: &WakeEvent,
trigger_time: zx_instant_boot_t,
) -> WakeResult {
event.trigger(trigger_time)
}
/// Acknowledges `event` with `ack_behavior`.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_acknowledge(event: &WakeEvent, ack_behavior: AckBehavior) {
event.acknowledge(ack_behavior);
}
/// Atomically triggers and acknowledges `event` at `trigger_time`.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_strobe(
event: &WakeEvent,
trigger_time: zx_instant_boot_t,
) -> WakeResult {
event.strobe(trigger_time)
}
/// Dumps diagnostic information for all pending or recently triggered wake events to `f`.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_dump(
f: &mut libc::stdio::FILE,
log_triggered_after_boot_time: zx_instant_boot_t,
) {
WakeEvent::dump(f, log_triggered_after_boot_time);
}
/// Generates a wake event report and copies it to userspace.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_generate_wake_event_report(
suspend_start_time: zx_instant_boot_t,
out_header: *mut zx_wake_source_report_header_t,
out_entries: *mut zx_wake_source_report_entry_t,
num_entries: u32,
actual_entries: *mut u32,
) -> zx_status_t {
Status::result_into_raw(WakeEvent::generate_wake_event_report(
suspend_start_time,
UserOutPtr::new(out_header),
UserOutPtr::new(out_entries),
num_entries,
UserOutPtr::new(actual_entries),
))
}
/// Discards acknowledged wake event entries from the pending list.
#[unsafe(no_mangle)]
pub extern "C" fn rust_wake_event_discard_wake_event_report() {
WakeEvent::discard_wake_event_report();
}