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 } 71 72 impl TimerTrait for Timer { reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()>73 fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> { 74 // If interval is 0 or None it means that this timer does not repeat. We 75 // set self.interval to None in this case so it can easily be checked 76 // in self.wait. 77 if interval == Some(Duration::from_secs(0)) { 78 interval = None; 79 } 80 self.interval = interval; 81 // Windows timers use negative values for relative times, and positive 82 // values for absolute times, so we'll use negative times. 83 84 // Windows timers also use a 64 number of 100 nanosecond intervals, 85 // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100) 86 87 let due_time = LargeInteger::new( 88 -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64), 89 ); 90 let period: i32 = match interval { 91 Some(int) => { 92 if int.is_zero() { 93 // Duration of zero implies non-periodic, which means setting period 94 // to 0ms. 95 0 96 } else { 97 // Otherwise, convert to ms and make sure it's >=1ms. 98 std::cmp::max(1, int.as_millis() as i32) 99 } 100 } 101 // Period of 0ms=non-periodic. 102 None => 0, 103 }; 104 105 // SAFETY: 106 // Safe because this doesn't modify any memory and we check the return value. 107 let ret = unsafe { 108 SetWaitableTimer( 109 self.as_raw_descriptor(), 110 &*due_time, 111 period, 112 None, // no completion routine 113 ptr::null_mut(), // or routine argument 114 FALSE, // no restoring system from power conservation mode 115 ) 116 }; 117 if ret == 0 { 118 return errno_result(); 119 } 120 121 Ok(()) 122 } 123 wait(&mut self) -> Result<()>124 fn wait(&mut self) -> Result<()> { 125 // SAFETY: 126 // Safe because this doesn't modify any memory and we check the return value. 127 let ret = unsafe { WaitForSingleObject(self.as_raw_descriptor(), INFINITE) }; 128 129 // Should return WAIT_OBJECT_0, otherwise it's some sort of error or 130 // timeout (which shouldn't happen in this case). 131 match ret { 132 WAIT_OBJECT_0 => Ok(()), 133 _ => errno_result(), 134 } 135 } 136 mark_waited(&mut self) -> Result<bool>137 fn mark_waited(&mut self) -> Result<bool> { 138 // We use a synchronization timer on windows, meaning waiting on the timer automatically 139 // un-signals the timer. We assume this is atomic so the return value is always false. 140 Ok(false) 141 } 142 clear(&mut self) -> Result<()>143 fn clear(&mut self) -> Result<()> { 144 // SAFETY: 145 // Safe because this doesn't modify any memory and we check the return value. 146 let ret = unsafe { CancelWaitableTimer(self.as_raw_descriptor()) }; 147 148 if ret == 0 { 149 return errno_result(); 150 } 151 152 self.interval = None; 153 Ok(()) 154 } 155 resolution(&self) -> Result<Duration>156 fn resolution(&self) -> Result<Duration> { 157 nt_query_timer_resolution().map(|(current_res, _)| current_res) 158 } 159 } 160