summaryrefslogtreecommitdiff
path: root/src/sys/timerfd.rs
diff options
context:
space:
mode:
authorBrian L. Troutwine <brian@troutwine.us>2021-12-27 15:37:30 -0800
committerBrian L. Troutwine <brian@troutwine.us>2021-12-30 20:40:48 -0800
commit77febe0e6b4e144992ea1b26ae1b9b45b746d970 (patch)
tree59e1a4ace5a4c9df7f4d110bac4595298f68ad6e /src/sys/timerfd.rs
parentb9eb19778a58603aae232bc838a8b8d8afd87c56 (diff)
downloadnix-77febe0e6b4e144992ea1b26ae1b9b45b746d970.zip
Introduce timer_* support
This commit adds support for the signal timer mechanism in POSIX, the mirror to timerfd on Linux. Resolves #1424 Signed-off-by: Brian L. Troutwine <brian@troutwine.us>
Diffstat (limited to 'src/sys/timerfd.rs')
-rw-r--r--src/sys/timerfd.rs111
1 files changed, 10 insertions, 101 deletions
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index 705a3c4d..bc5a75d4 100644
--- a/src/sys/timerfd.rs
+++ b/src/sys/timerfd.rs
@@ -28,10 +28,10 @@
//! // We wait for the timer to expire.
//! timer.wait().unwrap();
//! ```
-use crate::sys::time::TimeSpec;
+use crate::sys::time::timer::TimerSpec;
+pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
use crate::unistd::read;
use crate::{errno::Errno, Result};
-use bitflags::bitflags;
use libc::c_int;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
@@ -77,93 +77,6 @@ libc_bitflags! {
}
}
-bitflags! {
- /// Flags that are used for arming the timer.
- pub struct TimerSetTimeFlags: libc::c_int {
- const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-struct TimerSpec(libc::itimerspec);
-
-impl TimerSpec {
- pub const fn none() -> Self {
- Self(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- })
- }
-}
-
-impl AsRef<libc::itimerspec> for TimerSpec {
- fn as_ref(&self) -> &libc::itimerspec {
- &self.0
- }
-}
-
-impl From<Expiration> for TimerSpec {
- fn from(expiration: Expiration) -> TimerSpec {
- match expiration {
- Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
- it_interval: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: *t.as_ref(),
- }),
- Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec {
- it_interval: *interval.as_ref(),
- it_value: *start.as_ref(),
- }),
- Expiration::Interval(t) => TimerSpec(libc::itimerspec {
- it_interval: *t.as_ref(),
- it_value: *t.as_ref(),
- }),
- }
- }
-}
-
-impl From<TimerSpec> for Expiration {
- fn from(timerspec: TimerSpec) -> Expiration {
- match timerspec {
- TimerSpec(libc::itimerspec {
- it_interval:
- libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- it_value: ts,
- }) => Expiration::OneShot(ts.into()),
- TimerSpec(libc::itimerspec {
- it_interval: int_ts,
- it_value: val_ts,
- }) => {
- if (int_ts.tv_sec == val_ts.tv_sec) && (int_ts.tv_nsec == val_ts.tv_nsec) {
- Expiration::Interval(int_ts.into())
- } else {
- Expiration::IntervalDelayed(val_ts.into(), int_ts.into())
- }
- }
- }
- }
-}
-
-/// An enumeration allowing the definition of the expiration time of an alarm,
-/// recurring or not.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Expiration {
- OneShot(TimeSpec),
- IntervalDelayed(TimeSpec, TimeSpec),
- Interval(TimeSpec),
-}
-
impl TimerFd {
/// Creates a new timer based on the clock defined by `clockid`. The
/// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
@@ -181,7 +94,7 @@ impl TimerFd {
///
/// - one shot: the alarm will trigger once after the specified amount of
/// time.
- /// Example: I want an alarm to go off in 60s and then disables itself.
+ /// Example: I want an alarm to go off in 60s and then disable itself.
///
/// - interval: the alarm will trigger every specified interval of time.
/// Example: I want an alarm to go off every 60s. The alarm will first
@@ -225,13 +138,11 @@ impl TimerFd {
/// Get the parameters for the alarm currently set, if any.
pub fn get(&self) -> Result<Option<Expiration>> {
let mut timerspec = TimerSpec::none();
- let timerspec_ptr: *mut libc::itimerspec = &mut timerspec.0;
-
- Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec_ptr) }).map(|_| {
- if timerspec.0.it_interval.tv_sec == 0
- && timerspec.0.it_interval.tv_nsec == 0
- && timerspec.0.it_value.tv_sec == 0
- && timerspec.0.it_value.tv_nsec == 0
+ Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec.as_mut()) }).map(|_| {
+ if timerspec.as_ref().it_interval.tv_sec == 0
+ && timerspec.as_ref().it_interval.tv_nsec == 0
+ && timerspec.as_ref().it_value.tv_sec == 0
+ && timerspec.as_ref().it_value.tv_nsec == 0
{
None
} else {
@@ -259,7 +170,7 @@ impl TimerFd {
pub fn wait(&self) -> Result<()> {
while let Err(e) = read(self.fd, &mut [0u8; 8]) {
if e != Errno::EINTR {
- return Err(e)
+ return Err(e);
}
}
@@ -270,9 +181,7 @@ impl TimerFd {
impl Drop for TimerFd {
fn drop(&mut self) {
if !std::thread::panicking() {
- let result = Errno::result(unsafe {
- libc::close(self.fd)
- });
+ let result = Errno::result(unsafe { libc::close(self.fd) });
if let Err(Errno::EBADF) = result {
panic!("close of TimerFd encountered EBADF");
}