diff --git a/rust-version b/rust-version index b839837758..d3e139e465 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -9340e5c1b9dee53fd32a18f7bfb54faabfe00b7b +2f8d8040166a730d0da7bba0f2864f0ef7ff6364 diff --git a/src/shims/time.rs b/src/shims/time.rs index 617f90dfaa..bc0b71fbc2 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -22,21 +22,44 @@ 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")?; @@ -44,6 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } 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)); diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 44a433df1e..d746f9df90 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -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" => { diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 2b53152688..34076e842d 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -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] = diff --git a/tests/pass-dep/shims/libc-misc.rs b/tests/pass-dep/shims/libc-misc.rs index 904ae2fb17..2a4300fcd0 100644 --- a/tests/pass-dep/shims/libc-misc.rs +++ b/tests/pass-dep/shims/libc-misc.rs @@ -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::::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() { @@ -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(); } }