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