Skip to main content

ksync/
raw_kernel_event.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use core::ffi::c_void;
6use pin_init::{PinInit, pin_data};
7use zx_status::Status;
8use zx_types::{ZX_TIME_INFINITE, zx_instant_mono_t};
9
10unsafe extern "C" {
11    fn cpp_event_init(event: *mut c_void, initial: bool);
12    fn cpp_event_destroy(event: *mut c_void);
13    fn cpp_event_signal(event: *mut c_void, wait_result: i32);
14    fn cpp_event_unsignal(event: *mut c_void);
15    fn cpp_event_wait(event: *mut c_void, deadline: i64) -> i32;
16}
17
18#[repr(C, align(8))]
19struct RawEventStorage(zr::OpaqueBytes<72>);
20
21/// Opaque layout block matching the Zircon C++ Event exactly.
22#[pin_data(PinnedDrop)]
23#[repr(C)]
24pub struct RawEvent {
25    storage: RawEventStorage,
26}
27
28// SAFETY: RawEvent contains OpaqueBytes which is Send by default, but !Sync because of UnsafeCell.
29// We implement Sync manually because Event is safe to share across threads.
30unsafe impl Sync for RawEvent {}
31
32zr::unsafe_pinned_drop_ffi!(RawEvent, cpp_event_destroy);
33
34impl RawEvent {
35    /// Returns a PinInit block to initialize the raw event in-place.
36    pub fn init(initial: bool) -> impl PinInit<Self, core::convert::Infallible> {
37        zr::pin_init_ffi!(cpp_event_init, initial)
38    }
39
40    #[inline]
41    fn as_mut_ptr(&self) -> *mut c_void {
42        self as *const Self as *mut Self as *mut c_void
43    }
44}
45
46/// A wrapper around Zircon's C++ Event.
47#[repr(transparent)]
48#[pin_data]
49pub struct KEvent {
50    #[pin]
51    raw: RawEvent,
52}
53
54impl KEvent {
55    /// Creates a new `KEvent` with the given initial signaled state.
56    pub fn init(initial: bool) -> impl PinInit<Self, core::convert::Infallible> {
57        pin_init::pin_init!(Self {
58            raw <- RawEvent::init(initial),
59        })
60    }
61
62    /// Signals the event.
63    ///
64    /// Wakes up all waiting threads.
65    pub fn signal(&self) {
66        unsafe { cpp_event_signal(self.raw.as_mut_ptr(), Status::OK.into_raw()) }
67    }
68
69    /// Signals the event with a specific status.
70    pub fn signal_etc(&self, status: Status) {
71        unsafe { cpp_event_signal(self.raw.as_mut_ptr(), status.into_raw()) }
72    }
73
74    /// Unsignals the event.
75    pub fn unsignal(&self) {
76        unsafe { cpp_event_unsignal(self.raw.as_mut_ptr()) }
77    }
78
79    /// Waits for the event to be signaled.
80    ///
81    /// Returns `Ok(())` if signaled, or an error status.
82    pub fn wait(&self) -> Result<(), Status> {
83        let status = unsafe { cpp_event_wait(self.raw.as_mut_ptr(), ZX_TIME_INFINITE) };
84        Status::ok(status)
85    }
86
87    /// Waits for the event to be signaled with a deadline.
88    pub fn wait_deadline(&self, deadline: zx_instant_mono_t) -> Result<(), Status> {
89        let status = unsafe { cpp_event_wait(self.raw.as_mut_ptr(), deadline) };
90        Status::ok(status)
91    }
92}
93
94const _: () = {
95    assert!(core::mem::size_of::<RawEvent>() == 72);
96    assert!(core::mem::align_of::<RawEvent>() == 8);
97};