@@ -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