1 // Copyright 2022 The Chromium OS Authors. All rights reserved. 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::{ 6 os::windows::io::{AsRawHandle, RawHandle}, 7 ptr, 8 time::Duration, 9 }; 10 11 use win_util::{LargeInteger, SecurityAttributes, SelfRelativeSecurityDescriptor}; 12 use winapi::{ 13 shared::{minwindef::FALSE, winerror::WAIT_TIMEOUT}, 14 um::{ 15 synchapi::{CancelWaitableTimer, SetWaitableTimer, WaitForSingleObject}, 16 winbase::{CreateWaitableTimerA, INFINITE, WAIT_OBJECT_0}, 17 }, 18 }; 19 20 use super::{ 21 super::{errno_result, win::nt_query_timer_resolution, Result}, 22 Timer, WaitResult, 23 }; 24 use crate::descriptor::{AsRawDescriptor, FromRawDescriptor, SafeDescriptor}; 25 26 impl AsRawHandle for Timer { as_raw_handle(&self) -> RawHandle27 fn as_raw_handle(&self) -> RawHandle { 28 self.handle.as_raw_descriptor() 29 } 30 } 31 32 impl Timer { 33 /// Creates a new timer. The timer is initally disarmed and must be armed by calling 34 /// `reset`. new() -> Result<Timer>35 pub fn new() -> Result<Timer> { 36 // Safe because this doesn't modify any memory and we check the return value. 37 let handle = unsafe { 38 CreateWaitableTimerA( 39 // Not inheritable, duplicate before passing to child prcesses 40 SecurityAttributes::new_with_security_descriptor( 41 SelfRelativeSecurityDescriptor::get_singleton(), 42 /* inherit= */ false, 43 ) 44 .as_mut(), 45 // This is a synchronization timer, not a manual-reset timer. 46 FALSE, 47 // TODO (colindr) b/145622516 - we may have to give this a name if we later 48 // want to use names to test object equality 49 ptr::null_mut(), 50 ) 51 }; 52 53 if handle.is_null() { 54 return errno_result(); 55 } 56 57 // Safe because we uniquely own the file descriptor. 58 Ok(Timer { 59 handle: unsafe { SafeDescriptor::from_raw_descriptor(handle) }, 60 interval: None, 61 }) 62 } 63 64 /// Sets the timer to expire after `dur`. If `interval` is not `None` and non-zero 65 /// it represents the period for repeated expirations after the initial expiration. 66 /// Otherwise the timer will expire just once. Cancels any existing duration and 67 /// repeating interval. reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()>68 pub fn reset(&mut self, dur: Duration, mut interval: Option<Duration>) -> Result<()> { 69 // If interval is 0 or None it means that this timer does not repeat. We 70 // set self.interval to None in this case so it can easily be checked 71 // in self.wait. 72 if interval == Some(Duration::from_secs(0)) { 73 interval = None; 74 } 75 self.interval = interval; 76 // Windows timers use negative values for relative times, and positive 77 // values for absolute times, so we'll use negative times. 78 79 // Windows timers also use a 64 number of 100 nanosecond intervals, 80 // which we get like so: (dur.as_secs()*1e7 + dur.subsec_nanos()/100) 81 82 let due_time = LargeInteger::new( 83 -((dur.as_secs() * 10_000_000 + (dur.subsec_nanos() as u64) / 100) as i64), 84 ); 85 let period: i32 = match interval { 86 Some(int) => int.as_millis() as i32, 87 None => 0, 88 }; 89 90 // Safe because this doesn't modify any memory and we check the return value. 91 let ret = unsafe { 92 SetWaitableTimer( 93 self.as_raw_descriptor(), 94 &*due_time, 95 period, 96 None, // no completion routine 97 ptr::null_mut(), // or routine argument 98 FALSE, // no restoring system from power conservation mode 99 ) 100 }; 101 if ret == 0 { 102 return errno_result(); 103 } 104 105 Ok(()) 106 } 107 108 /// Waits until the timer expires, returing WaitResult::Expired when it expires. 109 /// 110 /// If timeout is not None, block for a maximum of the given `timeout` duration. 111 /// If a timeout occurs, return WaitResult::Timeout. wait(&mut self, timeout: Option<Duration>) -> Result<WaitResult>112 pub fn wait(&mut self, timeout: Option<Duration>) -> Result<WaitResult> { 113 let timeout = match timeout { 114 None => INFINITE, 115 Some(dur) => dur.as_millis() as u32, 116 }; 117 118 // Safe because this doesn't modify any memory and we check the return value. 119 let ret = unsafe { WaitForSingleObject(self.as_raw_descriptor(), timeout) }; 120 121 // Should return WAIT_OBJECT_0, otherwise it's some sort of error or 122 // timeout (which shouldn't happen in this case). 123 match ret { 124 WAIT_OBJECT_0 => Ok(WaitResult::Expired), 125 WAIT_TIMEOUT => Ok(WaitResult::Timeout), 126 _ => errno_result(), 127 } 128 } 129 130 /// After a timer is triggered from an EventContext, mark the timer as having been waited for. 131 /// If a timer is not marked waited, it will immediately trigger the event context again. This 132 /// does not need to be called after calling Timer::wait. 133 /// 134 /// Returns true if the timer has been adjusted since the EventContext was triggered by this 135 /// timer. mark_waited(&mut self) -> Result<bool>136 pub fn mark_waited(&mut self) -> Result<bool> { 137 // We use a synchronization timer on windows, meaning waiting on the timer automatically 138 // un-signals the timer. We assume this is atomic so the return value is always false. 139 Ok(false) 140 } 141 142 /// Disarms the timer. clear(&mut self) -> Result<()>143 pub fn clear(&mut self) -> Result<()> { 144 // Safe because this doesn't modify any memory and we check the return value. 145 let ret = unsafe { CancelWaitableTimer(self.as_raw_descriptor()) }; 146 147 if ret == 0 { 148 return errno_result(); 149 } 150 151 self.interval = None; 152 Ok(()) 153 } 154 155 /// Returns the resolution of timers on the host. resolution() -> Result<Duration>156 pub fn resolution() -> Result<Duration> { 157 nt_query_timer_resolution().map(|(current_res, _)| current_res) 158 } 159 } 160