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