1use libc::{c_int, c_void};
37use mio::event::Source;
38use mio::unix::SourceFd;
39use mio::{Interest, Registry, Token};
40use std::io;
41use std::mem::MaybeUninit;
42use std::os::unix::io::{AsRawFd, RawFd};
43use std::time::Duration;
44
45#[cfg(not(target_os = "linux"))]
46compile_error!("timerfd is a linux specific feature");
47
48pub struct TimerFd {
57 fd: c_int,
58}
59
60impl TimerFd {
61 pub fn new(clockid: ClockId) -> io::Result<Self> {
65 let flags = libc::TFD_NONBLOCK | libc::TFD_CLOEXEC;
66 Self::create(clockid.into(), flags)
67 }
68
69 pub fn set_timeout(&mut self, timeout: &Duration) -> io::Result<()> {
71 let new_value = libc::itimerspec {
74 it_interval: libc::timespec {
75 tv_sec: 0,
76 tv_nsec: 0,
77 },
78 it_value: libc::timespec {
79 tv_sec: timeout.as_secs() as libc::time_t,
80 tv_nsec: timeout.subsec_nanos() as libc::c_long,
81 },
82 };
83 self.settime(0, &new_value).map(|_old_value| ())
84 }
85
86 pub fn set_timeout_interval(&mut self, timeout: &Duration) -> io::Result<()> {
89 let new_value = libc::itimerspec {
91 it_interval: libc::timespec {
92 tv_sec: timeout.as_secs() as libc::time_t,
93 tv_nsec: timeout.subsec_nanos() as libc::c_long,
94 },
95 it_value: libc::timespec {
96 tv_sec: timeout.as_secs() as libc::time_t,
97 tv_nsec: timeout.subsec_nanos() as libc::c_long,
98 },
99 };
100 self.settime(0, &new_value).map(|_old_value| ())
101 }
102
103 pub fn disarm(&mut self) -> io::Result<()> {
106 self.set_timeout(&Duration::from_secs(0))
107 }
108
109 pub fn read(&self) -> io::Result<u64> {
119 let mut buf = [0u8; 8];
120 let ret = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
121 if ret == 8 {
122 Ok(u64::from_ne_bytes(buf))
123 } else if ret == -1 {
124 let errno = unsafe { *libc::__errno_location() };
125 if errno == libc::EAGAIN {
126 Ok(0)
127 } else {
128 Err(io::Error::from_raw_os_error(errno))
129 }
130 } else {
131 panic!("reading a timerfd should never yield {} bytes", ret);
132 }
133 }
134
135 pub fn create(clockid: c_int, flags: c_int) -> io::Result<Self> {
142 let fd = unsafe { libc::timerfd_create(clockid, flags) };
143 if fd == -1 {
144 Err(io::Error::last_os_error())
145 } else {
146 Ok(Self { fd })
147 }
148 }
149
150 pub fn settime(
154 &mut self,
155 flags: c_int,
156 new_value: &libc::itimerspec,
157 ) -> io::Result<libc::itimerspec> {
158 let mut old_spec_mem = MaybeUninit::<libc::itimerspec>::uninit();
159 let ret =
160 unsafe { libc::timerfd_settime(self.fd, flags, new_value, old_spec_mem.as_mut_ptr()) };
161 if ret == -1 {
162 Err(io::Error::last_os_error())
163 } else {
164 let old_spec = unsafe { old_spec_mem.assume_init() };
165 Ok(old_spec)
166 }
167 }
168
169 pub fn gettime(&self) -> io::Result<libc::itimerspec> {
171 let mut old_spec_mem = MaybeUninit::<libc::itimerspec>::uninit();
172 let ret = unsafe { libc::timerfd_gettime(self.fd, old_spec_mem.as_mut_ptr()) };
173 if ret == -1 {
174 Err(io::Error::last_os_error())
175 } else {
176 let old_spec = unsafe { old_spec_mem.assume_init() };
177 Ok(old_spec)
178 }
179 }
180}
181
182impl AsRawFd for TimerFd {
183 fn as_raw_fd(&self) -> RawFd {
184 self.fd
185 }
186}
187
188impl Source for TimerFd {
189 fn register(
190 &mut self,
191 registry: &Registry,
192 token: Token,
193 interest: Interest,
194 ) -> io::Result<()> {
195 SourceFd(&self.fd).register(registry, token, interest)
196 }
197
198 fn reregister(
199 &mut self,
200 registry: &Registry,
201 token: Token,
202 interest: Interest,
203 ) -> io::Result<()> {
204 SourceFd(&self.fd).reregister(registry, token, interest)
205 }
206
207 fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
208 SourceFd(&self.fd).deregister(registry)
209 }
210}
211
212impl Drop for TimerFd {
213 fn drop(&mut self) {
214 let _ = unsafe { libc::close(self.fd) };
215 }
216}
217
218#[derive(Copy, Clone)]
226pub enum ClockId {
227 RealTime,
228 Monotonic,
229 BootTime,
230 RealTimeAlarm,
231 BootTimeAlarm,
232}
233
234impl Into<c_int> for ClockId {
235 fn into(self) -> c_int {
236 match self {
237 ClockId::RealTime => libc::CLOCK_REALTIME,
238 ClockId::Monotonic => libc::CLOCK_MONOTONIC,
239 ClockId::BootTime => libc::CLOCK_BOOTTIME,
240 ClockId::RealTimeAlarm => libc::CLOCK_REALTIME_ALARM,
241 ClockId::BootTimeAlarm => libc::CLOCK_BOOTTIME_ALARM,
242 }
243 }
244}
245
246#[cfg(test)]
253mod test {
254 use super::*;
255 use mio::{Events, Poll};
256
257 const TOK: Token = Token(0);
258 const TIMEOUT: Duration = Duration::from_millis(60);
259
260 #[test]
261 fn single_timeout() {
262 let mut poll = Poll::new().unwrap();
263 let mut events = Events::with_capacity(1024);
264 let mut timer = TimerFd::new(ClockId::Monotonic).unwrap();
265 timer.set_timeout(&TIMEOUT).unwrap();
266 poll.registry()
267 .register(&mut timer, TOK, Interest::READABLE)
268 .unwrap();
269
270 poll.poll(&mut events, Some(TIMEOUT / 2)).unwrap();
272 assert!(events.is_empty());
273 assert!(timer.read().unwrap() == 0);
274
275 poll.poll(&mut events, Some(TIMEOUT)).unwrap();
277 assert!(!events.is_empty());
278 assert!(timer.read().unwrap() == 1);
279
280 poll.poll(&mut events, Some(TIMEOUT)).unwrap();
282 assert!(events.is_empty());
283 assert!(timer.read().unwrap() == 0);
284 }
285
286 #[test]
287 fn disarm_rearm_single_timeout() {
288 let mut poll = Poll::new().unwrap();
289 let mut events = Events::with_capacity(1024);
290 let mut timer = TimerFd::new(ClockId::Monotonic).unwrap();
291 timer.set_timeout(&TIMEOUT).unwrap();
292 poll.registry()
293 .register(&mut timer, TOK, Interest::READABLE)
294 .unwrap();
295
296 poll.poll(&mut events, Some(TIMEOUT / 2)).unwrap();
298 assert!(events.is_empty());
299 assert!(timer.read().unwrap() == 0);
300
301 timer.disarm().unwrap();
304 poll.poll(&mut events, Some(TIMEOUT)).unwrap();
305 assert!(events.is_empty());
306 assert!(timer.read().unwrap() == 0);
307
308 timer.set_timeout(&TIMEOUT).unwrap();
310 poll.poll(&mut events, Some(TIMEOUT * 2)).unwrap();
311 assert!(!events.is_empty());
312 assert!(timer.read().unwrap() == 1);
313 }
314
315 #[test]
316 fn timeout_interval() {
317 let mut poll = Poll::new().unwrap();
318 let mut events = Events::with_capacity(1024);
319 let mut timer = TimerFd::new(ClockId::Monotonic).unwrap();
320 timer.set_timeout_interval(&TIMEOUT).unwrap();
321 poll.registry()
322 .register(&mut timer, TOK, Interest::READABLE)
323 .unwrap();
324
325 poll.poll(&mut events, Some(TIMEOUT / 2)).unwrap();
327 assert!(events.is_empty());
328 assert!(timer.read().unwrap() == 0);
329
330 poll.poll(&mut events, Some(TIMEOUT)).unwrap();
332 assert!(!events.is_empty());
333 assert!(timer.read().unwrap() == 1);
334
335 poll.poll(&mut events, Some(TIMEOUT * 2)).unwrap();
337 assert!(!events.is_empty());
338 assert!(timer.read().unwrap() == 1);
339 }
340
341 #[test]
342 fn disarm_rearm_timeout_interval() {
343 let mut poll = Poll::new().unwrap();
344 let mut events = Events::with_capacity(1024);
345 let mut timer = TimerFd::new(ClockId::Monotonic).unwrap();
346 timer.set_timeout_interval(&TIMEOUT).unwrap();
347 poll.registry()
348 .register(&mut timer, TOK, Interest::READABLE)
349 .unwrap();
350
351 poll.poll(&mut events, Some(TIMEOUT / 2)).unwrap();
353 assert!(events.is_empty());
354 assert!(timer.read().unwrap() == 0);
355
356 timer.disarm().unwrap();
359 poll.poll(&mut events, Some(TIMEOUT)).unwrap();
360 assert!(events.is_empty());
361 assert!(timer.read().unwrap() == 0);
362
363 timer.set_timeout_interval(&TIMEOUT).unwrap();
365 poll.poll(&mut events, Some(TIMEOUT + (TIMEOUT / 2)))
366 .unwrap();
367 assert!(!events.is_empty());
368 assert!(timer.read().unwrap() == 1);
369
370 timer.set_timeout_interval(&TIMEOUT).unwrap();
372 poll.poll(&mut events, Some(TIMEOUT + (TIMEOUT / 2)))
373 .unwrap();
374 assert!(!events.is_empty());
375 assert!(timer.read().unwrap() == 1);
376 }
377
378 #[test]
379 fn deregister_and_drop() {
380 let mut poll = Poll::new().unwrap();
381 let mut events = Events::with_capacity(1024);
382
383 let mut timer_one = TimerFd::new(ClockId::Monotonic).unwrap();
384 timer_one.set_timeout(&Duration::from_millis(32)).unwrap();
385 poll.registry()
386 .register(&mut timer_one, Token(1), Interest::READABLE)
387 .unwrap();
388 let mut timer_two = TimerFd::new(ClockId::Monotonic).unwrap();
389 timer_two.set_timeout(&Duration::from_millis(64)).unwrap();
390 poll.registry()
391 .register(&mut timer_two, Token(2), Interest::READABLE)
392 .unwrap();
393
394 poll.poll(&mut events, Some(Duration::from_millis(5)))
397 .unwrap();
398 assert!(events.is_empty());
399 poll.registry().deregister(&mut timer_one).unwrap();
400 std::mem::drop(timer_one);
401
402 poll.poll(&mut events, Some(Duration::from_millis(500)))
403 .unwrap();
404 assert!(!events.is_empty());
405 for event in events.iter() {
406 match event.token() {
407 Token(1) => panic!(),
408 Token(2) => {}
409 _ => panic!(),
410 }
411 }
412 }
413
414 #[test]
415 fn multiple_timers() {
416 use std::time::Instant;
417
418 let deadline = Instant::now() + Duration::from_millis(330);
419 let mut count_one = 0;
420 let mut count_two = 0;
421 let mut count_three = 0;
422 let mut count_four = 0;
423
424 let mut poll = Poll::new().unwrap();
425 let mut events = Events::with_capacity(1024);
426
427 let mut timer_one = TimerFd::new(ClockId::Monotonic).unwrap();
429 timer_one.set_timeout(&Duration::from_millis(100)).unwrap();
430 poll.registry()
431 .register(&mut timer_one, Token(1), Interest::READABLE)
432 .unwrap();
433
434 let mut timer_two = TimerFd::new(ClockId::Monotonic).unwrap();
436 timer_two
437 .set_timeout_interval(&Duration::from_millis(100))
438 .unwrap();
439 poll.registry()
440 .register(&mut timer_two, Token(2), Interest::READABLE)
441 .unwrap();
442
443 let mut timer_three = TimerFd::new(ClockId::Monotonic).unwrap();
445 timer_three
446 .set_timeout(&Duration::from_millis(200))
447 .unwrap();
448 poll.registry()
449 .register(&mut timer_three, Token(3), Interest::READABLE)
450 .unwrap();
451
452 let mut timer_four = TimerFd::new(ClockId::Monotonic).unwrap();
454 timer_four
455 .set_timeout_interval(&Duration::from_millis(300))
456 .unwrap();
457 poll.registry()
458 .register(&mut timer_four, Token(4), Interest::READABLE)
459 .unwrap();
460
461 loop {
462 poll.poll(&mut events, Some(deadline - Instant::now()))
463 .unwrap();
464 if events.is_empty() {
465 break;
466 }
467 for event in events.iter() {
468 match event.token() {
469 Token(1) => {
470 let _ = timer_one.read();
471 count_one += 1;
472 if count_one == 1 {
473 assert!(count_two <= 1);
474 assert!(count_three == 0);
475 assert!(count_four == 0);
476 timer_one.set_timeout(&Duration::from_millis(150)).unwrap();
477 }
478 }
479 Token(2) => {
480 let _ = timer_two.read();
481 count_two += 1;
482 assert!(count_two == 1 || count_two == 2);
483 if count_two >= 2 {
485 timer_two.disarm().unwrap();
486 }
487 if count_two == 1 {
489 assert!(count_one <= 1);
490 assert!(count_three == 0);
491 assert!(count_four == 0);
492 } else if count_two == 2 {
493 assert!(count_one == 1);
494 assert!(count_three <= 1);
495 assert!(count_four == 0);
496 }
497 }
498 Token(3) => {
499 let _ = timer_three.read();
500 count_three += 1;
501 assert!(count_one == 1);
502 assert!(count_two == 1 || count_two == 2);
503 assert!(count_three == 1);
504 assert!(count_four == 0);
505 }
506 Token(4) => {
507 let _ = timer_four.read();
508 count_four += 1;
509 assert!(count_one == 2);
510 assert!(count_two == 2);
511 assert!(count_three == 1);
512 assert!(count_four == 1);
513 }
514 _ => unreachable!(),
515 }
516 }
517 }
518
519 assert!(count_one == 2);
520 assert!(count_two == 2);
521 assert!(count_three == 1);
522 assert!(count_four == 1);
523 }
524}