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