xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/event.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CString;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::MaybeUninit;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::io::AsRawHandle;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::io::RawHandle;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
13*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
14*bb4ee6a4SAndroid Build Coastguard Worker use win_util::SecurityAttributes;
15*bb4ee6a4SAndroid Build Coastguard Worker use win_util::SelfRelativeSecurityDescriptor;
16*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::minwindef::DWORD;
17*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::minwindef::FALSE;
18*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::minwindef::TRUE;
19*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::winerror::WAIT_TIMEOUT;
20*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::handleapi::DuplicateHandle;
21*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::processthreadsapi::GetCurrentProcess;
22*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::CreateEventA;
23*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::OpenEventA;
24*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::ResetEvent;
25*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::SetEvent;
26*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::WaitForSingleObject;
27*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::INFINITE;
28*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::WAIT_FAILED;
29*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::WAIT_OBJECT_0;
30*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::DUPLICATE_SAME_ACCESS;
31*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::EVENT_MODIFY_STATE;
32*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::HANDLE;
33*bb4ee6a4SAndroid Build Coastguard Worker 
34*bb4ee6a4SAndroid Build Coastguard Worker use super::errno_result;
35*bb4ee6a4SAndroid Build Coastguard Worker use super::Error;
36*bb4ee6a4SAndroid Build Coastguard Worker use super::RawDescriptor;
37*bb4ee6a4SAndroid Build Coastguard Worker use super::Result;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::IntoRawDescriptor;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::Event;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::EventWaitResult;
44*bb4ee6a4SAndroid Build Coastguard Worker 
45*bb4ee6a4SAndroid Build Coastguard Worker /// A safe wrapper around Windows synchapi methods used to mimic Linux eventfd (man 2 eventfd).
46*bb4ee6a4SAndroid Build Coastguard Worker /// Since the eventfd isn't using "EFD_SEMAPHORE", we don't need to keep count so we can just use
47*bb4ee6a4SAndroid Build Coastguard Worker /// events.
48*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
49*bb4ee6a4SAndroid Build Coastguard Worker #[serde(transparent)]
50*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) struct PlatformEvent {
51*bb4ee6a4SAndroid Build Coastguard Worker     event_handle: SafeDescriptor,
52*bb4ee6a4SAndroid Build Coastguard Worker }
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker pub trait EventExt {
new_auto_reset() -> Result<Event>55*bb4ee6a4SAndroid Build Coastguard Worker     fn new_auto_reset() -> Result<Event>;
open(name: &str) -> Result<Event>56*bb4ee6a4SAndroid Build Coastguard Worker     fn open(name: &str) -> Result<Event>;
create_event_with_name(name: &str) -> Result<Event>57*bb4ee6a4SAndroid Build Coastguard Worker     fn create_event_with_name(name: &str) -> Result<Event>;
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker impl EventExt for Event {
new_auto_reset() -> Result<Event>61*bb4ee6a4SAndroid Build Coastguard Worker     fn new_auto_reset() -> Result<Event> {
62*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent::new_with_manual_reset(false).map(Event)
63*bb4ee6a4SAndroid Build Coastguard Worker     }
64*bb4ee6a4SAndroid Build Coastguard Worker 
open(name: &str) -> Result<Event>65*bb4ee6a4SAndroid Build Coastguard Worker     fn open(name: &str) -> Result<Event> {
66*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent::open(name).map(Event)
67*bb4ee6a4SAndroid Build Coastguard Worker     }
68*bb4ee6a4SAndroid Build Coastguard Worker 
create_event_with_name(name: &str) -> Result<Event>69*bb4ee6a4SAndroid Build Coastguard Worker     fn create_event_with_name(name: &str) -> Result<Event> {
70*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent::create_event_with_name(name).map(Event)
71*bb4ee6a4SAndroid Build Coastguard Worker     }
72*bb4ee6a4SAndroid Build Coastguard Worker }
73*bb4ee6a4SAndroid Build Coastguard Worker 
74*bb4ee6a4SAndroid Build Coastguard Worker impl PlatformEvent {
new_with_manual_reset(manual_reset: bool) -> Result<PlatformEvent>75*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new_with_manual_reset(manual_reset: bool) -> Result<PlatformEvent> {
76*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
77*bb4ee6a4SAndroid Build Coastguard Worker         let handle = unsafe {
78*bb4ee6a4SAndroid Build Coastguard Worker             CreateEventA(
79*bb4ee6a4SAndroid Build Coastguard Worker                 SecurityAttributes::new_with_security_descriptor(
80*bb4ee6a4SAndroid Build Coastguard Worker                     SelfRelativeSecurityDescriptor::get_singleton(),
81*bb4ee6a4SAndroid Build Coastguard Worker                     /* inherit= */ false,
82*bb4ee6a4SAndroid Build Coastguard Worker                 )
83*bb4ee6a4SAndroid Build Coastguard Worker                 .as_mut(),
84*bb4ee6a4SAndroid Build Coastguard Worker                 if manual_reset { TRUE } else { FALSE },
85*bb4ee6a4SAndroid Build Coastguard Worker                 FALSE, // initial state = unsignalled
86*bb4ee6a4SAndroid Build Coastguard Worker                 null(),
87*bb4ee6a4SAndroid Build Coastguard Worker             )
88*bb4ee6a4SAndroid Build Coastguard Worker         };
89*bb4ee6a4SAndroid Build Coastguard Worker         if handle.is_null() {
90*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
91*bb4ee6a4SAndroid Build Coastguard Worker         }
92*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PlatformEvent {
93*bb4ee6a4SAndroid Build Coastguard Worker             event_handle:
94*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: Safe because the descriptor is valid.
95*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { SafeDescriptor::from_raw_descriptor(handle) },
96*bb4ee6a4SAndroid Build Coastguard Worker         })
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker 
create_event_with_name(name: &str) -> Result<PlatformEvent>99*bb4ee6a4SAndroid Build Coastguard Worker     pub fn create_event_with_name(name: &str) -> Result<PlatformEvent> {
100*bb4ee6a4SAndroid Build Coastguard Worker         let event_str = CString::new(String::from(name)).unwrap();
101*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
102*bb4ee6a4SAndroid Build Coastguard Worker         let handle = unsafe {
103*bb4ee6a4SAndroid Build Coastguard Worker             CreateEventA(
104*bb4ee6a4SAndroid Build Coastguard Worker                 SecurityAttributes::new_with_security_descriptor(
105*bb4ee6a4SAndroid Build Coastguard Worker                     SelfRelativeSecurityDescriptor::get_singleton(),
106*bb4ee6a4SAndroid Build Coastguard Worker                     /* inherit= */ false,
107*bb4ee6a4SAndroid Build Coastguard Worker                 )
108*bb4ee6a4SAndroid Build Coastguard Worker                 .as_mut(),
109*bb4ee6a4SAndroid Build Coastguard Worker                 FALSE, // manual_reset = false
110*bb4ee6a4SAndroid Build Coastguard Worker                 FALSE, // initial state = unsignalled
111*bb4ee6a4SAndroid Build Coastguard Worker                 event_str.as_ptr(),
112*bb4ee6a4SAndroid Build Coastguard Worker             )
113*bb4ee6a4SAndroid Build Coastguard Worker         };
114*bb4ee6a4SAndroid Build Coastguard Worker         if handle.is_null() {
115*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
116*bb4ee6a4SAndroid Build Coastguard Worker         }
117*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PlatformEvent {
118*bb4ee6a4SAndroid Build Coastguard Worker             event_handle:
119*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: Safe because the descriptor is valid.
120*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { SafeDescriptor::from_raw_descriptor(handle) },
121*bb4ee6a4SAndroid Build Coastguard Worker         })
122*bb4ee6a4SAndroid Build Coastguard Worker     }
123*bb4ee6a4SAndroid Build Coastguard Worker 
new() -> Result<PlatformEvent>124*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<PlatformEvent> {
125*bb4ee6a4SAndroid Build Coastguard Worker         // Require manual reset
126*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent::new_with_manual_reset(true)
127*bb4ee6a4SAndroid Build Coastguard Worker     }
128*bb4ee6a4SAndroid Build Coastguard Worker 
open(name: &str) -> Result<PlatformEvent>129*bb4ee6a4SAndroid Build Coastguard Worker     pub fn open(name: &str) -> Result<PlatformEvent> {
130*bb4ee6a4SAndroid Build Coastguard Worker         let event_str = CString::new(String::from(name)).unwrap();
131*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
132*bb4ee6a4SAndroid Build Coastguard Worker         let handle = unsafe { OpenEventA(EVENT_MODIFY_STATE, FALSE, event_str.as_ptr()) };
133*bb4ee6a4SAndroid Build Coastguard Worker         if handle.is_null() {
134*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
135*bb4ee6a4SAndroid Build Coastguard Worker         }
136*bb4ee6a4SAndroid Build Coastguard Worker         Ok(PlatformEvent {
137*bb4ee6a4SAndroid Build Coastguard Worker             event_handle:
138*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: Safe because the descriptor is valid.
139*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { SafeDescriptor::from_raw_descriptor(handle) },
140*bb4ee6a4SAndroid Build Coastguard Worker         })
141*bb4ee6a4SAndroid Build Coastguard Worker     }
142*bb4ee6a4SAndroid Build Coastguard Worker 
143*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::signal`.
signal(&self) -> Result<()>144*bb4ee6a4SAndroid Build Coastguard Worker     pub fn signal(&self) -> Result<()> {
145*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because the descriptor is valid.
146*bb4ee6a4SAndroid Build Coastguard Worker         let event_result = unsafe { SetEvent(self.event_handle.as_raw_descriptor()) };
147*bb4ee6a4SAndroid Build Coastguard Worker         if event_result == 0 {
148*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
149*bb4ee6a4SAndroid Build Coastguard Worker         }
150*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
151*bb4ee6a4SAndroid Build Coastguard Worker     }
152*bb4ee6a4SAndroid Build Coastguard Worker 
reset(&self) -> Result<()>153*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reset(&self) -> Result<()> {
154*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because the descriptor is valid.
155*bb4ee6a4SAndroid Build Coastguard Worker         let res = unsafe { ResetEvent(self.event_handle.as_raw_descriptor()) };
156*bb4ee6a4SAndroid Build Coastguard Worker         if res == 0 {
157*bb4ee6a4SAndroid Build Coastguard Worker             errno_result()
158*bb4ee6a4SAndroid Build Coastguard Worker         } else {
159*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
160*bb4ee6a4SAndroid Build Coastguard Worker         }
161*bb4ee6a4SAndroid Build Coastguard Worker     }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker     /// Wait for the event with an optional timeout and reset the event if it was signaled.
wait_and_reset(&self, timeout: Option<Duration>) -> Result<EventWaitResult>164*bb4ee6a4SAndroid Build Coastguard Worker     fn wait_and_reset(&self, timeout: Option<Duration>) -> Result<EventWaitResult> {
165*bb4ee6a4SAndroid Build Coastguard Worker         let milliseconds = match timeout {
166*bb4ee6a4SAndroid Build Coastguard Worker             Some(timeout) => timeout.as_millis() as DWORD,
167*bb4ee6a4SAndroid Build Coastguard Worker             None => INFINITE,
168*bb4ee6a4SAndroid Build Coastguard Worker         };
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
171*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we pass an event object handle owned by this PlatformEvent.
172*bb4ee6a4SAndroid Build Coastguard Worker         let wait_result = match unsafe {
173*bb4ee6a4SAndroid Build Coastguard Worker             WaitForSingleObject(self.event_handle.as_raw_descriptor(), milliseconds)
174*bb4ee6a4SAndroid Build Coastguard Worker         } {
175*bb4ee6a4SAndroid Build Coastguard Worker             WAIT_OBJECT_0 => Ok(EventWaitResult::Signaled),
176*bb4ee6a4SAndroid Build Coastguard Worker             WAIT_TIMEOUT => Ok(EventWaitResult::TimedOut),
177*bb4ee6a4SAndroid Build Coastguard Worker             WAIT_FAILED => errno_result(),
178*bb4ee6a4SAndroid Build Coastguard Worker             other => Err(Error::new(other)),
179*bb4ee6a4SAndroid Build Coastguard Worker         }?;
180*bb4ee6a4SAndroid Build Coastguard Worker 
181*bb4ee6a4SAndroid Build Coastguard Worker         if wait_result == EventWaitResult::Signaled {
182*bb4ee6a4SAndroid Build Coastguard Worker             self.reset()?;
183*bb4ee6a4SAndroid Build Coastguard Worker         }
184*bb4ee6a4SAndroid Build Coastguard Worker 
185*bb4ee6a4SAndroid Build Coastguard Worker         Ok(wait_result)
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::wait`.
wait(&self) -> Result<()>189*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait(&self) -> Result<()> {
190*bb4ee6a4SAndroid Build Coastguard Worker         let wait_result = self.wait_and_reset(None)?;
191*bb4ee6a4SAndroid Build Coastguard Worker         // Waiting with `INFINITE` can only return when the event is signaled or an error occurs.
192*bb4ee6a4SAndroid Build Coastguard Worker         // `EventWaitResult::TimedOut` is not valid here.
193*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(wait_result, EventWaitResult::Signaled);
194*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
195*bb4ee6a4SAndroid Build Coastguard Worker     }
196*bb4ee6a4SAndroid Build Coastguard Worker 
197*bb4ee6a4SAndroid Build Coastguard Worker     /// See `Event::wait_timeout`.
wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult>198*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wait_timeout(&self, timeout: Duration) -> Result<EventWaitResult> {
199*bb4ee6a4SAndroid Build Coastguard Worker         self.wait_and_reset(Some(timeout))
200*bb4ee6a4SAndroid Build Coastguard Worker     }
201*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<PlatformEvent>202*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<PlatformEvent> {
203*bb4ee6a4SAndroid Build Coastguard Worker         let mut event_clone: HANDLE = MaybeUninit::uninit().as_mut_ptr();
204*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
205*bb4ee6a4SAndroid Build Coastguard Worker         let duplicate_result = unsafe {
206*bb4ee6a4SAndroid Build Coastguard Worker             DuplicateHandle(
207*bb4ee6a4SAndroid Build Coastguard Worker                 GetCurrentProcess(),
208*bb4ee6a4SAndroid Build Coastguard Worker                 self.event_handle.as_raw_descriptor(),
209*bb4ee6a4SAndroid Build Coastguard Worker                 GetCurrentProcess(),
210*bb4ee6a4SAndroid Build Coastguard Worker                 &mut event_clone,
211*bb4ee6a4SAndroid Build Coastguard Worker                 0,
212*bb4ee6a4SAndroid Build Coastguard Worker                 0,
213*bb4ee6a4SAndroid Build Coastguard Worker                 DUPLICATE_SAME_ACCESS,
214*bb4ee6a4SAndroid Build Coastguard Worker             )
215*bb4ee6a4SAndroid Build Coastguard Worker         };
216*bb4ee6a4SAndroid Build Coastguard Worker         if duplicate_result == 0 {
217*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
218*bb4ee6a4SAndroid Build Coastguard Worker         }
219*bb4ee6a4SAndroid Build Coastguard Worker         Ok(
220*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: Safe because the descriptor is valid.
221*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { PlatformEvent::from_raw_descriptor(event_clone) },
222*bb4ee6a4SAndroid Build Coastguard Worker         )
223*bb4ee6a4SAndroid Build Coastguard Worker     }
224*bb4ee6a4SAndroid Build Coastguard Worker }
225*bb4ee6a4SAndroid Build Coastguard Worker 
226*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for PlatformEvent {
as_raw_descriptor(&self) -> RawDescriptor227*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptor(&self) -> RawDescriptor {
228*bb4ee6a4SAndroid Build Coastguard Worker         self.event_handle.as_raw_descriptor()
229*bb4ee6a4SAndroid Build Coastguard Worker     }
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker 
232*bb4ee6a4SAndroid Build Coastguard Worker impl FromRawDescriptor for PlatformEvent {
233*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: Safe because the descriptor is expected to be valid.
from_raw_descriptor(descriptor: RawDescriptor) -> Self234*bb4ee6a4SAndroid Build Coastguard Worker     unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
235*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent {
236*bb4ee6a4SAndroid Build Coastguard Worker             event_handle: SafeDescriptor::from_raw_descriptor(descriptor),
237*bb4ee6a4SAndroid Build Coastguard Worker         }
238*bb4ee6a4SAndroid Build Coastguard Worker     }
239*bb4ee6a4SAndroid Build Coastguard Worker }
240*bb4ee6a4SAndroid Build Coastguard Worker 
241*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawHandle for PlatformEvent {
as_raw_handle(&self) -> RawHandle242*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_handle(&self) -> RawHandle {
243*bb4ee6a4SAndroid Build Coastguard Worker         self.as_raw_descriptor()
244*bb4ee6a4SAndroid Build Coastguard Worker     }
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker impl IntoRawDescriptor for PlatformEvent {
into_raw_descriptor(self) -> RawDescriptor248*bb4ee6a4SAndroid Build Coastguard Worker     fn into_raw_descriptor(self) -> RawDescriptor {
249*bb4ee6a4SAndroid Build Coastguard Worker         self.event_handle.into_raw_descriptor()
250*bb4ee6a4SAndroid Build Coastguard Worker     }
251*bb4ee6a4SAndroid Build Coastguard Worker }
252*bb4ee6a4SAndroid Build Coastguard Worker 
253*bb4ee6a4SAndroid Build Coastguard Worker impl From<PlatformEvent> for SafeDescriptor {
from(evt: PlatformEvent) -> Self254*bb4ee6a4SAndroid Build Coastguard Worker     fn from(evt: PlatformEvent) -> Self {
255*bb4ee6a4SAndroid Build Coastguard Worker         evt.event_handle
256*bb4ee6a4SAndroid Build Coastguard Worker     }
257*bb4ee6a4SAndroid Build Coastguard Worker }
258*bb4ee6a4SAndroid Build Coastguard Worker 
259*bb4ee6a4SAndroid Build Coastguard Worker impl From<SafeDescriptor> for PlatformEvent {
from(sd: SafeDescriptor) -> Self260*bb4ee6a4SAndroid Build Coastguard Worker     fn from(sd: SafeDescriptor) -> Self {
261*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent { event_handle: sd }
262*bb4ee6a4SAndroid Build Coastguard Worker     }
263*bb4ee6a4SAndroid Build Coastguard Worker }
264*bb4ee6a4SAndroid Build Coastguard Worker 
265*bb4ee6a4SAndroid Build Coastguard Worker // Safety:
266*bb4ee6a4SAndroid Build Coastguard Worker // PlatformEvent is safe for send & Sync despite containing a raw handle to its
267*bb4ee6a4SAndroid Build Coastguard Worker // file mapping object. As long as the instance to PlatformEvent stays alive, this
268*bb4ee6a4SAndroid Build Coastguard Worker // pointer will be a valid handle.
269*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for PlatformEvent {}
270*bb4ee6a4SAndroid Build Coastguard Worker // Safety: See comments for impl Send
271*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for PlatformEvent {}
272*bb4ee6a4SAndroid Build Coastguard Worker 
273*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
274*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
275*bb4ee6a4SAndroid Build Coastguard Worker     use winapi::shared::winerror::WAIT_TIMEOUT;
276*bb4ee6a4SAndroid Build Coastguard Worker     use winapi::um::winbase::INFINITE;
277*bb4ee6a4SAndroid Build Coastguard Worker     use winapi::um::winbase::WAIT_OBJECT_0;
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
new()282*bb4ee6a4SAndroid Build Coastguard Worker     fn new() {
283*bb4ee6a4SAndroid Build Coastguard Worker         PlatformEvent::new().unwrap();
284*bb4ee6a4SAndroid Build Coastguard Worker     }
285*bb4ee6a4SAndroid Build Coastguard Worker 
286*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_write()287*bb4ee6a4SAndroid Build Coastguard Worker     fn read_write() {
288*bb4ee6a4SAndroid Build Coastguard Worker         let evt = PlatformEvent::new().unwrap();
289*bb4ee6a4SAndroid Build Coastguard Worker         evt.signal().unwrap();
290*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(evt.wait(), Ok(()));
291*bb4ee6a4SAndroid Build Coastguard Worker     }
292*bb4ee6a4SAndroid Build Coastguard Worker 
293*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_write_auto_reset()294*bb4ee6a4SAndroid Build Coastguard Worker     fn read_write_auto_reset() {
295*bb4ee6a4SAndroid Build Coastguard Worker         let evt = PlatformEvent::new_with_manual_reset(false).unwrap();
296*bb4ee6a4SAndroid Build Coastguard Worker         evt.signal().unwrap();
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the notification.
299*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
300*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), INFINITE) };
301*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(result, WAIT_OBJECT_0);
302*bb4ee6a4SAndroid Build Coastguard Worker 
303*bb4ee6a4SAndroid Build Coastguard Worker         // The notification should have reset since we already received it.
304*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
305*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) };
306*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(result, WAIT_TIMEOUT);
307*bb4ee6a4SAndroid Build Coastguard Worker     }
308*bb4ee6a4SAndroid Build Coastguard Worker 
309*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_write_notifies_until_read()310*bb4ee6a4SAndroid Build Coastguard Worker     fn read_write_notifies_until_read() {
311*bb4ee6a4SAndroid Build Coastguard Worker         let evt = PlatformEvent::new().unwrap();
312*bb4ee6a4SAndroid Build Coastguard Worker         evt.signal().unwrap();
313*bb4ee6a4SAndroid Build Coastguard Worker 
314*bb4ee6a4SAndroid Build Coastguard Worker         // Wait for the notification.
315*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
316*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), INFINITE) };
317*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(result, WAIT_OBJECT_0);
318*bb4ee6a4SAndroid Build Coastguard Worker 
319*bb4ee6a4SAndroid Build Coastguard Worker         // The notification should still be active because read wasn't called.
320*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
321*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) };
322*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(result, WAIT_OBJECT_0);
323*bb4ee6a4SAndroid Build Coastguard Worker 
324*bb4ee6a4SAndroid Build Coastguard Worker         // Read and ensure the notification has cleared.
325*bb4ee6a4SAndroid Build Coastguard Worker         evt.wait().expect("Failed to read event.");
326*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: Safe because return value is checked.
327*bb4ee6a4SAndroid Build Coastguard Worker         let result = unsafe { WaitForSingleObject(evt.as_raw_descriptor(), 0) };
328*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(result, WAIT_TIMEOUT);
329*bb4ee6a4SAndroid Build Coastguard Worker     }
330*bb4ee6a4SAndroid Build Coastguard Worker 
331*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
clone()332*bb4ee6a4SAndroid Build Coastguard Worker     fn clone() {
333*bb4ee6a4SAndroid Build Coastguard Worker         let evt = PlatformEvent::new().unwrap();
334*bb4ee6a4SAndroid Build Coastguard Worker         let evt_clone = evt.try_clone().unwrap();
335*bb4ee6a4SAndroid Build Coastguard Worker         evt.signal().unwrap();
336*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(evt_clone.wait(), Ok(()));
337*bb4ee6a4SAndroid Build Coastguard Worker     }
338*bb4ee6a4SAndroid Build Coastguard Worker 
339*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
timeout()340*bb4ee6a4SAndroid Build Coastguard Worker     fn timeout() {
341*bb4ee6a4SAndroid Build Coastguard Worker         let evt = PlatformEvent::new().expect("failed to create event");
342*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
343*bb4ee6a4SAndroid Build Coastguard Worker             evt.wait_timeout(Duration::from_millis(1))
344*bb4ee6a4SAndroid Build Coastguard Worker                 .expect("failed to read from event with timeout"),
345*bb4ee6a4SAndroid Build Coastguard Worker             EventWaitResult::TimedOut
346*bb4ee6a4SAndroid Build Coastguard Worker         );
347*bb4ee6a4SAndroid Build Coastguard Worker     }
348*bb4ee6a4SAndroid Build Coastguard Worker }
349