1 // Copyright 2019 Intel Corporation. All Rights Reserved. 2 // 3 // Copyright 2018 The Chromium OS Authors. All rights reserved. 4 // 5 // SPDX-License-Identifier: BSD-3-Clause 6 7 //! Structure and functions for working with 8 //! [`timerfd`](http://man7.org/linux/man-pages/man2/timerfd_create.2.html). 9 10 use std::fs::File; 11 use std::mem; 12 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 13 use std::ptr; 14 use std::time::Duration; 15 16 use libc::{self, timerfd_create, timerfd_gettime, timerfd_settime, CLOCK_MONOTONIC, TFD_CLOEXEC}; 17 18 use crate::errno::{errno_result, Result}; 19 20 /// A safe wrapper around a Linux 21 /// [`timerfd`](http://man7.org/linux/man-pages/man2/timerfd_create.2.html). 22 #[derive(Debug)] 23 pub struct TimerFd(File); 24 25 impl TimerFd { 26 /// Create a new [`TimerFd`](struct.TimerFd.html). 27 /// 28 /// This creates a nonsettable monotonically increasing clock that does not 29 /// change after system startup. The timer is initally disarmed and must be 30 /// armed by calling [`reset`](fn.reset.html). new() -> Result<TimerFd>31 pub fn new() -> Result<TimerFd> { 32 // SAFETY: Safe because this doesn't modify any memory and we check the return value. 33 let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) }; 34 if ret < 0 { 35 return errno_result(); 36 } 37 38 // SAFETY: Safe because we uniquely own the file descriptor. 39 Ok(TimerFd(unsafe { File::from_raw_fd(ret) })) 40 } 41 42 /// Arm the [`TimerFd`](struct.TimerFd.html). 43 /// 44 /// Set the timer to expire after `dur`. 45 /// 46 /// # Arguments 47 /// 48 /// * `dur`: Specify the initial expiration of the timer. 49 /// * `interval`: Specify the period for repeated expirations, depending on the 50 /// value passed. If `interval` is not `None`, it represents the period after 51 /// the initial expiration. Otherwise the timer will expire just once. Cancels 52 /// any existing duration and repeating interval. 53 /// 54 /// # Examples 55 /// 56 /// ``` 57 /// extern crate vmm_sys_util; 58 /// # use std::time::Duration; 59 /// use vmm_sys_util::timerfd::TimerFd; 60 /// 61 /// let mut timer = TimerFd::new().unwrap(); 62 /// let dur = Duration::from_millis(100); 63 /// let interval = Duration::from_millis(100); 64 /// 65 /// timer.reset(dur, Some(interval)).unwrap(); 66 /// ``` reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()>67 pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> { 68 // SAFETY: Safe because we are zero-initializing a struct with only primitive member fields. 69 let mut spec: libc::itimerspec = unsafe { mem::zeroed() }; 70 // https://github.com/rust-lang/libc/issues/1848 71 #[cfg_attr(target_env = "musl", allow(deprecated))] 72 { 73 spec.it_value.tv_sec = dur.as_secs() as libc::time_t; 74 } 75 // nsec always fits in i32 because subsec_nanos is defined to be less than one billion. 76 let nsec = dur.subsec_nanos() as i32; 77 spec.it_value.tv_nsec = libc::c_long::from(nsec); 78 79 if let Some(int) = interval { 80 // https://github.com/rust-lang/libc/issues/1848 81 #[cfg_attr(target_env = "musl", allow(deprecated))] 82 { 83 spec.it_interval.tv_sec = int.as_secs() as libc::time_t; 84 } 85 // nsec always fits in i32 because subsec_nanos is defined to be less than one billion. 86 let nsec = int.subsec_nanos() as i32; 87 spec.it_interval.tv_nsec = libc::c_long::from(nsec); 88 } 89 90 // SAFETY: Safe because this doesn't modify any memory and we check the return value. 91 let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) }; 92 if ret < 0 { 93 return errno_result(); 94 } 95 96 Ok(()) 97 } 98 99 /// Wait until the timer expires. 100 /// 101 /// The return value represents the number of times the timer has expired since 102 /// the last time `wait` was called. If the timer has not yet expired once, 103 /// this call will block until it does. 104 /// 105 /// # Examples 106 /// 107 /// ``` 108 /// extern crate vmm_sys_util; 109 /// # use std::time::Duration; 110 /// # use std::thread::sleep; 111 /// use vmm_sys_util::timerfd::TimerFd; 112 /// 113 /// let mut timer = TimerFd::new().unwrap(); 114 /// let dur = Duration::from_millis(100); 115 /// let interval = Duration::from_millis(100); 116 /// timer.reset(dur, Some(interval)).unwrap(); 117 /// 118 /// sleep(dur * 3); 119 /// let count = timer.wait().unwrap(); 120 /// assert!(count >= 3); 121 /// ``` wait(&mut self) -> Result<u64>122 pub fn wait(&mut self) -> Result<u64> { 123 let mut count = 0u64; 124 125 // SAFETY: Safe because this will only modify |buf| and we check the return value. 126 let ret = unsafe { 127 libc::read( 128 self.as_raw_fd(), 129 &mut count as *mut _ as *mut libc::c_void, 130 mem::size_of_val(&count), 131 ) 132 }; 133 if ret < 0 { 134 return errno_result(); 135 } 136 137 // The bytes in the buffer are guaranteed to be in native byte-order so we don't need to 138 // use from_le or from_be. 139 Ok(count) 140 } 141 142 /// Tell if the timer is armed. 143 /// 144 /// Returns `Ok(true)` if the timer is currently armed, otherwise the errno set by 145 /// [`timerfd_gettime`](http://man7.org/linux/man-pages/man2/timerfd_create.2.html). 146 /// 147 /// # Examples 148 /// 149 /// ``` 150 /// extern crate vmm_sys_util; 151 /// # use std::time::Duration; 152 /// use vmm_sys_util::timerfd::TimerFd; 153 /// 154 /// let mut timer = TimerFd::new().unwrap(); 155 /// let dur = Duration::from_millis(100); 156 /// 157 /// timer.reset(dur, None).unwrap(); 158 /// assert!(timer.is_armed().unwrap()); 159 /// ``` is_armed(&self) -> Result<bool>160 pub fn is_armed(&self) -> Result<bool> { 161 // SAFETY: Safe because we are zero-initializing a struct with only primitive member fields. 162 let mut spec: libc::itimerspec = unsafe { mem::zeroed() }; 163 164 // SAFETY: Safe because timerfd_gettime is trusted to only modify `spec`. 165 let ret = unsafe { timerfd_gettime(self.as_raw_fd(), &mut spec) }; 166 if ret < 0 { 167 return errno_result(); 168 } 169 170 Ok(spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0) 171 } 172 173 /// Disarm the timer. 174 /// 175 /// Set zero to disarm the timer, referring to 176 /// [`timerfd_settime`](http://man7.org/linux/man-pages/man2/timerfd_create.2.html). 177 /// 178 /// # Examples 179 /// 180 /// ``` 181 /// extern crate vmm_sys_util; 182 /// # use std::time::Duration; 183 /// use vmm_sys_util::timerfd::TimerFd; 184 /// 185 /// let mut timer = TimerFd::new().unwrap(); 186 /// let dur = Duration::from_millis(100); 187 /// 188 /// timer.reset(dur, None).unwrap(); 189 /// timer.clear().unwrap(); 190 /// ``` clear(&mut self) -> Result<()>191 pub fn clear(&mut self) -> Result<()> { 192 // SAFETY: Safe because we are zero-initializing a struct with only primitive member fields. 193 let spec: libc::itimerspec = unsafe { mem::zeroed() }; 194 195 // SAFETY: Safe because this doesn't modify any memory and we check the return value. 196 let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) }; 197 if ret < 0 { 198 return errno_result(); 199 } 200 201 Ok(()) 202 } 203 } 204 205 impl AsRawFd for TimerFd { as_raw_fd(&self) -> RawFd206 fn as_raw_fd(&self) -> RawFd { 207 self.0.as_raw_fd() 208 } 209 } 210 211 impl FromRawFd for TimerFd { 212 /// This function is unsafe as the primitives currently returned 213 /// have the contract that they are the sole owner of the file 214 /// descriptor they are wrapping. Usage of this function could 215 /// accidentally allow violating this contract which can cause memory 216 /// unsafety in code that relies on it being true. from_raw_fd(fd: RawFd) -> Self217 unsafe fn from_raw_fd(fd: RawFd) -> Self { 218 TimerFd(File::from_raw_fd(fd)) 219 } 220 } 221 222 impl IntoRawFd for TimerFd { into_raw_fd(self) -> RawFd223 fn into_raw_fd(self) -> RawFd { 224 self.0.into_raw_fd() 225 } 226 } 227 228 #[cfg(test)] 229 mod tests { 230 #![allow(clippy::undocumented_unsafe_blocks)] 231 use super::*; 232 use std::thread::sleep; 233 use std::time::{Duration, Instant}; 234 235 #[test] test_from_raw_fd()236 fn test_from_raw_fd() { 237 let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) }; 238 let tfd = unsafe { TimerFd::from_raw_fd(ret) }; 239 assert!(!tfd.is_armed().unwrap()); 240 } 241 242 #[test] test_into_raw_fd()243 fn test_into_raw_fd() { 244 let tfd = TimerFd::new().expect("failed to create timerfd"); 245 let fd = tfd.into_raw_fd(); 246 assert!(fd > 0); 247 } 248 #[test] test_one_shot()249 fn test_one_shot() { 250 let mut tfd = TimerFd::new().expect("failed to create timerfd"); 251 assert!(!tfd.is_armed().unwrap()); 252 253 let dur = Duration::from_millis(200); 254 let now = Instant::now(); 255 tfd.reset(dur, None).expect("failed to arm timer"); 256 257 assert!(tfd.is_armed().unwrap()); 258 259 let count = tfd.wait().expect("unable to wait for timer"); 260 261 assert_eq!(count, 1); 262 assert!(now.elapsed() >= dur); 263 tfd.clear().expect("unable to clear the timer"); 264 assert!(!tfd.is_armed().unwrap()); 265 } 266 267 #[test] test_repeating()268 fn test_repeating() { 269 let mut tfd = TimerFd::new().expect("failed to create timerfd"); 270 271 let dur = Duration::from_millis(200); 272 let interval = Duration::from_millis(100); 273 tfd.reset(dur, Some(interval)).expect("failed to arm timer"); 274 275 sleep(dur * 3); 276 277 let count = tfd.wait().expect("unable to wait for timer"); 278 assert!(count >= 5, "count = {}", count); 279 tfd.clear().expect("unable to clear the timer"); 280 assert!(!tfd.is_armed().unwrap()); 281 } 282 } 283