summary refs log tree commit diff
path: root/sys_util
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2018-09-07 22:36:55 +0000
committerchrome-bot <chrome-bot@chromium.org>2018-09-17 21:34:42 -0700
commit407c3151d81441f9ab4b64243b62b7692090a4a8 (patch)
treed86f2ae6c802774ddaa30910957b84df7ee229e6 /sys_util
parent32e17bc0b7ddd0cfa2ace015f38bce8375e43af2 (diff)
downloadcrosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar.gz
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar.bz2
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar.lz
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar.xz
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.tar.zst
crosvm-407c3151d81441f9ab4b64243b62b7692090a4a8.zip
sys_util: timerfd: Add ability to check if the timer is armed
This allows users to only arm timers if not already armed.

Signed-off-by: Dylan Reid <dgreid@chromium.org>
Change-Id: I8d7c6a7643a2ae2ce4b5679107bfd2be6e4adf3a
Reviewed-on: https://chromium-review.googlesource.com/1214442
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'sys_util')
-rw-r--r--sys_util/src/timerfd.rs19
1 files changed, 18 insertions, 1 deletions
diff --git a/sys_util/src/timerfd.rs b/sys_util/src/timerfd.rs
index 7d2c76a..6effd22 100644
--- a/sys_util/src/timerfd.rs
+++ b/sys_util/src/timerfd.rs
@@ -8,7 +8,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
 use std::ptr;
 use std::time::Duration;
 
-use libc::{self, CLOCK_MONOTONIC, TFD_CLOEXEC, timerfd_create, timerfd_settime};
+use libc::{self, CLOCK_MONOTONIC, TFD_CLOEXEC, timerfd_create, timerfd_gettime, timerfd_settime};
 
 use {Result, errno_result};
 
@@ -73,6 +73,20 @@ impl TimerFd {
         Ok(count)
     }
 
+    /// Returns `true` if the timer is currently armed.
+    pub fn is_armed(&self) -> Result<bool> {
+        // Safe because we are zero-initializing a struct with only primitive member fields.
+        let mut spec: libc::itimerspec = unsafe { mem::zeroed() };
+
+        // Safe because timerfd_gettime is trusted to only modify `spec`.
+        let ret = unsafe { timerfd_gettime(self.as_raw_fd(), &mut spec) };
+        if ret < 0 {
+            return errno_result();
+        }
+
+        Ok(spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0)
+    }
+
     /// Disarms the timer.
     pub fn clear(&mut self) -> Result<()> {
         // Safe because we are zero-initializing a struct with only primitive member fields.
@@ -115,11 +129,14 @@ mod tests {
     #[test]
     fn one_shot() {
         let mut tfd = TimerFd::new().expect("failed to create timerfd");
+        assert_eq!(tfd.is_armed().unwrap(), false);
 
         let dur = Duration::from_millis(200);
         let now = Instant::now();
         tfd.reset(dur.clone(), None).expect("failed to arm timer");
 
+        assert_eq!(tfd.is_armed().unwrap(), true);
+
         let count = tfd.wait().expect("unable to wait for timer");
 
         assert_eq!(count, 1);