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::os::windows::io::AsRawHandle; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::os::windows::io::RawHandle; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration; 9*bb4ee6a4SAndroid Build Coastguard Worker 10*bb4ee6a4SAndroid Build Coastguard Worker use win_util::LargeInteger; 11*bb4ee6a4SAndroid Build Coastguard Worker use win_util::SecurityAttributes; 12*bb4ee6a4SAndroid Build Coastguard Worker use win_util::SelfRelativeSecurityDescriptor; 13*bb4ee6a4SAndroid Build Coastguard Worker use winapi::shared::minwindef::FALSE; 14*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::CancelWaitableTimer; 15*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::SetWaitableTimer; 16*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::synchapi::WaitForSingleObject; 17*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::CreateWaitableTimerA; 18*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::INFINITE; 19*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winbase::WAIT_OBJECT_0; 20*bb4ee6a4SAndroid Build Coastguard Worker 21*bb4ee6a4SAndroid Build Coastguard Worker use super::errno_result; 22*bb4ee6a4SAndroid Build Coastguard Worker use super::platform_timer_utils::nt_query_timer_resolution; 23*bb4ee6a4SAndroid Build Coastguard Worker use super::Result; 24*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor; 25*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::FromRawDescriptor; 26*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::SafeDescriptor; 27*bb4ee6a4SAndroid Build Coastguard Worker use crate::timer::Timer; 28*bb4ee6a4SAndroid Build Coastguard Worker use crate::timer::TimerTrait; 29*bb4ee6a4SAndroid Build Coastguard Worker 30*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawHandle for Timer { as_raw_handle(&self) -> RawHandle31*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_handle(&self) -> RawHandle { 32*bb4ee6a4SAndroid Build Coastguard Worker self.handle.as_raw_descriptor() 33*bb4ee6a4SAndroid Build Coastguard Worker } 34*bb4ee6a4SAndroid Build Coastguard Worker } 35*bb4ee6a4SAndroid Build Coastguard Worker 36*bb4ee6a4SAndroid Build Coastguard Worker impl Timer { 37*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new timer. The timer is initally disarmed and must be armed by calling 38*bb4ee6a4SAndroid Build Coastguard Worker /// `reset`. Note that this timer MAY wake/trigger early due to limitations on 39*bb4ee6a4SAndroid Build Coastguard Worker /// SetWaitableTimer (see <https://github.com/rust-lang/rust/issues/43376>). new() -> Result<Timer>40*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> Result<Timer> { 41*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 42*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value. 43*bb4ee6a4SAndroid Build Coastguard Worker let handle = unsafe { 44*bb4ee6a4SAndroid Build Coastguard Worker CreateWaitableTimerA( 45*bb4ee6a4SAndroid Build Coastguard Worker // Not inheritable, duplicate before passing to child prcesses 46*bb4ee6a4SAndroid Build Coastguard Worker SecurityAttributes::new_with_security_descriptor( 47*bb4ee6a4SAndroid Build Coastguard Worker SelfRelativeSecurityDescriptor::get_singleton(), 48*bb4ee6a4SAndroid Build Coastguard Worker /* inherit= */ false, 49*bb4ee6a4SAndroid Build Coastguard Worker ) 50*bb4ee6a4SAndroid Build Coastguard Worker .as_mut(), 51*bb4ee6a4SAndroid Build Coastguard Worker // This is a synchronization timer, not a manual-reset timer. 52*bb4ee6a4SAndroid Build Coastguard Worker FALSE, 53*bb4ee6a4SAndroid Build Coastguard Worker // TODO (colindr) b/145622516 - we may have to give this a name if we later 54*bb4ee6a4SAndroid Build Coastguard Worker // want to use names to test object equality 55*bb4ee6a4SAndroid Build Coastguard Worker ptr::null_mut(), 56*bb4ee6a4SAndroid Build Coastguard Worker ) 57*bb4ee6a4SAndroid Build Coastguard Worker }; 58*bb4ee6a4SAndroid Build Coastguard Worker 59*bb4ee6a4SAndroid Build Coastguard Worker if handle.is_null() { 60*bb4ee6a4SAndroid Build Coastguard Worker return errno_result(); 61*bb4ee6a4SAndroid Build Coastguard Worker } 62*bb4ee6a4SAndroid Build Coastguard Worker 63*bb4ee6a4SAndroid Build Coastguard Worker Ok(Timer { 64*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 65*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we uniquely own the file descriptor. 66*bb4ee6a4SAndroid Build Coastguard Worker handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) }, 67*bb4ee6a4SAndroid Build Coastguard Worker interval: None, 68*bb4ee6a4SAndroid Build Coastguard Worker }) 69*bb4ee6a4SAndroid Build Coastguard Worker } 70*bb4ee6a4SAndroid Build Coastguard Worker reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()>71*bb4ee6a4SAndroid Build Coastguard Worker fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> { 72*bb4ee6a4SAndroid Build Coastguard Worker // If interval is 0 or None it means that this timer does not repeat. We 73*bb4ee6a4SAndroid Build Coastguard Worker // set self.interval to None in this case so it can easily be checked 74*bb4ee6a4SAndroid Build Coastguard Worker // in self.wait. 75*bb4ee6a4SAndroid Build Coastguard Worker if interval == Some(Duration::from_secs(0)) { 76*bb4ee6a4SAndroid Build Coastguard Worker interval = None; 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker self.interval = interval; 79*bb4ee6a4SAndroid Build Coastguard Worker // Windows timers use negative values for relative times, and positive 80*bb4ee6a4SAndroid Build Coastguard Worker // values for absolute times, so we'll use negative times. 81*bb4ee6a4SAndroid Build Coastguard Worker 82*bb4ee6a4SAndroid Build Coastguard Worker // Windows timers also use a 64 number of 100 nanosecond intervals, 83*bb4ee6a4SAndroid Build Coastguard Worker // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100) 84*bb4ee6a4SAndroid Build Coastguard Worker 85*bb4ee6a4SAndroid Build Coastguard Worker let due_time = LargeInteger::new( 86*bb4ee6a4SAndroid Build Coastguard Worker -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64), 87*bb4ee6a4SAndroid Build Coastguard Worker ); 88*bb4ee6a4SAndroid Build Coastguard Worker let period: i32 = match interval { 89*bb4ee6a4SAndroid Build Coastguard Worker Some(int) => { 90*bb4ee6a4SAndroid Build Coastguard Worker if int.is_zero() { 91*bb4ee6a4SAndroid Build Coastguard Worker // Duration of zero implies non-periodic, which means setting period 92*bb4ee6a4SAndroid Build Coastguard Worker // to 0ms. 93*bb4ee6a4SAndroid Build Coastguard Worker 0 94*bb4ee6a4SAndroid Build Coastguard Worker } else { 95*bb4ee6a4SAndroid Build Coastguard Worker // Otherwise, convert to ms and make sure it's >=1ms. 96*bb4ee6a4SAndroid Build Coastguard Worker std::cmp::max(1, int.as_millis() as i32) 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker } 99*bb4ee6a4SAndroid Build Coastguard Worker // Period of 0ms=non-periodic. 100*bb4ee6a4SAndroid Build Coastguard Worker None => 0, 101*bb4ee6a4SAndroid Build Coastguard Worker }; 102*bb4ee6a4SAndroid Build Coastguard Worker 103*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 104*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value. 105*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { 106*bb4ee6a4SAndroid Build Coastguard Worker SetWaitableTimer( 107*bb4ee6a4SAndroid Build Coastguard Worker self.as_raw_descriptor(), 108*bb4ee6a4SAndroid Build Coastguard Worker &*due_time, 109*bb4ee6a4SAndroid Build Coastguard Worker period, 110*bb4ee6a4SAndroid Build Coastguard Worker None, // no completion routine 111*bb4ee6a4SAndroid Build Coastguard Worker ptr::null_mut(), // or routine argument 112*bb4ee6a4SAndroid Build Coastguard Worker FALSE, // no restoring system from power conservation mode 113*bb4ee6a4SAndroid Build Coastguard Worker ) 114*bb4ee6a4SAndroid Build Coastguard Worker }; 115*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 { 116*bb4ee6a4SAndroid Build Coastguard Worker return errno_result(); 117*bb4ee6a4SAndroid Build Coastguard Worker } 118*bb4ee6a4SAndroid Build Coastguard Worker 119*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 120*bb4ee6a4SAndroid Build Coastguard Worker } 121*bb4ee6a4SAndroid Build Coastguard Worker } 122*bb4ee6a4SAndroid Build Coastguard Worker 123*bb4ee6a4SAndroid Build Coastguard Worker impl TimerTrait for Timer { reset_oneshot(&mut self, dur: Duration) -> Result<()>124*bb4ee6a4SAndroid Build Coastguard Worker fn reset_oneshot(&mut self, dur: Duration) -> Result<()> { 125*bb4ee6a4SAndroid Build Coastguard Worker self.reset(dur, None) 126*bb4ee6a4SAndroid Build Coastguard Worker } 127*bb4ee6a4SAndroid Build Coastguard Worker reset_repeating(&mut self, interval: Duration) -> Result<()>128*bb4ee6a4SAndroid Build Coastguard Worker fn reset_repeating(&mut self, interval: Duration) -> Result<()> { 129*bb4ee6a4SAndroid Build Coastguard Worker self.reset(interval, Some(interval)) 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker wait(&mut self) -> Result<()>132*bb4ee6a4SAndroid Build Coastguard Worker fn wait(&mut self) -> Result<()> { 133*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 134*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value. 135*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { WaitForSingleObject(self.as_raw_descriptor(), INFINITE) }; 136*bb4ee6a4SAndroid Build Coastguard Worker 137*bb4ee6a4SAndroid Build Coastguard Worker // Should return WAIT_OBJECT_0, otherwise it's some sort of error or 138*bb4ee6a4SAndroid Build Coastguard Worker // timeout (which shouldn't happen in this case). 139*bb4ee6a4SAndroid Build Coastguard Worker match ret { 140*bb4ee6a4SAndroid Build Coastguard Worker WAIT_OBJECT_0 => Ok(()), 141*bb4ee6a4SAndroid Build Coastguard Worker _ => errno_result(), 142*bb4ee6a4SAndroid Build Coastguard Worker } 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker mark_waited(&mut self) -> Result<bool>145*bb4ee6a4SAndroid Build Coastguard Worker fn mark_waited(&mut self) -> Result<bool> { 146*bb4ee6a4SAndroid Build Coastguard Worker // We use a synchronization timer on windows, meaning waiting on the timer automatically 147*bb4ee6a4SAndroid Build Coastguard Worker // un-signals the timer. We assume this is atomic so the return value is always false. 148*bb4ee6a4SAndroid Build Coastguard Worker Ok(false) 149*bb4ee6a4SAndroid Build Coastguard Worker } 150*bb4ee6a4SAndroid Build Coastguard Worker clear(&mut self) -> Result<()>151*bb4ee6a4SAndroid Build Coastguard Worker fn clear(&mut self) -> Result<()> { 152*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 153*bb4ee6a4SAndroid Build Coastguard Worker // Safe because this doesn't modify any memory and we check the return value. 154*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { CancelWaitableTimer(self.as_raw_descriptor()) }; 155*bb4ee6a4SAndroid Build Coastguard Worker 156*bb4ee6a4SAndroid Build Coastguard Worker if ret == 0 { 157*bb4ee6a4SAndroid Build Coastguard Worker return errno_result(); 158*bb4ee6a4SAndroid Build Coastguard Worker } 159*bb4ee6a4SAndroid Build Coastguard Worker 160*bb4ee6a4SAndroid Build Coastguard Worker self.interval = None; 161*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 162*bb4ee6a4SAndroid Build Coastguard Worker } 163*bb4ee6a4SAndroid Build Coastguard Worker resolution(&self) -> Result<Duration>164*bb4ee6a4SAndroid Build Coastguard Worker fn resolution(&self) -> Result<Duration> { 165*bb4ee6a4SAndroid Build Coastguard Worker nt_query_timer_resolution().map(|(current_res, _)| current_res) 166*bb4ee6a4SAndroid Build Coastguard Worker } 167*bb4ee6a4SAndroid Build Coastguard Worker } 168