Skip to content

Commit eb774c1

Browse files
authored
Add more clocks to ClockId under linux_4_11 (#911)
* Add more clocks to `ClockId` under `linux_4_11` Add several more clocks to `ClockId` for use with the infallible `clock_gettiem` when the `linux_4_11` feature is enabled. * Don't test `test_boottime_alarm_clock` on platforms that don't have it.
1 parent bc4fa30 commit eb774c1

File tree

4 files changed

+178
-1
lines changed

4 files changed

+178
-1
lines changed

src/backend/linux_raw/c.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,14 @@ pub(crate) const CLOCK_THREAD_CPUTIME_ID: c_int =
266266
linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID as _;
267267
pub(crate) const CLOCK_PROCESS_CPUTIME_ID: c_int =
268268
linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID as _;
269+
#[cfg(all(feature = "time", feature = "linux_4_11"))]
270+
pub(crate) const CLOCK_BOOTTIME: c_int = linux_raw_sys::general::CLOCK_BOOTTIME as _;
271+
#[cfg(all(feature = "time", feature = "linux_4_11"))]
272+
pub(crate) const CLOCK_BOOTTIME_ALARM: c_int = linux_raw_sys::general::CLOCK_BOOTTIME_ALARM as _;
273+
#[cfg(all(feature = "time", feature = "linux_4_11"))]
274+
pub(crate) const CLOCK_TAI: c_int = linux_raw_sys::general::CLOCK_TAI as _;
275+
#[cfg(all(feature = "time", feature = "linux_4_11"))]
276+
pub(crate) const CLOCK_REALTIME_ALARM: c_int = linux_raw_sys::general::CLOCK_REALTIME_ALARM as _;
269277

270278
#[cfg(feature = "system")]
271279
mod reboot_symbols {

src/backend/linux_raw/fs/syscalls.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
use crate::backend::c;
1010
use crate::backend::conv::fs::oflags_for_open_how;
11+
#[cfg(not(feature = "linux_4_11"))]
12+
use crate::backend::conv::zero;
1113
use crate::backend::conv::{
1214
by_ref, c_int, c_uint, dev_t, opt_mut, pass_usize, raw_fd, ret, ret_c_int, ret_c_uint,
13-
ret_infallible, ret_owned_fd, ret_usize, size_of, slice, slice_mut, zero,
15+
ret_infallible, ret_owned_fd, ret_usize, size_of, slice, slice_mut,
1416
};
1517
#[cfg(target_pointer_width = "64")]
1618
use crate::backend::conv::{loff_t, loff_t_from_u64, ret_u64};
@@ -839,6 +841,7 @@ pub(crate) fn statx(
839841
}
840842
}
841843

844+
#[cfg(not(feature = "linux_4_11"))]
842845
#[inline]
843846
pub(crate) fn is_statx_available() -> bool {
844847
unsafe {

src/clockid.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,33 @@ pub enum ClockId {
5454
/// `CLOCK_MONOTONIC_RAW`
5555
#[cfg(linux_kernel)]
5656
MonotonicRaw = c::CLOCK_MONOTONIC_RAW,
57+
58+
/// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0
59+
#[cfg(all(linux_kernel, feature = "linux_4_11"))]
60+
#[doc(alias = "CLOCK_REALTIME_ALARM")]
61+
RealtimeAlarm = bitcast!(c::CLOCK_REALTIME_ALARM),
62+
63+
/// `CLOCK_TAI`, available on Linux >= 3.10
64+
#[cfg(all(linux_kernel, feature = "linux_4_11"))]
65+
#[doc(alias = "CLOCK_TAI")]
66+
Tai = bitcast!(c::CLOCK_TAI),
67+
68+
/// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39
69+
///
70+
/// On FreeBSD, use [`Self::Uptime`], as `CLOCK_BOOTTIME` is an alias for
71+
/// `CLOCK_UPTIME`.
72+
#[cfg(any(
73+
all(linux_kernel, feature = "linux_4_11"),
74+
target_os = "fuchsia",
75+
target_os = "openbsd"
76+
))]
77+
#[doc(alias = "CLOCK_BOOTTIME")]
78+
Boottime = bitcast!(c::CLOCK_BOOTTIME),
79+
80+
/// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39
81+
#[cfg(any(all(linux_kernel, feature = "linux_4_11"), target_os = "fuchsia"))]
82+
#[doc(alias = "CLOCK_BOOTTIME_ALARM")]
83+
BoottimeAlarm = bitcast!(c::CLOCK_BOOTTIME_ALARM),
5784
}
5885

5986
/// `CLOCK_*` constants for use with [`clock_gettime`].

tests/time/clocks.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use rustix::time::{clock_gettime, ClockId};
1717
fn test_boottime_clock() {
1818
use rustix::time::{clock_gettime_dynamic, DynamicClockId};
1919

20+
let monotonic = clock_gettime(ClockId::Monotonic);
21+
2022
if let Ok(a) = clock_gettime_dynamic(DynamicClockId::Boottime) {
2123
if let Ok(b) = clock_gettime_dynamic(DynamicClockId::Boottime) {
2224
if b.tv_sec == a.tv_sec {
@@ -25,6 +27,78 @@ fn test_boottime_clock() {
2527
assert!(b.tv_sec > a.tv_sec);
2628
}
2729
}
30+
31+
// Test that boot time is after monotonic.
32+
if a.tv_sec == monotonic.tv_sec {
33+
assert!(a.tv_nsec >= monotonic.tv_nsec);
34+
} else {
35+
assert!(a.tv_sec > monotonic.tv_sec);
36+
}
37+
}
38+
39+
#[cfg(feature = "linux_4_11")]
40+
{
41+
let a = clock_gettime(ClockId::Boottime);
42+
let b = clock_gettime(ClockId::Boottime);
43+
44+
if b.tv_sec == a.tv_sec {
45+
assert!(b.tv_nsec >= a.tv_nsec);
46+
} else {
47+
assert!(b.tv_sec > a.tv_sec);
48+
}
49+
50+
// Test that boot time is after monotonic.
51+
if a.tv_sec == monotonic.tv_sec {
52+
assert!(a.tv_nsec >= monotonic.tv_nsec);
53+
} else {
54+
assert!(a.tv_sec > monotonic.tv_sec);
55+
}
56+
}
57+
}
58+
59+
/// Attempt to test that the boot alarm clock is monotonic. Time may or may not
60+
/// advance, but it shouldn't regress.
61+
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
62+
#[test]
63+
fn test_boottime_alarm_clock() {
64+
use rustix::time::{clock_gettime_dynamic, DynamicClockId};
65+
66+
let monotonic = clock_gettime(ClockId::Monotonic);
67+
68+
if let Ok(a) = clock_gettime_dynamic(DynamicClockId::BoottimeAlarm) {
69+
if let Ok(b) = clock_gettime_dynamic(DynamicClockId::BoottimeAlarm) {
70+
if b.tv_sec == a.tv_sec {
71+
assert!(b.tv_nsec >= a.tv_nsec);
72+
} else {
73+
assert!(b.tv_sec > a.tv_sec);
74+
}
75+
}
76+
77+
// Test that boot alarm time is after monotonic.
78+
if a.tv_sec == monotonic.tv_sec {
79+
assert!(a.tv_nsec >= monotonic.tv_nsec);
80+
} else {
81+
assert!(a.tv_sec > monotonic.tv_sec);
82+
}
83+
}
84+
85+
#[cfg(feature = "linux_4_11")]
86+
{
87+
let a = clock_gettime(ClockId::BoottimeAlarm);
88+
let b = clock_gettime(ClockId::BoottimeAlarm);
89+
90+
if b.tv_sec == a.tv_sec {
91+
assert!(b.tv_nsec >= a.tv_nsec);
92+
} else {
93+
assert!(b.tv_sec > a.tv_sec);
94+
}
95+
96+
// Test that boot alarm time is after monotonic.
97+
if a.tv_sec == monotonic.tv_sec {
98+
assert!(a.tv_nsec >= monotonic.tv_nsec);
99+
} else {
100+
assert!(a.tv_sec > monotonic.tv_sec);
101+
}
28102
}
29103
}
30104

@@ -79,6 +153,71 @@ fn test_realtime_coarse_clock() {
79153
assert!(a.tv_nsec < 1_000_000_000);
80154
}
81155

156+
#[cfg(linux_kernel)]
157+
#[test]
158+
fn test_realtime_alarm_clock() {
159+
use rustix::time::{clock_gettime_dynamic, DynamicClockId};
160+
161+
if let Ok(a) = clock_gettime_dynamic(DynamicClockId::RealtimeAlarm) {
162+
// Test that the timespec is valid; there's not much else we can say.
163+
assert!(a.tv_nsec < 1_000_000_000);
164+
}
165+
166+
#[cfg(feature = "linux_4_11")]
167+
{
168+
let a = clock_gettime(ClockId::RealtimeAlarm);
169+
170+
// Test that the timespec is valid; there's not much else we can say.
171+
assert!(a.tv_nsec < 1_000_000_000);
172+
}
173+
}
174+
175+
/// Attempt to test that the TAI clock is monotonic. Time may or may not
176+
/// advance, but it shouldn't regress.
177+
#[cfg(linux_kernel)]
178+
#[test]
179+
fn test_tai_clock() {
180+
use rustix::time::{clock_gettime_dynamic, DynamicClockId};
181+
182+
let realtime = clock_gettime(ClockId::Realtime);
183+
184+
if let Ok(a) = clock_gettime_dynamic(DynamicClockId::Tai) {
185+
if let Ok(b) = clock_gettime_dynamic(DynamicClockId::Tai) {
186+
if b.tv_sec == a.tv_sec {
187+
assert!(b.tv_nsec >= a.tv_nsec);
188+
} else {
189+
assert!(b.tv_sec > a.tv_sec);
190+
}
191+
}
192+
193+
// Test that TAI time is after realtime.
194+
if a.tv_sec == realtime.tv_sec {
195+
assert!(a.tv_nsec >= realtime.tv_nsec);
196+
} else {
197+
assert!(a.tv_sec > realtime.tv_sec);
198+
}
199+
}
200+
201+
#[cfg(feature = "linux_4_11")]
202+
{
203+
let a = clock_gettime(ClockId::Tai);
204+
let b = clock_gettime(ClockId::Tai);
205+
206+
if b.tv_sec == a.tv_sec {
207+
assert!(b.tv_nsec >= a.tv_nsec);
208+
} else {
209+
assert!(b.tv_sec > a.tv_sec);
210+
}
211+
212+
// Test that TAI time is after realtime.
213+
if a.tv_sec == realtime.tv_sec {
214+
assert!(a.tv_nsec >= realtime.tv_nsec);
215+
} else {
216+
assert!(a.tv_sec > realtime.tv_sec);
217+
}
218+
}
219+
}
220+
82221
/// Attempt to test that the coarse monotonic clock is monotonic. Time may or
83222
/// may not advance, but it shouldn't regress.
84223
#[cfg(any(linux_kernel, target_os = "freebsd"))]

0 commit comments

Comments
 (0)