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