Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/base/src/sys/macos/timer.rs
5394 views
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 {
18
pub fn new() -> Result<Timer> {
19
Ok(Timer {
20
handle: SafeDescriptor::from(Kqueue::new()?),
21
interval: None,
22
})
23
}
24
25
fn queue(&self) -> Result<Kqueue> {
26
Ok(Kqueue::from(clone_descriptor(&self.handle)?))
27
}
28
}
29
30
impl crate::TimerTrait for Timer {
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
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
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
63
fn mark_waited(&mut self) -> Result<bool> {
64
// Timers cannot be tested without consuming the event
65
Ok(false)
66
}
67
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
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
91