@@ -16,18 +16,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
16
16
clk_id_op : & OpTy < ' tcx , Tag > ,
17
17
tp_op : & OpTy < ' tcx , Tag > ,
18
18
) -> InterpResult < ' tcx , i32 > {
19
+ // This clock support is deliberately minimal because a lot of clock types have fiddly
20
+ // properties (is it possible for Miri to be suspended independently of the host?). If you
21
+ // have a use for another clock type, please open an issue.
22
+
19
23
let this = self . eval_context_mut ( ) ;
20
24
21
25
this. assert_target_os ( "linux" , "clock_gettime" ) ;
22
26
this. check_no_isolation ( "`clock_gettime`" ) ?;
23
27
24
28
let clk_id = this. read_scalar ( clk_id_op) ?. to_i32 ( ) ?;
25
29
26
- let duration = if clk_id == this. eval_libc_i32 ( "CLOCK_REALTIME" ) ? {
30
+ // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
31
+ // Unix epoch, including effects which may cause time to move backwards such as NTP.
32
+ // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
33
+ // is just specified to be "faster and less precise", so we implement both the same way.
34
+ let absolute_clocks =
35
+ [ this. eval_libc_i32 ( "CLOCK_REALTIME" ) ?, this. eval_libc_i32 ( "CLOCK_REALTIME_COARSE" ) ?] ;
36
+ // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
37
+ // never allowed to go backwards. We don't need to do any additonal monotonicity
38
+ // enforcement because std::time::Instant already guarantees that it is monotonic.
39
+ let relative_clocks =
40
+ [ this. eval_libc_i32 ( "CLOCK_MONOTONIC" ) ?, this. eval_libc_i32 ( "CLOCK_MONOTONIC_COARSE" ) ?] ;
41
+
42
+ let duration = if absolute_clocks. contains ( & clk_id) {
27
43
system_time_to_duration ( & SystemTime :: now ( ) ) ?
28
- } else if clk_id == this. eval_libc_i32 ( "CLOCK_MONOTONIC" ) ? {
29
- // Absolute time does not matter, only relative time does, so we can just
30
- // use our own time anchor here.
44
+ } else if relative_clocks. contains ( & clk_id) {
31
45
Instant :: now ( ) . duration_since ( this. machine . time_anchor )
32
46
} else {
33
47
let einval = this. eval_libc ( "EINVAL" ) ?;
0 commit comments