1use std::mem;
6use std::os::unix::io::AsRawFd;
7use std::os::unix::io::RawFd;
8use std::ptr;
9use std::time::Duration;
10
11use libc::clock_getres;
12use libc::timerfd_create;
13use libc::timerfd_settime;
14use libc::CLOCK_MONOTONIC;
15use libc::EAGAIN;
16use libc::POLLIN;
17use libc::TFD_CLOEXEC;
18use libc::TFD_NONBLOCK;
19
20use super::super::errno_result;
21use super::super::Error;
22use super::super::Result;
23use crate::descriptor::AsRawDescriptor;
24use crate::descriptor::FromRawDescriptor;
25use crate::descriptor::SafeDescriptor;
26use crate::handle_eintr_errno;
27use crate::timer::Timer;
28use crate::timer::TimerTrait;
29use crate::unix::duration_to_timespec;
30
31impl AsRawFd for Timer {
32 fn as_raw_fd(&self) -> RawFd {
33 self.handle.as_raw_descriptor()
34 }
35}
36
37impl Timer {
38 pub fn new() -> Result<Timer> {
41 let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK) };
44 if ret < 0 {
45 return errno_result();
46 }
47
48 Ok(Timer {
49 handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) },
52 interval: None,
53 })
54 }
55
56 fn set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()> {
58 self.interval = interval;
61
62 let spec = libc::itimerspec {
63 it_interval: duration_to_timespec(interval.unwrap_or_default()),
64 it_value: duration_to_timespec(dur.unwrap_or_default()),
65 };
66
67 let ret = unsafe { timerfd_settime(self.as_raw_descriptor(), 0, &spec, ptr::null_mut()) };
70 if ret < 0 {
71 return errno_result();
72 }
73
74 Ok(())
75 }
76}
77
78impl TimerTrait for Timer {
79 fn reset_oneshot(&mut self, dur: Duration) -> Result<()> {
80 self.set_time(Some(dur), None)
81 }
82
83 fn reset_repeating(&mut self, dur: Duration) -> Result<()> {
84 self.set_time(Some(dur), Some(dur))
85 }
86
87 fn clear(&mut self) -> Result<()> {
88 self.set_time(None, None)
89 }
90
91 fn wait(&mut self) -> Result<()> {
92 let mut pfd = libc::pollfd {
93 fd: self.as_raw_descriptor(),
94 events: POLLIN,
95 revents: 0,
96 };
97
98 let ret = handle_eintr_errno!(unsafe {
101 libc::ppoll(
102 &mut pfd as *mut libc::pollfd,
103 1,
104 ptr::null_mut(),
105 ptr::null_mut(),
106 )
107 });
108
109 if ret < 0 {
110 return errno_result();
111 }
112
113 let _ = self.mark_waited()?;
118
119 Ok(())
120 }
121
122 fn mark_waited(&mut self) -> Result<bool> {
123 let mut count = 0u64;
124
125 let ret = unsafe {
128 libc::read(
129 self.as_raw_descriptor(),
130 &mut count as *mut _ as *mut libc::c_void,
131 mem::size_of_val(&count),
132 )
133 };
134
135 if ret < 0 {
136 if Error::last().errno() == EAGAIN {
137 Ok(true)
138 } else {
139 errno_result()
140 }
141 } else {
142 Ok(false)
143 }
144 }
145
146 fn resolution(&self) -> Result<Duration> {
147 let mut res: libc::timespec = unsafe { mem::zeroed() };
150
151 let ret = unsafe { clock_getres(CLOCK_MONOTONIC, &mut res) };
154
155 if ret != 0 {
156 return errno_result();
157 }
158
159 Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32))
160 }
161}