xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/timer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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