Add support for _COARSE clocks, spruce up comments

This commit is contained in:
Ben Kimock 2022-05-29 18:00:06 -04:00
parent 5c3e4b6556
commit ba9391334e
2 changed files with 43 additions and 4 deletions

View File

@ -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")?;

View File

@ -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();
}