1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::mem; 6 use std::os::unix::io::AsRawFd; 7 use std::os::unix::io::RawFd; 8 use std::ptr; 9 use std::time::Duration; 10 11 use libc::clock_getres; 12 use libc::timerfd_create; 13 use libc::timerfd_settime; 14 use libc::CLOCK_MONOTONIC; 15 use libc::EAGAIN; 16 use libc::POLLIN; 17 use libc::TFD_CLOEXEC; 18 19 use super::super::errno_result; 20 use super::super::Error; 21 use super::super::Result; 22 use crate::descriptor::AsRawDescriptor; 23 use crate::descriptor::FromRawDescriptor; 24 use crate::descriptor::SafeDescriptor; 25 use crate::handle_eintr_errno; 26 use crate::timer::Timer; 27 use crate::timer::TimerTrait; 28 use crate::unix::duration_to_timespec; 29 30 impl AsRawFd for Timer { as_raw_fd(&self) -> RawFd31 fn as_raw_fd(&self) -> RawFd { 32 self.handle.as_raw_descriptor() 33 } 34 } 35 36 impl Timer { 37 /// Creates a new timerfd. The timer is initally disarmed and must be armed by calling 38 /// `reset`. new() -> Result<Timer>39 pub fn new() -> Result<Timer> { 40 // SAFETY: 41 // Safe because this doesn't modify any memory and we check the return value. 42 let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) }; 43 if ret < 0 { 44 return errno_result(); 45 } 46 47 Ok(Timer { 48 // SAFETY: 49 // Safe because we uniquely own the file descriptor. 50 handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) }, 51 interval: None, 52 }) 53 } 54 55 // Calls `timerfd_settime()` and stores the new value of `interval`. set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()>56 fn set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()> { 57 // The posix implementation of timer does not need self.interval, but we 58 // save it anyways to keep a consistent interface. 59 self.interval = interval; 60 61 let spec = libc::itimerspec { 62 it_interval: duration_to_timespec(interval.unwrap_or_default()), 63 it_value: duration_to_timespec(dur.unwrap_or_default()), 64 }; 65 66 // SAFETY: 67 // Safe because this doesn't modify any memory and we check the return value. 68 let ret = unsafe { timerfd_settime(self.as_raw_descriptor(), 0, &spec, ptr::null_mut()) }; 69 if ret < 0 { 70 return errno_result(); 71 } 72 73 Ok(()) 74 } 75 } 76 77 impl TimerTrait for Timer { reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()>78 fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> { 79 self.set_time(Some(dur), interval) 80 } 81 clear(&mut self) -> Result<()>82 fn clear(&mut self) -> Result<()> { 83 self.set_time(None, None) 84 } 85 wait(&mut self) -> Result<()>86 fn wait(&mut self) -> Result<()> { 87 let mut pfd = libc::pollfd { 88 fd: self.as_raw_descriptor(), 89 events: POLLIN, 90 revents: 0, 91 }; 92 93 // SAFETY: 94 // Safe because this only modifies |pfd| and we check the return value 95 let ret = handle_eintr_errno!(unsafe { 96 libc::ppoll( 97 &mut pfd as *mut libc::pollfd, 98 1, 99 ptr::null_mut(), 100 ptr::null_mut(), 101 ) 102 }); 103 104 if ret < 0 { 105 return errno_result(); 106 } 107 108 // EAGAIN is a valid error in the case where another thread has called timerfd_settime 109 // in between this thread calling ppoll and read. Since the ppoll returned originally 110 // without any revents it means the timer did expire, so we treat this as a 111 // WaitResult::Expired. 112 let _ = self.mark_waited()?; 113 114 Ok(()) 115 } 116 mark_waited(&mut self) -> Result<bool>117 fn mark_waited(&mut self) -> Result<bool> { 118 let mut count = 0u64; 119 120 // SAFETY: 121 // The timerfd is in non-blocking mode, so this should return immediately. 122 let ret = unsafe { 123 libc::read( 124 self.as_raw_descriptor(), 125 &mut count as *mut _ as *mut libc::c_void, 126 mem::size_of_val(&count), 127 ) 128 }; 129 130 if ret < 0 { 131 if Error::last().errno() == EAGAIN { 132 Ok(true) 133 } else { 134 errno_result() 135 } 136 } else { 137 Ok(false) 138 } 139 } 140 resolution(&self) -> Result<Duration>141 fn resolution(&self) -> Result<Duration> { 142 // SAFETY: 143 // Safe because we are zero-initializing a struct with only primitive member fields. 144 let mut res: libc::timespec = unsafe { mem::zeroed() }; 145 146 // SAFETY: 147 // Safe because it only modifies a local struct and we check the return value. 148 let ret = unsafe { clock_getres(CLOCK_MONOTONIC, &mut res) }; 149 150 if ret != 0 { 151 return errno_result(); 152 } 153 154 Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32)) 155 } 156 } 157