1use 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")]
10use crate::unistd::Pid;
11use crate::{Errno, Result};
12use libc::{self, clockid_t};
13use std::mem::MaybeUninit;
14
15#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
20pub struct ClockId(clockid_t);
21
22impl ClockId {
23 pub const fn from_raw(clk_id: clockid_t) -> Self {
25 ClockId(clk_id)
26 }
27
28 feature! {
29 #![feature = "process"]
30 #[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 #[cfg(not(target_os = "redox"))]
46 #[cfg_attr(docsrs, doc(cfg(all())))]
47 pub fn res(self) -> Result<TimeSpec> {
48 clock_getres(self)
49 }
50
51 pub fn now(self) -> Result<TimeSpec> {
53 clock_gettime(self)
54 }
55
56 #[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())))]
64 pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
65 clock_settime(self, timespec)
66 }
67
68 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 = ClockId(libc::CLOCK_BOOTTIME_ALARM);
89 pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
90 #[cfg(any(
91 target_os = "android",
92 target_os = "emscripten",
93 target_os = "fuchsia",
94 target_os = "linux"
95 ))]
96 #[cfg_attr(docsrs, doc(cfg(all())))]
97 pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE);
98 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
99 #[cfg_attr(docsrs, doc(cfg(all())))]
100 pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST);
101 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
102 #[cfg_attr(docsrs, doc(cfg(all())))]
103 pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE);
104 #[cfg(any(
105 target_os = "android",
106 target_os = "emscripten",
107 target_os = "fuchsia",
108 target_os = "linux"
109 ))]
110 #[cfg_attr(docsrs, doc(cfg(all())))]
111 pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
112 #[cfg(any(
113 target_os = "android",
114 target_os = "emscripten",
115 target_os = "fuchsia",
116 target_os = "macos",
117 target_os = "ios",
118 target_os = "freebsd",
119 target_os = "dragonfly",
120 target_os = "redox",
121 target_os = "linux"
122 ))]
123 #[cfg_attr(docsrs, doc(cfg(all())))]
124 pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
125 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
126 #[cfg_attr(docsrs, doc(cfg(all())))]
127 pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
128 pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
129 #[cfg(any(
130 target_os = "android",
131 target_os = "emscripten",
132 target_os = "fuchsia",
133 target_os = "linux"
134 ))]
135 #[cfg_attr(docsrs, doc(cfg(all())))]
136 pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM);
137 #[cfg(any(
138 target_os = "android",
139 target_os = "emscripten",
140 target_os = "fuchsia",
141 target_os = "linux"
142 ))]
143 #[cfg_attr(docsrs, doc(cfg(all())))]
144 pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE);
145 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
146 #[cfg_attr(docsrs, doc(cfg(all())))]
147 pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
148 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
149 #[cfg_attr(docsrs, doc(cfg(all())))]
150 pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE);
151 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
152 #[cfg_attr(docsrs, doc(cfg(all())))]
153 pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
154 #[cfg(any(
155 target_os = "emscripten",
156 target_os = "fuchsia",
157 all(target_os = "linux", target_env = "musl")
158 ))]
159 #[cfg_attr(docsrs, doc(cfg(all())))]
160 pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
161 #[cfg(any(
162 target_os = "android",
163 target_os = "emscripten",
164 target_os = "fuchsia",
165 target_os = "linux"
166 ))]
167 #[cfg_attr(docsrs, doc(cfg(all())))]
168 pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
169 #[cfg(any(
170 target_os = "android",
171 target_os = "emscripten",
172 target_os = "fuchsia",
173 target_os = "ios",
174 target_os = "macos",
175 target_os = "freebsd",
176 target_os = "dragonfly",
177 target_os = "linux"
178 ))]
179 #[cfg_attr(docsrs, doc(cfg(all())))]
180 pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
181 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
182 #[cfg_attr(docsrs, doc(cfg(all())))]
183 pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
184 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
185 #[cfg_attr(docsrs, doc(cfg(all())))]
186 pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
187 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
188 #[cfg_attr(docsrs, doc(cfg(all())))]
189 pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE);
190 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
191 #[cfg_attr(docsrs, doc(cfg(all())))]
192 pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
193}
194
195impl From<ClockId> for clockid_t {
196 fn from(clock_id: ClockId) -> Self {
197 clock_id.as_raw()
198 }
199}
200
201impl From<clockid_t> for ClockId {
202 fn from(clk_id: clockid_t) -> Self {
203 ClockId::from_raw(clk_id)
204 }
205}
206
207impl std::fmt::Display for ClockId {
208 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
209 std::fmt::Display::fmt(&self.0, f)
210 }
211}
212
213#[cfg(not(target_os = "redox"))]
216#[cfg_attr(docsrs, doc(cfg(all())))]
217pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
218 let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
219 let ret = unsafe { libc::clock_getres(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
225pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
228 let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
229 let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
230 Errno::result(ret)?;
231 let res = unsafe { c_time.assume_init() };
232 Ok(TimeSpec::from(res))
233}
234
235#[cfg(not(any(
238 target_os = "macos",
239 target_os = "ios",
240 target_os = "redox",
241 target_os = "hermit",
242)))]
243#[cfg_attr(docsrs, doc(cfg(all())))]
244pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
245 let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
246 Errno::result(ret).map(drop)
247}
248
249#[cfg(any(
252 target_os = "freebsd",
253 target_os = "dragonfly",
254 target_os = "linux",
255 target_os = "android",
256 target_os = "emscripten",
257))]
258#[cfg(feature = "process")]
259#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
260pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
261 let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
262 let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
263 if ret == 0 {
264 let res = unsafe { clk_id.assume_init() };
265 Ok(ClockId::from(res))
266 } else {
267 Err(Errno::from_i32(ret))
268 }
269}