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