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