• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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