Skip to content

Commit a6a38dc

Browse files
committed
Auto merge of #2679 - RalfJung:clock_gettime, r=RalfJung
implement clock_gettime on macos and pull in rustc changes so we can test this against rust-lang/rust#103594. Fixes #2664
2 parents 6d75804 + 445c2f5 commit a6a38dc

File tree

5 files changed

+57
-28
lines changed

5 files changed

+57
-28
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9340e5c1b9dee53fd32a18f7bfb54faabfe00b7b
1+
2f8d8040166a730d0da7bba0f2864f0ef7ff6364

src/shims/time.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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));

src/shims/unix/foreign_items.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
180180
let result = this.gettimeofday(tv, tz)?;
181181
this.write_scalar(Scalar::from_i32(result), dest)?;
182182
}
183+
"clock_gettime" => {
184+
let [clk_id, tp] =
185+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
186+
let result = this.clock_gettime(clk_id, tp)?;
187+
this.write_scalar(result, dest)?;
188+
}
183189

184190
// Allocation
185191
"posix_memalign" => {

src/shims/unix/linux/foreign_items.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4343
this.write_scalar(result, dest)?;
4444
}
4545

46-
// Time related shims
47-
"clock_gettime" => {
48-
// This is a POSIX function but it has only been tested on linux.
49-
let [clk_id, tp] =
50-
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
51-
let result = this.clock_gettime(clk_id, tp)?;
52-
this.write_scalar(result, dest)?;
53-
}
54-
5546
// Threading
5647
"pthread_condattr_setclock" => {
5748
let [attr, clock_id] =

tests/pass-dep/shims/libc-misc.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,25 @@ fn test_thread_local_errno() {
181181
}
182182

183183
/// Tests whether clock support exists at all
184-
#[cfg(target_os = "linux")]
185184
fn test_clocks() {
186185
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
187186
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
188187
assert_eq!(is_error, 0);
189-
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
190-
assert_eq!(is_error, 0);
191188
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
192189
assert_eq!(is_error, 0);
193-
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
194-
assert_eq!(is_error, 0);
190+
#[cfg(target_os = "linux")]
191+
{
192+
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
193+
assert_eq!(is_error, 0);
194+
let is_error =
195+
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
196+
assert_eq!(is_error, 0);
197+
}
198+
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
199+
{
200+
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
201+
assert_eq!(is_error, 0);
202+
}
195203
}
196204

197205
fn test_posix_gettimeofday() {
@@ -293,11 +301,11 @@ fn main() {
293301
test_thread_local_errno();
294302

295303
test_isatty();
304+
test_clocks();
296305

297306
#[cfg(target_os = "linux")]
298307
{
299308
test_posix_fadvise();
300309
test_sync_file_range();
301-
test_clocks();
302310
}
303311
}

0 commit comments

Comments
 (0)