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