@@ -22,28 +22,52 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
2222
2323 let this = self.eval_context_mut();
2424
25- this.assert_target_os("linux", "clock_gettime");
25+ this.assert_target_os_is_unix( "clock_gettime");
2626
2727 let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
2828
29- // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
30- // Unix epoch, including effects which may cause time to move backwards such as NTP.
31- // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
32- // is just specified to be "faster and less precise", so we implement both the same way.
33- let absolute_clocks =
34- [this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?];
35- // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
36- // never allowed to go backwards. We don't need to do any additonal monotonicity
37- // enforcement because std::time::Instant already guarantees that it is monotonic.
38- let relative_clocks =
39- [this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?];
29+ let absolute_clocks;
30+ let mut relative_clocks;
31+
32+ match this.tcx.sess.target.os.as_ref() {
33+ "linux" => {
34+ // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
35+ // Unix epoch, including effects which may cause time to move backwards such as NTP.
36+ // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
37+ // is just specified to be "faster and less precise", so we implement both the same way.
38+ absolute_clocks = vec![
39+ this.eval_libc_i32("CLOCK_REALTIME")?,
40+ this.eval_libc_i32("CLOCK_REALTIME_COARSE")?,
41+ ];
42+ // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
43+ // never allowed to go backwards. We don't need to do any additonal monotonicity
44+ // enforcement because std::time::Instant already guarantees that it is monotonic.
45+ relative_clocks = vec![
46+ this.eval_libc_i32("CLOCK_MONOTONIC")?,
47+ this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
48+ ];
49+ }
50+ "macos" => {
51+ absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
52+ relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
53+ // Some clocks only seem to exist in the aarch64 version of the target.
54+ if this.tcx.sess.target.arch == "aarch64" {
55+ // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
56+ // that's not really something a program running inside Miri can tell, anyway.
57+ // We need to support it because std uses it.
58+ relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
59+ }
60+ }
61+ target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
62+ }
4063
4164 let duration = if absolute_clocks.contains(&clk_id) {
4265 this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?;
4366 system_time_to_duration(&SystemTime::now())?
4467 } else if relative_clocks.contains(&clk_id) {
4568 this.machine.clock.now().duration_since(this.machine.clock.anchor())
4669 } else {
70+ // Unsupported clock.
4771 let einval = this.eval_libc("EINVAL")?;
4872 this.set_last_error(einval)?;
4973 return Ok(Scalar::from_i32(-1));
0 commit comments