Auto merge of #2165 - saethlin:more-clocks, r=RalfJung
Add support for _COARSE clocks Original idea does not work, so I'm just going to try expanding support to include the `_COARSE` clocks. The original motivation for this PR is that the test suite for the crate [`minstant`](https://crates.io/crates/minstant) reports UB, because it tries to use a clock type Miri didn't support, but never checked for an error code and so just used the uninit `libc::timespec`. So, that's technically a bug in `minstant`, but outside of Miri you'd have to be using an incredibly old Linux to ever see an `EINVAL` so the more helpful thing for Miri to do is behave like a newer Linux. So now we don't detect UB in `minstant`, but we have a test failure: ``` failures: ---- src/instant.rs - instant::Instant::as_unix_nanos (line 150) stdout ---- Test executable failed (exit status: 101). stderr: thread 'main' panicked at 'assertion failed: (instant.as_unix_nanos(&anchor) as i64 - expected as i64).abs() < 1_000_000', src/instant.rs:11:1 ``` I'm having trouble getting my head around the code in `minstant` that's involved in this test, but as far as I can tell from the man pages, these `_COARSE` clocks meet the requirements. Closes https://github.com/rust-lang/miri/issues/1983 at least as best as I can.
This commit is contained in:
commit
57d8206093
2 changed files with 43 additions and 4 deletions
|
|
@ -16,6 +16,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
clk_id_op: &OpTy<'tcx, Tag>,
|
||||
tp_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
// This clock support is deliberately minimal because a lot of clock types have fiddly
|
||||
// properties (is it possible for Miri to be suspended independently of the host?). If you
|
||||
// have a use for another clock type, please open an issue.
|
||||
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.assert_target_os("linux", "clock_gettime");
|
||||
|
|
@ -23,11 +27,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
|
||||
let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
|
||||
|
||||
let duration = if clk_id == this.eval_libc_i32("CLOCK_REALTIME")? {
|
||||
// Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
|
||||
// Unix epoch, including effects which may cause time to move backwards such as NTP.
|
||||
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
|
||||
// is just specified to be "faster and less precise", so we implement both the same way.
|
||||
let absolute_clocks =
|
||||
[this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?];
|
||||
// The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
|
||||
// never allowed to go backwards. We don't need to do any additonal monotonicity
|
||||
// enforcement because std::time::Instant already guarantees that it is monotonic.
|
||||
let relative_clocks =
|
||||
[this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?];
|
||||
|
||||
let duration = if absolute_clocks.contains(&clk_id) {
|
||||
system_time_to_duration(&SystemTime::now())?
|
||||
} else if clk_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
|
||||
// Absolute time does not matter, only relative time does, so we can just
|
||||
// use our own time anchor here.
|
||||
} else if relative_clocks.contains(&clk_id) {
|
||||
Instant::now().duration_since(this.machine.time_anchor)
|
||||
} else {
|
||||
let einval = this.eval_libc("EINVAL")?;
|
||||
|
|
|
|||
|
|
@ -230,6 +230,28 @@ fn test_thread_local_errno() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tests whether clock support exists at all
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_clocks() {
|
||||
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
|
||||
let is_error = unsafe {
|
||||
libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr())
|
||||
};
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe {
|
||||
libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr())
|
||||
};
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe {
|
||||
libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr())
|
||||
};
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe {
|
||||
libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr())
|
||||
};
|
||||
assert_eq!(is_error, 0);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_os = "linux")]
|
||||
test_posix_fadvise();
|
||||
|
|
@ -249,4 +271,7 @@ fn main() {
|
|||
test_prctl_thread_name();
|
||||
|
||||
test_thread_local_errno();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
test_clocks();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue