@@ -17,73 +17,71 @@ pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Du
17
17
18
18
impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
19
19
pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
20
- fn clock_gettime (
21
- & mut self ,
22
- clk_id_op : & OpTy < ' tcx > ,
23
- tp_op : & OpTy < ' tcx > ,
24
- dest : & MPlaceTy < ' tcx > ,
25
- ) -> InterpResult < ' tcx > {
20
+ fn parse_clockid ( & self , clk_id : Scalar ) -> Option < TimeoutClock > {
26
21
// This clock support is deliberately minimal because a lot of clock types have fiddly
27
22
// properties (is it possible for Miri to be suspended independently of the host?). If you
28
23
// have a use for another clock type, please open an issue.
24
+ let this = self . eval_context_ref ( ) ;
29
25
30
- let this = self . eval_context_mut ( ) ;
31
-
32
- this. assert_target_os_is_unix ( "clock_gettime" ) ;
33
- let clockid_t_size = this. libc_ty_layout ( "clockid_t" ) . size ;
34
-
35
- let clk_id = this. read_scalar ( clk_id_op) ?. to_int ( clockid_t_size) ?;
36
- let tp = this. deref_pointer_as ( tp_op, this. libc_ty_layout ( "timespec" ) ) ?;
37
-
38
- let absolute_clocks;
39
- let mut relative_clocks;
26
+ // Portable names that exist everywhere.
27
+ if clk_id == this. eval_libc ( "CLOCK_REALTIME" ) {
28
+ return Some ( TimeoutClock :: RealTime ) ;
29
+ } else if clk_id == this. eval_libc ( "CLOCK_MONOTONIC" ) {
30
+ return Some ( TimeoutClock :: Monotonic ) ;
31
+ }
40
32
33
+ // Some further platform-specific names we support.
41
34
match this. tcx . sess . target . os . as_ref ( ) {
42
35
"linux" | "freebsd" | "android" => {
43
- // Linux, Android, and FreeBSD have two main kinds of clocks. REALTIME clocks return the actual time since the
44
- // Unix epoch, including effects which may cause time to move backwards such as NTP.
45
36
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
46
- // is just specified to be "faster and less precise", so we implement both the same way.
47
- absolute_clocks = vec ! [
48
- this. eval_libc( "CLOCK_REALTIME" ) . to_int( clockid_t_size) ?,
49
- this. eval_libc( "CLOCK_REALTIME_COARSE" ) . to_int( clockid_t_size) ?,
50
- ] ;
51
- // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
52
- // never allowed to go backwards. We don't need to do any additional monotonicity
53
- // enforcement because std::time::Instant already guarantees that it is monotonic.
54
- relative_clocks = vec ! [
55
- this. eval_libc( "CLOCK_MONOTONIC" ) . to_int( clockid_t_size) ?,
56
- this. eval_libc( "CLOCK_MONOTONIC_COARSE" ) . to_int( clockid_t_size) ?,
57
- ] ;
37
+ // is just specified to be "faster and less precise", so we treat it like normal
38
+ // clocks.
39
+ if clk_id == this. eval_libc ( "CLOCK_REALTIME_COARSE" ) {
40
+ return Some ( TimeoutClock :: RealTime ) ;
41
+ } else if clk_id == this. eval_libc ( "CLOCK_MONOTONIC_COARSE" ) {
42
+ return Some ( TimeoutClock :: Monotonic ) ;
43
+ }
58
44
}
59
45
"macos" => {
60
- absolute_clocks = vec ! [ this. eval_libc( "CLOCK_REALTIME" ) . to_int( clockid_t_size) ?] ;
61
- relative_clocks = vec ! [ this. eval_libc( "CLOCK_MONOTONIC" ) . to_int( clockid_t_size) ?] ;
62
46
// `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
63
47
// that's not really something a program running inside Miri can tell, anyway.
64
48
// We need to support it because std uses it.
65
- relative_clocks. push ( this. eval_libc ( "CLOCK_UPTIME_RAW" ) . to_int ( clockid_t_size) ?) ;
66
- }
67
- "solaris" | "illumos" => {
68
- // The REALTIME clock returns the actual time since the Unix epoch.
69
- absolute_clocks = vec ! [ this. eval_libc( "CLOCK_REALTIME" ) . to_int( clockid_t_size) ?] ;
70
- // MONOTONIC, in the other hand, is the high resolution, non-adjustable
71
- // clock from an arbitrary time in the past.
72
- // Note that the man page mentions HIGHRES but it is just
73
- // an alias of MONOTONIC and the libc crate does not expose it anyway.
74
- // https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html
75
- relative_clocks = vec ! [ this. eval_libc( "CLOCK_MONOTONIC" ) . to_int( clockid_t_size) ?] ;
49
+ if clk_id == this. eval_libc ( "CLOCK_UPTIME_RAW" ) {
50
+ return Some ( TimeoutClock :: Monotonic ) ;
51
+ }
76
52
}
77
- target => throw_unsup_format ! ( "`clock_gettime` is not supported on target OS {target}" ) ,
53
+ _ => { }
78
54
}
79
55
80
- let duration = if absolute_clocks. contains ( & clk_id) {
81
- this. check_no_isolation ( "`clock_gettime` with `REALTIME` clocks" ) ?;
82
- system_time_to_duration ( & SystemTime :: now ( ) ) ?
83
- } else if relative_clocks. contains ( & clk_id) {
84
- this. machine . monotonic_clock . now ( ) . duration_since ( this. machine . monotonic_clock . epoch ( ) )
85
- } else {
86
- return this. set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
56
+ None
57
+ }
58
+
59
+ fn clock_gettime (
60
+ & mut self ,
61
+ clk_id_op : & OpTy < ' tcx > ,
62
+ tp_op : & OpTy < ' tcx > ,
63
+ dest : & MPlaceTy < ' tcx > ,
64
+ ) -> InterpResult < ' tcx > {
65
+ let this = self . eval_context_mut ( ) ;
66
+
67
+ this. assert_target_os_is_unix ( "clock_gettime" ) ;
68
+
69
+ let clk_id = this. read_scalar ( clk_id_op) ?;
70
+ let tp = this. deref_pointer_as ( tp_op, this. libc_ty_layout ( "timespec" ) ) ?;
71
+
72
+ let duration = match this. parse_clockid ( clk_id) {
73
+ Some ( TimeoutClock :: RealTime ) => {
74
+ this. check_no_isolation ( "`clock_gettime` with `REALTIME` clocks" ) ?;
75
+ system_time_to_duration ( & SystemTime :: now ( ) ) ?
76
+ }
77
+ Some ( TimeoutClock :: Monotonic ) =>
78
+ this. machine
79
+ . monotonic_clock
80
+ . now ( )
81
+ . duration_since ( this. machine . monotonic_clock . epoch ( ) ) ,
82
+ None => {
83
+ return this. set_last_error_and_return ( LibcError ( "EINVAL" ) , dest) ;
84
+ }
87
85
} ;
88
86
89
87
let tv_sec = duration. as_secs ( ) ;
0 commit comments