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