// Copyright 2018 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. use std::mem; use std::os::unix::io::AsRawFd; use std::os::unix::io::RawFd; use std::ptr; use std::time::Duration; use libc::clock_getres; use libc::timerfd_create; use libc::timerfd_settime; use libc::CLOCK_MONOTONIC; use libc::EAGAIN; use libc::POLLIN; use libc::TFD_CLOEXEC; use libc::TFD_NONBLOCK; use super::super::errno_result; use super::super::Error; use super::super::Result; use crate::descriptor::AsRawDescriptor; use crate::descriptor::FromRawDescriptor; use crate::descriptor::SafeDescriptor; use crate::handle_eintr_errno; use crate::timer::Timer; use crate::timer::TimerTrait; use crate::unix::duration_to_timespec; impl AsRawFd for Timer { fn as_raw_fd(&self) -> RawFd { self.handle.as_raw_descriptor() } } impl Timer { /// Creates a new timerfd. The timer is initally disarmed and must be armed by calling /// `reset`. pub fn new() -> Result { // SAFETY: // Safe because this doesn't modify any memory and we check the return value. let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK) }; if ret < 0 { return errno_result(); } Ok(Timer { // SAFETY: // Safe because we uniquely own the file descriptor. handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) }, interval: None, }) } // Calls `timerfd_settime()` and stores the new value of `interval`. fn set_time(&mut self, dur: Option, interval: Option) -> Result<()> { // The posix implementation of timer does not need self.interval, but we // save it anyways to keep a consistent interface. self.interval = interval; let spec = libc::itimerspec { it_interval: duration_to_timespec(interval.unwrap_or_default()), it_value: duration_to_timespec(dur.unwrap_or_default()), }; // SAFETY: // Safe because this doesn't modify any memory and we check the return value. let ret = unsafe { timerfd_settime(self.as_raw_descriptor(), 0, &spec, ptr::null_mut()) }; if ret < 0 { return errno_result(); } Ok(()) } } impl TimerTrait for Timer { fn reset_oneshot(&mut self, dur: Duration) -> Result<()> { self.set_time(Some(dur), None) } fn reset_repeating(&mut self, dur: Duration) -> Result<()> { self.set_time(Some(dur), Some(dur)) } fn clear(&mut self) -> Result<()> { self.set_time(None, None) } fn wait(&mut self) -> Result<()> { let mut pfd = libc::pollfd { fd: self.as_raw_descriptor(), events: POLLIN, revents: 0, }; // SAFETY: // Safe because this only modifies |pfd| and we check the return value let ret = handle_eintr_errno!(unsafe { libc::ppoll( &mut pfd as *mut libc::pollfd, 1, ptr::null_mut(), ptr::null_mut(), ) }); if ret < 0 { return errno_result(); } // EAGAIN is a valid error in the case where another thread has called timerfd_settime // in between this thread calling ppoll and read. Since the ppoll returned originally // without any revents it means the timer did expire, so we treat this as a // WaitResult::Expired. let _ = self.mark_waited()?; Ok(()) } fn mark_waited(&mut self) -> Result { let mut count = 0u64; // The timerfd is in non-blocking mode, so this should return immediately. // SAFETY: We own the FD and provide a valid buffer we have exclusive access to. let ret = unsafe { libc::read( self.as_raw_descriptor(), &mut count as *mut _ as *mut libc::c_void, mem::size_of_val(&count), ) }; if ret < 0 { if Error::last().errno() == EAGAIN { Ok(true) } else { errno_result() } } else { Ok(false) } } fn resolution(&self) -> Result { // SAFETY: // Safe because we are zero-initializing a struct with only primitive member fields. let mut res: libc::timespec = unsafe { mem::zeroed() }; // SAFETY: // Safe because it only modifies a local struct and we check the return value. let ret = unsafe { clock_getres(CLOCK_MONOTONIC, &mut res) }; if ret != 0 { return errno_result(); } Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32)) } }