1- use std:: sync:: atomic:: AtomicU64 ;
2- use std:: time:: { Duration , Instant as StdInstant , SystemTime } ;
1+ use std:: time:: { Duration , SystemTime } ;
32
4- use rustc_data_structures:: sync:: Ordering ;
5-
6- use crate :: concurrency:: thread:: Time ;
73use crate :: * ;
84
9- /// When using a virtual clock, this defines how many nanoseconds do we pretend
10- /// are passing for each basic block.
11- const NANOSECOND_PER_BASIC_BLOCK : u64 = 10 ;
12-
13- #[ derive( Debug ) ]
14- pub struct Instant {
15- kind : InstantKind ,
16- }
17-
18- #[ derive( Debug ) ]
19- enum InstantKind {
20- Host ( StdInstant ) ,
21- Virtual { nanoseconds : u64 } ,
22- }
23-
24- /// A monotone clock used for `Instant` simulation.
25- #[ derive( Debug ) ]
26- pub struct Clock {
27- kind : ClockKind ,
28- }
29-
30- #[ derive( Debug ) ]
31- enum ClockKind {
32- Host {
33- /// The "time anchor" for this machine's monotone clock.
34- time_anchor : StdInstant ,
35- } ,
36- Virtual {
37- /// The "current virtual time".
38- nanoseconds : AtomicU64 ,
39- } ,
40- }
41-
42- impl Clock {
43- /// Create a new clock based on the availability of communication with the host.
44- pub fn new ( communicate : bool ) -> Self {
45- let kind = if communicate {
46- ClockKind :: Host { time_anchor : StdInstant :: now ( ) }
47- } else {
48- ClockKind :: Virtual { nanoseconds : 0 . into ( ) }
49- } ;
50-
51- Self { kind }
52- }
53-
54- /// Get the current time relative to this clock.
55- pub fn get ( & self ) -> Duration {
56- match & self . kind {
57- ClockKind :: Host { time_anchor } =>
58- StdInstant :: now ( ) . saturating_duration_since ( * time_anchor) ,
59- ClockKind :: Virtual { nanoseconds } =>
60- Duration :: from_nanos ( nanoseconds. load ( Ordering :: Relaxed ) ) ,
61- }
62- }
63-
64- /// Let the time pass for a small interval.
65- pub fn tick ( & self ) {
66- match & self . kind {
67- ClockKind :: Host { .. } => {
68- // Time will pass without us doing anything.
69- }
70- ClockKind :: Virtual { nanoseconds } => {
71- nanoseconds. fetch_add ( NANOSECOND_PER_BASIC_BLOCK , Ordering :: Relaxed ) ;
72- }
73- }
74- }
75-
76- /// Sleep for the desired duration.
77- pub fn sleep ( & self , duration : Duration ) {
78- match & self . kind {
79- ClockKind :: Host { .. } => std:: thread:: sleep ( duration) ,
80- ClockKind :: Virtual { nanoseconds } => {
81- // Just pretend that we have slept for some time.
82- nanoseconds. fetch_add ( duration. as_nanos ( ) . try_into ( ) . unwrap ( ) , Ordering :: Relaxed ) ;
83- }
84- }
85- }
86-
87- /// Compute `now + duration` relative to this clock.
88- pub fn get_time_relative ( & self , duration : Duration ) -> Option < Time > {
89- match & self . kind {
90- ClockKind :: Host { .. } =>
91- StdInstant :: now ( )
92- . checked_add ( duration)
93- . map ( |instant| Time :: Monotonic ( Instant { kind : InstantKind :: Host ( instant) } ) ) ,
94- ClockKind :: Virtual { nanoseconds } =>
95- nanoseconds
96- . load ( Ordering :: Relaxed )
97- . checked_add ( duration. as_nanos ( ) . try_into ( ) . unwrap ( ) )
98- . map ( |nanoseconds| {
99- Time :: Monotonic ( Instant { kind : InstantKind :: Virtual { nanoseconds } } )
100- } ) ,
101- }
102- }
103-
104- /// Compute `start + duration` relative to this clock where `start` is the instant of time when
105- /// this clock was created.
106- pub fn get_time_absolute ( & self , duration : Duration ) -> Option < Time > {
107- match & self . kind {
108- ClockKind :: Host { time_anchor } =>
109- time_anchor
110- . checked_add ( duration)
111- . map ( |instant| Time :: Monotonic ( Instant { kind : InstantKind :: Host ( instant) } ) ) ,
112- ClockKind :: Virtual { .. } =>
113- Some ( Time :: Monotonic ( Instant {
114- kind : InstantKind :: Virtual {
115- nanoseconds : duration. as_nanos ( ) . try_into ( ) . unwrap ( ) ,
116- } ,
117- } ) ) ,
118- }
119- }
120-
121- /// How long do we have to wait from now until the specified time?
122- pub fn get_wait_time ( & self , time : & Time ) -> Duration {
123- match time {
124- Time :: Monotonic ( instant) =>
125- match ( & instant. kind , & self . kind ) {
126- ( InstantKind :: Host ( instant) , ClockKind :: Host { .. } ) =>
127- instant. saturating_duration_since ( StdInstant :: now ( ) ) ,
128- (
129- InstantKind :: Virtual { nanoseconds } ,
130- ClockKind :: Virtual { nanoseconds : current_ns } ,
131- ) =>
132- Duration :: from_nanos (
133- nanoseconds. saturating_sub ( current_ns. load ( Ordering :: Relaxed ) ) ,
134- ) ,
135- _ => panic ! ( ) ,
136- } ,
137- Time :: RealTime ( time) =>
138- time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: new ( 0 , 0 ) ) ,
139- }
140- }
141- }
142-
1435/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
1446pub fn system_time_to_duration < ' tcx > ( time : & SystemTime ) -> InterpResult < ' tcx , Duration > {
1457 time. duration_since ( SystemTime :: UNIX_EPOCH )
@@ -354,7 +216,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
354216
355217 this. register_timeout_callback (
356218 active_thread,
357- timeout_time,
219+ Time :: Monotonic ( timeout_time) ,
358220 Box :: new ( move |ecx| {
359221 ecx. unblock_thread ( active_thread) ;
360222 Ok ( ( ) )
@@ -380,7 +242,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
380242
381243 this. register_timeout_callback (
382244 active_thread,
383- timeout_time,
245+ Time :: Monotonic ( timeout_time) ,
384246 Box :: new ( move |ecx| {
385247 ecx. unblock_thread ( active_thread) ;
386248 Ok ( ( ) )
0 commit comments