1
- use std:: time:: { Duration , SystemTime } ;
1
+ use std:: time:: { Duration , SystemTime , Instant } ;
2
+ use std:: convert:: TryFrom ;
2
3
3
4
use crate :: stacked_borrows:: Tag ;
4
5
use crate :: * ;
5
6
use helpers:: immty_from_int_checked;
6
7
7
- // Returns the time elapsed between now and the unix epoch as a `Duration`.
8
- fn get_time < ' tcx > ( ) -> InterpResult < ' tcx , Duration > {
9
- system_time_to_duration ( & SystemTime :: now ( ) )
10
- }
11
-
12
8
/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
13
9
pub fn system_time_to_duration < ' tcx > ( time : & SystemTime ) -> InterpResult < ' tcx , Duration > {
14
10
time. duration_since ( SystemTime :: UNIX_EPOCH )
@@ -17,26 +13,31 @@ pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Du
17
13
18
14
impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
19
15
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
20
- // Foreign function used by linux
21
16
fn clock_gettime (
22
17
& mut self ,
23
18
clk_id_op : OpTy < ' tcx , Tag > ,
24
19
tp_op : OpTy < ' tcx , Tag > ,
25
20
) -> InterpResult < ' tcx , i32 > {
26
21
let this = self . eval_context_mut ( ) ;
27
22
23
+ this. assert_platform ( "linux" , "clock_gettime" ) ;
28
24
this. check_no_isolation ( "clock_gettime" ) ?;
29
25
30
26
let clk_id = this. read_scalar ( clk_id_op) ?. to_i32 ( ) ?;
31
- if clk_id != this. eval_libc_i32 ( "CLOCK_REALTIME" ) ? {
27
+ let tp = this. deref_operand ( tp_op) ?;
28
+
29
+ let duration = if clk_id == this. eval_libc_i32 ( "CLOCK_REALTIME" ) ? {
30
+ system_time_to_duration ( & SystemTime :: now ( ) ) ?
31
+ } else if clk_id == this. eval_libc_i32 ( "CLOCK_MONOTONIC" ) ? {
32
+ // Absolute time does not matter, only relative time does, so we can just
33
+ // use our own time anchor here.
34
+ Instant :: now ( ) . duration_since ( this. machine . time_anchor )
35
+ } else {
32
36
let einval = this. eval_libc ( "EINVAL" ) ?;
33
37
this. set_last_error ( einval) ?;
34
38
return Ok ( -1 ) ;
35
- }
36
-
37
- let tp = this. deref_operand ( tp_op) ?;
39
+ } ;
38
40
39
- let duration = get_time ( ) ?;
40
41
let tv_sec = duration. as_secs ( ) ;
41
42
let tv_nsec = duration. subsec_nanos ( ) ;
42
43
@@ -49,15 +50,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
49
50
50
51
Ok ( 0 )
51
52
}
52
- // Foreign function used by generic unix (in particular macOS)
53
+
53
54
fn gettimeofday (
54
55
& mut self ,
55
56
tv_op : OpTy < ' tcx , Tag > ,
56
57
tz_op : OpTy < ' tcx , Tag > ,
57
58
) -> InterpResult < ' tcx , i32 > {
58
59
let this = self . eval_context_mut ( ) ;
59
60
61
+ this. assert_platform ( "macos" , "gettimeofday" ) ;
60
62
this. check_no_isolation ( "gettimeofday" ) ?;
63
+
61
64
// Using tz is obsolete and should always be null
62
65
let tz = this. read_scalar ( tz_op) ?. not_undef ( ) ?;
63
66
if !this. is_null ( tz) ? {
@@ -68,7 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
68
71
69
72
let tv = this. deref_operand ( tv_op) ?;
70
73
71
- let duration = get_time ( ) ?;
74
+ let duration = system_time_to_duration ( & SystemTime :: now ( ) ) ?;
72
75
let tv_sec = duration. as_secs ( ) ;
73
76
let tv_usec = duration. subsec_micros ( ) ;
74
77
@@ -81,4 +84,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
81
84
82
85
Ok ( 0 )
83
86
}
87
+
88
+ fn mach_absolute_time ( & self ) -> InterpResult < ' tcx , u64 > {
89
+ let this = self . eval_context_ref ( ) ;
90
+
91
+ this. assert_platform ( "macos" , "mach_absolute_time" ) ;
92
+ this. check_no_isolation ( "mach_absolute_time" ) ?;
93
+
94
+ // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
95
+ // We return plain nanoseconds.
96
+ let duration = Instant :: now ( ) . duration_since ( this. machine . time_anchor ) ;
97
+ u64:: try_from ( duration. as_nanos ( ) )
98
+ . map_err ( |_| err_unsup_format ! ( "programs running longer than 2^64 nanoseconds are not supported" ) . into ( ) )
99
+ }
84
100
}
0 commit comments