• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 use crate::sys::{event_init, event_signal, event_wait_timeout};
25 use crate::sys::{event_t, status_t, uint};
26 use crate::INFINITE_TIME;
27 use alloc::boxed::Box;
28 use core::cell::UnsafeCell;
29 use core::mem;
30 
31 pub use crate::sys::EVENT_FLAG_AUTOUNSIGNAL;
32 
33 // `event_t`s should not move since they contain wait queues which contains
34 // linked list nodes. The kernel may write back to the non-node fields as well.
35 // TODO: add Unpin as a negative trait bound once the rustc feature is stabilized.
36 // impl !Unpin for event_t {}
37 
38 #[derive(Debug)]
39 pub struct Event(Box<UnsafeCell<event_t>>);
40 
41 impl Event {
new(initial: bool, flags: uint) -> Self42     pub fn new(initial: bool, flags: uint) -> Self {
43         // SAFETY: event_t is a C type which can be zeroed out
44         let event = unsafe { mem::zeroed() };
45         let mut boxed_event = Box::new(UnsafeCell::new(event));
46         // SAFETY: event_init just writes to the fields of event_t. The self-referential `wait`
47         // field is written to after the event_t is placed on the heap so it won't become
48         // invalidated until it's dropped.
49         unsafe { event_init(boxed_event.get_mut(), initial, flags) };
50         Self(boxed_event)
51     }
52 
wait(&self) -> status_t53     pub fn wait(&self) -> status_t {
54         // SAFETY: One or more threads are allowed to wait for an event to be signaled
55         unsafe { event_wait_timeout(self.0.get(), INFINITE_TIME) }
56     }
57 
signal(&self) -> status_t58     pub fn signal(&self) -> status_t {
59         // SAFETY: Events may be signaled from any thread or interrupt context if the reschedule
60         // parameter is false
61         unsafe {
62             event_signal(self.0.get(), false /* reschedule */)
63         }
64     }
65 }
66 
67 // SAFETY: More than one thread may wait using an &Event but only one will be woken up and change
68 // its signaled field. &Event provides no other APIs to modify its state
69 unsafe impl Sync for Event {}
70 
71 // SAFETY: Event is heap allocated so it may be freely sent across threads without invalidating it.
72 // It may also be waited on and signaled from any thread.
73 unsafe impl Send for Event {}
74