• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::sys::time::TimeSpec;
2 #[cfg(any(
3     target_os = "freebsd",
4     target_os = "dragonfly",
5     target_os = "linux",
6     target_os = "android",
7     target_os = "emscripten",
8 ))]
9 #[cfg(feature = "process")]
10 use crate::unistd::Pid;
11 use crate::{Errno, Result};
12 use libc::{self, clockid_t};
13 use std::mem::MaybeUninit;
14 
15 /// Clock identifier
16 ///
17 /// Newtype pattern around `clockid_t` (which is just alias). It prevents bugs caused by
18 /// accidentally passing wrong value.
19 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
20 pub struct ClockId(clockid_t);
21 
22 impl ClockId {
23     /// Creates `ClockId` from raw `clockid_t`
from_raw(clk_id: clockid_t) -> Self24     pub const fn from_raw(clk_id: clockid_t) -> Self {
25         ClockId(clk_id)
26     }
27 
28     feature! {
29     #![feature = "process"]
30     /// Returns `ClockId` of a `pid` CPU-time clock
31     #[cfg(any(
32         target_os = "freebsd",
33         target_os = "dragonfly",
34         target_os = "linux",
35         target_os = "android",
36         target_os = "emscripten",
37     ))]
38     #[cfg_attr(docsrs, doc(cfg(all())))]
39     pub fn pid_cpu_clock_id(pid: Pid) -> Result<Self> {
40         clock_getcpuclockid(pid)
41     }
42     }
43 
44     /// Returns resolution of the clock id
45     #[cfg(not(target_os = "redox"))]
46     #[cfg_attr(docsrs, doc(cfg(all())))]
res(self) -> Result<TimeSpec>47     pub fn res(self) -> Result<TimeSpec> {
48         clock_getres(self)
49     }
50 
51     /// Returns the current time on the clock id
now(self) -> Result<TimeSpec>52     pub fn now(self) -> Result<TimeSpec> {
53         clock_gettime(self)
54     }
55 
56     /// Sets time to `timespec` on the clock id
57     #[cfg(not(any(
58         target_os = "macos",
59         target_os = "ios",
60         target_os = "redox",
61         target_os = "hermit",
62     )))]
63     #[cfg_attr(docsrs, doc(cfg(all())))]
set_time(self, timespec: TimeSpec) -> Result<()>64     pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
65         clock_settime(self, timespec)
66     }
67 
68     /// Gets the raw `clockid_t` wrapped by `self`
as_raw(self) -> clockid_t69     pub const fn as_raw(self) -> clockid_t {
70         self.0
71     }
72 
73     #[cfg(any(
74         target_os = "android",
75         target_os = "emscripten",
76         target_os = "fuchsia",
77         target_os = "linux"
78     ))]
79     #[cfg_attr(docsrs, doc(cfg(all())))]
80     pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME);
81     #[cfg(any(
82         target_os = "android",
83         target_os = "emscripten",
84         target_os = "fuchsia",
85         target_os = "linux"
86     ))]
87     #[cfg_attr(docsrs, doc(cfg(all())))]
88     pub const CLOCK_BOOTTIME_ALARM: ClockId =
89         ClockId(libc::CLOCK_BOOTTIME_ALARM);
90     pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
91     #[cfg(any(
92         target_os = "android",
93         target_os = "emscripten",
94         target_os = "fuchsia",
95         target_os = "linux"
96     ))]
97     #[cfg_attr(docsrs, doc(cfg(all())))]
98     pub const CLOCK_MONOTONIC_COARSE: ClockId =
99         ClockId(libc::CLOCK_MONOTONIC_COARSE);
100     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
101     #[cfg_attr(docsrs, doc(cfg(all())))]
102     pub const CLOCK_MONOTONIC_FAST: ClockId =
103         ClockId(libc::CLOCK_MONOTONIC_FAST);
104     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
105     #[cfg_attr(docsrs, doc(cfg(all())))]
106     pub const CLOCK_MONOTONIC_PRECISE: ClockId =
107         ClockId(libc::CLOCK_MONOTONIC_PRECISE);
108     #[cfg(any(
109         target_os = "android",
110         target_os = "emscripten",
111         target_os = "fuchsia",
112         target_os = "linux"
113     ))]
114     #[cfg_attr(docsrs, doc(cfg(all())))]
115     pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
116     #[cfg(any(
117         target_os = "android",
118         target_os = "emscripten",
119         target_os = "fuchsia",
120         target_os = "macos",
121         target_os = "ios",
122         target_os = "freebsd",
123         target_os = "dragonfly",
124         target_os = "redox",
125         target_os = "linux"
126     ))]
127     #[cfg_attr(docsrs, doc(cfg(all())))]
128     pub const CLOCK_PROCESS_CPUTIME_ID: ClockId =
129         ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
130     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
131     #[cfg_attr(docsrs, doc(cfg(all())))]
132     pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
133     pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
134     #[cfg(any(
135         target_os = "android",
136         target_os = "emscripten",
137         target_os = "fuchsia",
138         target_os = "linux"
139     ))]
140     #[cfg_attr(docsrs, doc(cfg(all())))]
141     pub const CLOCK_REALTIME_ALARM: ClockId =
142         ClockId(libc::CLOCK_REALTIME_ALARM);
143     #[cfg(any(
144         target_os = "android",
145         target_os = "emscripten",
146         target_os = "fuchsia",
147         target_os = "linux"
148     ))]
149     #[cfg_attr(docsrs, doc(cfg(all())))]
150     pub const CLOCK_REALTIME_COARSE: ClockId =
151         ClockId(libc::CLOCK_REALTIME_COARSE);
152     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
153     #[cfg_attr(docsrs, doc(cfg(all())))]
154     pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
155     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
156     #[cfg_attr(docsrs, doc(cfg(all())))]
157     pub const CLOCK_REALTIME_PRECISE: ClockId =
158         ClockId(libc::CLOCK_REALTIME_PRECISE);
159     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
160     #[cfg_attr(docsrs, doc(cfg(all())))]
161     pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
162     #[cfg(any(
163         target_os = "emscripten",
164         target_os = "fuchsia",
165         all(target_os = "linux", target_env = "musl")
166     ))]
167     #[cfg_attr(docsrs, doc(cfg(all())))]
168     pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
169     #[cfg(any(
170         target_os = "android",
171         target_os = "emscripten",
172         target_os = "fuchsia",
173         target_os = "linux"
174     ))]
175     #[cfg_attr(docsrs, doc(cfg(all())))]
176     pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
177     #[cfg(any(
178         target_os = "android",
179         target_os = "emscripten",
180         target_os = "fuchsia",
181         target_os = "ios",
182         target_os = "macos",
183         target_os = "freebsd",
184         target_os = "dragonfly",
185         target_os = "linux"
186     ))]
187     #[cfg_attr(docsrs, doc(cfg(all())))]
188     pub const CLOCK_THREAD_CPUTIME_ID: ClockId =
189         ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
190     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
191     #[cfg_attr(docsrs, doc(cfg(all())))]
192     pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
193     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
194     #[cfg_attr(docsrs, doc(cfg(all())))]
195     pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
196     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
197     #[cfg_attr(docsrs, doc(cfg(all())))]
198     pub const CLOCK_UPTIME_PRECISE: ClockId =
199         ClockId(libc::CLOCK_UPTIME_PRECISE);
200     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
201     #[cfg_attr(docsrs, doc(cfg(all())))]
202     pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
203 }
204 
205 impl From<ClockId> for clockid_t {
from(clock_id: ClockId) -> Self206     fn from(clock_id: ClockId) -> Self {
207         clock_id.as_raw()
208     }
209 }
210 
211 impl From<clockid_t> for ClockId {
from(clk_id: clockid_t) -> Self212     fn from(clk_id: clockid_t) -> Self {
213         ClockId::from_raw(clk_id)
214     }
215 }
216 
217 impl std::fmt::Display for ClockId {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result218     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
219         std::fmt::Display::fmt(&self.0, f)
220     }
221 }
222 
223 /// Get the resolution of the specified clock, (see
224 /// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)).
225 #[cfg(not(target_os = "redox"))]
226 #[cfg_attr(docsrs, doc(cfg(all())))]
clock_getres(clock_id: ClockId) -> Result<TimeSpec>227 pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
228     let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
229     let ret =
230         unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
231     Errno::result(ret)?;
232     let res = unsafe { c_time.assume_init() };
233     Ok(TimeSpec::from(res))
234 }
235 
236 /// Get the time of the specified clock, (see
237 /// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)).
clock_gettime(clock_id: ClockId) -> Result<TimeSpec>238 pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
239     let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
240     let ret =
241         unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
242     Errno::result(ret)?;
243     let res = unsafe { c_time.assume_init() };
244     Ok(TimeSpec::from(res))
245 }
246 
247 /// Set the time of the specified clock, (see
248 /// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)).
249 #[cfg(not(any(
250     target_os = "macos",
251     target_os = "ios",
252     target_os = "redox",
253     target_os = "hermit",
254 )))]
255 #[cfg_attr(docsrs, doc(cfg(all())))]
clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()>256 pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
257     let ret =
258         unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
259     Errno::result(ret).map(drop)
260 }
261 
262 /// Get the clock id of the specified process id, (see
263 /// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)).
264 #[cfg(any(
265     target_os = "freebsd",
266     target_os = "dragonfly",
267     target_os = "linux",
268     target_os = "android",
269     target_os = "emscripten",
270 ))]
271 #[cfg(feature = "process")]
272 #[cfg_attr(docsrs, doc(cfg(feature = "process")))]
clock_getcpuclockid(pid: Pid) -> Result<ClockId>273 pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
274     let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
275     let ret =
276         unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
277     if ret == 0 {
278         let res = unsafe { clk_id.assume_init() };
279         Ok(ClockId::from(res))
280     } else {
281         Err(Errno::from_i32(ret))
282     }
283 }
284