1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::mem;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::ptr;
use std::time::Duration;

use libc::clock_getres;
use libc::timerfd_create;
use libc::timerfd_settime;
use libc::CLOCK_MONOTONIC;
use libc::EAGAIN;
use libc::POLLIN;
use libc::TFD_CLOEXEC;

use super::super::errno_result;
use super::super::Error;
use super::super::Result;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::FromRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::handle_eintr_errno;
use crate::timer::Timer;
use crate::timer::TimerTrait;
use crate::unix::duration_to_timespec;

impl AsRawFd for Timer {
    fn as_raw_fd(&self) -> RawFd {
        self.handle.as_raw_descriptor()
    }
}

impl Timer {
    /// Creates a new timerfd.  The timer is initally disarmed and must be armed by calling
    /// `reset`.
    pub fn new() -> Result<Timer> {
        // SAFETY:
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) };
        if ret < 0 {
            return errno_result();
        }

        Ok(Timer {
            // SAFETY:
            // Safe because we uniquely own the file descriptor.
            handle: unsafe { SafeDescriptor::from_raw_descriptor(ret) },
            interval: None,
        })
    }

    // Calls `timerfd_settime()` and stores the new value of `interval`.
    fn set_time(&mut self, dur: Option<Duration>, interval: Option<Duration>) -> Result<()> {
        // The posix implementation of timer does not need self.interval, but we
        // save it anyways to keep a consistent interface.
        self.interval = interval;

        let spec = libc::itimerspec {
            it_interval: duration_to_timespec(interval.unwrap_or_default()),
            it_value: duration_to_timespec(dur.unwrap_or_default()),
        };

        // SAFETY:
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_settime(self.as_raw_descriptor(), 0, &spec, ptr::null_mut()) };
        if ret < 0 {
            return errno_result();
        }

        Ok(())
    }
}

impl TimerTrait for Timer {
    fn reset_oneshot(&mut self, dur: Duration) -> Result<()> {
        self.set_time(Some(dur), None)
    }

    fn reset_repeating(&mut self, dur: Duration) -> Result<()> {
        self.set_time(Some(dur), Some(dur))
    }

    fn clear(&mut self) -> Result<()> {
        self.set_time(None, None)
    }

    fn wait(&mut self) -> Result<()> {
        let mut pfd = libc::pollfd {
            fd: self.as_raw_descriptor(),
            events: POLLIN,
            revents: 0,
        };

        // SAFETY:
        // Safe because this only modifies |pfd| and we check the return value
        let ret = handle_eintr_errno!(unsafe {
            libc::ppoll(
                &mut pfd as *mut libc::pollfd,
                1,
                ptr::null_mut(),
                ptr::null_mut(),
            )
        });

        if ret < 0 {
            return errno_result();
        }

        // EAGAIN is a valid error in the case where another thread has called timerfd_settime
        // in between this thread calling ppoll and read. Since the ppoll returned originally
        // without any revents it means the timer did expire, so we treat this as a
        // WaitResult::Expired.
        let _ = self.mark_waited()?;

        Ok(())
    }

    fn mark_waited(&mut self) -> Result<bool> {
        let mut count = 0u64;

        // SAFETY:
        // The timerfd is in non-blocking mode, so this should return immediately.
        let ret = unsafe {
            libc::read(
                self.as_raw_descriptor(),
                &mut count as *mut _ as *mut libc::c_void,
                mem::size_of_val(&count),
            )
        };

        if ret < 0 {
            if Error::last().errno() == EAGAIN {
                Ok(true)
            } else {
                errno_result()
            }
        } else {
            Ok(false)
        }
    }

    fn resolution(&self) -> Result<Duration> {
        // SAFETY:
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let mut res: libc::timespec = unsafe { mem::zeroed() };

        // SAFETY:
        // Safe because it only modifies a local struct and we check the return value.
        let ret = unsafe { clock_getres(CLOCK_MONOTONIC, &mut res) };

        if ret != 0 {
            return errno_result();
        }

        Ok(Duration::new(res.tv_sec as u64, res.tv_nsec as u32))
    }
}