1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
// 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<Timer> {
// 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<Duration>, interval: Option<Duration>) -> 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<bool> {
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<Duration> {
// 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))
}
}