xref: /aosp_15_r20/external/crosvm/base/src/sys/macos/timer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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::mem;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::errno_result;
9*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::Error;
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::errno::Result;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::macos::kqueue::make_kevent;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::macos::kqueue::Kqueue;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::unix::clone_descriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::Timer;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker impl Timer {
new() -> Result<Timer>18*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<Timer> {
19*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Timer {
20*bb4ee6a4SAndroid Build Coastguard Worker             handle: SafeDescriptor::from(Kqueue::new()?),
21*bb4ee6a4SAndroid Build Coastguard Worker             interval: None,
22*bb4ee6a4SAndroid Build Coastguard Worker         })
23*bb4ee6a4SAndroid Build Coastguard Worker     }
24*bb4ee6a4SAndroid Build Coastguard Worker 
queue(&self) -> Result<Kqueue>25*bb4ee6a4SAndroid Build Coastguard Worker     fn queue(&self) -> Result<Kqueue> {
26*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Kqueue::from(clone_descriptor(&self.handle)?))
27*bb4ee6a4SAndroid Build Coastguard Worker     }
28*bb4ee6a4SAndroid Build Coastguard Worker }
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker impl crate::TimerTrait for Timer {
reset_oneshot(&mut self, delay: Duration) -> Result<()>31*bb4ee6a4SAndroid Build Coastguard Worker     fn reset_oneshot(&mut self, delay: Duration) -> Result<()> {
32*bb4ee6a4SAndroid Build Coastguard Worker         self.interval = None;
33*bb4ee6a4SAndroid Build Coastguard Worker         let mut event = make_kevent(
34*bb4ee6a4SAndroid Build Coastguard Worker             libc::EVFILT_TIMER,
35*bb4ee6a4SAndroid Build Coastguard Worker             libc::EV_ADD | libc::EV_ONESHOT,
36*bb4ee6a4SAndroid Build Coastguard Worker             libc::NOTE_NSECONDS,
37*bb4ee6a4SAndroid Build Coastguard Worker         );
38*bb4ee6a4SAndroid Build Coastguard Worker         event.data = delay
39*bb4ee6a4SAndroid Build Coastguard Worker             .as_nanos()
40*bb4ee6a4SAndroid Build Coastguard Worker             .try_into()
41*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::new(libc::EINVAL))?;
42*bb4ee6a4SAndroid Build Coastguard Worker         self.queue()?.kevent(&[event], &mut [], None)?;
43*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
44*bb4ee6a4SAndroid Build Coastguard Worker     }
45*bb4ee6a4SAndroid Build Coastguard Worker 
reset_repeating(&mut self, interval: Duration) -> Result<()>46*bb4ee6a4SAndroid Build Coastguard Worker     fn reset_repeating(&mut self, interval: Duration) -> Result<()> {
47*bb4ee6a4SAndroid Build Coastguard Worker         self.interval = Some(interval);
48*bb4ee6a4SAndroid Build Coastguard Worker         let mut event = make_kevent(libc::EVFILT_TIMER, libc::EV_ADD, libc::NOTE_NSECONDS);
49*bb4ee6a4SAndroid Build Coastguard Worker         event.data = interval
50*bb4ee6a4SAndroid Build Coastguard Worker             .as_nanos()
51*bb4ee6a4SAndroid Build Coastguard Worker             .try_into()
52*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|_| Error::new(libc::EINVAL))?;
53*bb4ee6a4SAndroid Build Coastguard Worker         self.queue()?.kevent(&[event], &mut [], None)?;
54*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
55*bb4ee6a4SAndroid Build Coastguard Worker     }
56*bb4ee6a4SAndroid Build Coastguard Worker 
wait(&mut self) -> Result<()>57*bb4ee6a4SAndroid Build Coastguard Worker     fn wait(&mut self) -> Result<()> {
58*bb4ee6a4SAndroid Build Coastguard Worker         let mut event = [make_kevent(0, 0, 0)];
59*bb4ee6a4SAndroid Build Coastguard Worker         self.queue()?.kevent(&[], &mut event[..], None)?;
60*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
61*bb4ee6a4SAndroid Build Coastguard Worker     }
62*bb4ee6a4SAndroid Build Coastguard Worker 
mark_waited(&mut self) -> Result<bool>63*bb4ee6a4SAndroid Build Coastguard Worker     fn mark_waited(&mut self) -> Result<bool> {
64*bb4ee6a4SAndroid Build Coastguard Worker         // Timers cannot be tested without consuming the event
65*bb4ee6a4SAndroid Build Coastguard Worker         Ok(false)
66*bb4ee6a4SAndroid Build Coastguard Worker     }
67*bb4ee6a4SAndroid Build Coastguard Worker 
clear(&mut self) -> Result<()>68*bb4ee6a4SAndroid Build Coastguard Worker     fn clear(&mut self) -> Result<()> {
69*bb4ee6a4SAndroid Build Coastguard Worker         let delete = make_kevent(libc::EVFILT_TIMER, libc::EV_DELETE, 0);
70*bb4ee6a4SAndroid Build Coastguard Worker         self.queue()?.kevent(&[delete], &mut [], None)?;
71*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
resolution(&self) -> Result<Duration>74*bb4ee6a4SAndroid Build Coastguard Worker     fn resolution(&self) -> Result<Duration> {
75*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
76*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because we are zero-initializing a struct with only primitive member fields.
77*bb4ee6a4SAndroid Build Coastguard Worker         let mut res: libc::timespec = unsafe { mem::zeroed() };
78*bb4ee6a4SAndroid Build Coastguard Worker 
79*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
80*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because it only modifies a local struct and we check the return value.
81*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut res) };
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker         if ret != 0 {
84*bb4ee6a4SAndroid Build Coastguard Worker             return errno_result();
85*bb4ee6a4SAndroid Build Coastguard Worker         }
86*bb4ee6a4SAndroid Build Coastguard Worker 
87*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32))
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker }
90