@@ -22,28 +22,52 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
22
22
23
23
let this = self . eval_context_mut ( ) ;
24
24
25
- this. assert_target_os ( "linux" , "clock_gettime" ) ;
25
+ this. assert_target_os_is_unix ( "clock_gettime" ) ;
26
26
27
27
let clk_id = this. read_scalar ( clk_id_op) ?. to_i32 ( ) ?;
28
28
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
+ }
40
63
41
64
let duration = if absolute_clocks. contains ( & clk_id) {
42
65
this. check_no_isolation ( "`clock_gettime` with `REALTIME` clocks" ) ?;
43
66
system_time_to_duration ( & SystemTime :: now ( ) ) ?
44
67
} else if relative_clocks. contains ( & clk_id) {
45
68
this. machine . clock . now ( ) . duration_since ( this. machine . clock . anchor ( ) )
46
69
} else {
70
+ // Unsupported clock.
47
71
let einval = this. eval_libc ( "EINVAL" ) ?;
48
72
this. set_last_error ( einval) ?;
49
73
return Ok ( Scalar :: from_i32 ( -1 ) ) ;
0 commit comments