Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ba93913

Browse files
committed
Add support for _COARSE clocks, spruce up comments
1 parent 5c3e4b6 commit ba93913

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

src/shims/time.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1616
clk_id_op: &OpTy<'tcx, Tag>,
1717
tp_op: &OpTy<'tcx, Tag>,
1818
) -> InterpResult<'tcx, i32> {
19+
// This clock support is deliberately minimal because a lot of clock types have fiddly
20+
// properties (is it possible for Miri to be suspended independently of the host?). If you
21+
// have a use for another clock type, please open an issue.
22+
1923
let this = self.eval_context_mut();
2024

2125
this.assert_target_os("linux", "clock_gettime");
2226
this.check_no_isolation("`clock_gettime`")?;
2327

2428
let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
2529

26-
let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
30+
// Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
31+
// Unix epoch, including effects which may cause time to move backwards such as NTP.
32+
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
33+
// is just specified to be "faster and less precise", so we implement both the same way.
34+
let absolute_clocks =
35+
[this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?];
36+
// The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
37+
// never allowed to go backwards. We don't need to do any additonal monotonicity
38+
// enforcement because std::time::Instant already guarantees that it is monotonic.
39+
let relative_clocks =
40+
[this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?];
41+
42+
let duration = if absolute_clocks.contains(&clk_id) {
2743
system_time_to_duration(&SystemTime::now())?
28-
} else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
29-
// Absolute time does not matter, only relative time does, so we can just
30-
// use our own time anchor here.
44+
} else if relative_clocks.contains(&clk_id) {
3145
Instant::now().duration_since(this.machine.time_anchor)
3246
} else {
3347
let einval = this.eval_libc("EINVAL")?;

tests/run-pass/libc.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,28 @@ fn test_thread_local_errno() {
230230
}
231231
}
232232

233+
/// Tests whether clock support exists at all
234+
#[cfg(target_os = "linux")]
235+
fn test_clocks() {
236+
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
237+
let is_error = unsafe {
238+
libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr())
239+
};
240+
assert_eq!(is_error, 0);
241+
let is_error = unsafe {
242+
libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr())
243+
};
244+
assert_eq!(is_error, 0);
245+
let is_error = unsafe {
246+
libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr())
247+
};
248+
assert_eq!(is_error, 0);
249+
let is_error = unsafe {
250+
libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr())
251+
};
252+
assert_eq!(is_error, 0);
253+
}
254+
233255
fn main() {
234256
#[cfg(target_os = "linux")]
235257
test_posix_fadvise();
@@ -249,4 +271,7 @@ fn main() {
249271
test_prctl_thread_name();
250272

251273
test_thread_local_errno();
274+
275+
#[cfg(target_os = "linux")]
276+
test_clocks();
252277
}

0 commit comments

Comments
 (0)