Skip to content

Commit

Permalink
Auto merge of #2679 - RalfJung:clock_gettime, r=RalfJung
Browse files Browse the repository at this point in the history
implement clock_gettime on macos

and pull in rustc changes so we can test this against rust-lang/rust#103594.

Fixes #2664
  • Loading branch information
bors committed Nov 19, 2022
2 parents 6d75804 + 445c2f5 commit a6a38dc
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 28 deletions.
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9340e5c1b9dee53fd32a18f7bfb54faabfe00b7b
2f8d8040166a730d0da7bba0f2864f0ef7ff6364
48 changes: 36 additions & 12 deletions src/shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,52 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

let this = self.eval_context_mut();

this.assert_target_os("linux", "clock_gettime");
this.assert_target_os_is_unix("clock_gettime");

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

// 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 absolute_clocks;
let mut relative_clocks;

match this.tcx.sess.target.os.as_ref() {
"linux" => {
// 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.
absolute_clocks = vec![
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.
relative_clocks = vec![
this.eval_libc_i32("CLOCK_MONOTONIC")?,
this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
];
}
"macos" => {
absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
// Some clocks only seem to exist in the aarch64 version of the target.
if this.tcx.sess.target.arch == "aarch64" {
// `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
// that's not really something a program running inside Miri can tell, anyway.
// We need to support it because std uses it.
relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
}
}
target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
}

let duration = if absolute_clocks.contains(&clk_id) {
this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?;
system_time_to_duration(&SystemTime::now())?
} else if relative_clocks.contains(&clk_id) {
this.machine.clock.now().duration_since(this.machine.clock.anchor())
} else {
// Unsupported clock.
let einval = this.eval_libc("EINVAL")?;
this.set_last_error(einval)?;
return Ok(Scalar::from_i32(-1));
Expand Down
6 changes: 6 additions & 0 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let result = this.gettimeofday(tv, tz)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"clock_gettime" => {
let [clk_id, tp] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.clock_gettime(clk_id, tp)?;
this.write_scalar(result, dest)?;
}

// Allocation
"posix_memalign" => {
Expand Down
9 changes: 0 additions & 9 deletions src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.write_scalar(result, dest)?;
}

// Time related shims
"clock_gettime" => {
// This is a POSIX function but it has only been tested on linux.
let [clk_id, tp] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.clock_gettime(clk_id, tp)?;
this.write_scalar(result, dest)?;
}

// Threading
"pthread_condattr_setclock" => {
let [attr, clock_id] =
Expand Down
20 changes: 14 additions & 6 deletions tests/pass-dep/shims/libc-misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,17 +181,25 @@ 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);
#[cfg(target_os = "linux")]
{
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_COARSE, tp.as_mut_ptr()) };
assert_eq!(is_error, 0);
}
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
{
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
assert_eq!(is_error, 0);
}
}

fn test_posix_gettimeofday() {
Expand Down Expand Up @@ -293,11 +301,11 @@ fn main() {
test_thread_local_errno();

test_isatty();
test_clocks();

#[cfg(target_os = "linux")]
{
test_posix_fadvise();
test_sync_file_range();
test_clocks();
}
}

0 comments on commit a6a38dc

Please sign in to comment.