about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-11-19 20:21:48 +0100
committerRalf Jung <post@ralfj.de>2022-11-19 23:47:41 +0100
commit21321f57c2e6670d29b8f68cb2b4835142cfa3e2 (patch)
tree04ad58cb345f5d3368db96e74bf365e211d5af48
parent81ee8c13dc3e10cf4f028faf19a5585a73c5f3d3 (diff)
downloadrust-21321f57c2e6670d29b8f68cb2b4835142cfa3e2.tar.gz
rust-21321f57c2e6670d29b8f68cb2b4835142cfa3e2.zip
implement clock_gettime on macos
-rw-r--r--src/tools/miri/src/shims/time.rs48
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs9
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-misc.rs20
4 files changed, 56 insertions, 27 deletions
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 617f90dfaa5..bc0b71fbc20 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/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/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 44a433df1e9..d746f9df90a 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/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/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 2b53152688b..34076e842d5 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/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/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index 904ae2fb17f..2a4300fcd04 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/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::<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() {
@@ -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();
     }
 }