3
3
use std:: cell:: RefCell ;
4
4
use std:: collections:: hash_map:: Entry ;
5
5
use std:: num:: TryFromIntError ;
6
- use std:: time:: { Duration , Instant , SystemTime } ;
6
+ use std:: time:: { Duration , SystemTime } ;
7
7
8
8
use log:: trace;
9
9
@@ -16,6 +16,7 @@ use rustc_target::spec::abi::Abi;
16
16
17
17
use crate :: concurrency:: data_race;
18
18
use crate :: concurrency:: sync:: SynchronizationState ;
19
+ use crate :: shims:: time:: { Clock , Instant } ;
19
20
use crate :: * ;
20
21
21
22
#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
@@ -187,17 +188,6 @@ pub enum Time {
187
188
RealTime ( SystemTime ) ,
188
189
}
189
190
190
- impl Time {
191
- /// How long do we have to wait from now until the specified time?
192
- fn get_wait_time ( & self ) -> Duration {
193
- match self {
194
- Time :: Monotonic ( instant) => instant. saturating_duration_since ( Instant :: now ( ) ) ,
195
- Time :: RealTime ( time) =>
196
- time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: new ( 0 , 0 ) ) ,
197
- }
198
- }
199
- }
200
-
201
191
/// Callbacks are used to implement timeouts. For example, waiting on a
202
192
/// conditional variable with a timeout creates a callback that is called after
203
193
/// the specified time and unblocks the thread. If another thread signals on the
@@ -490,13 +480,16 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
490
480
}
491
481
492
482
/// Get a callback that is ready to be called.
493
- fn get_ready_callback ( & mut self ) -> Option < ( ThreadId , TimeoutCallback < ' mir , ' tcx > ) > {
483
+ fn get_ready_callback (
484
+ & mut self ,
485
+ clock : & Clock ,
486
+ ) -> Option < ( ThreadId , TimeoutCallback < ' mir , ' tcx > ) > {
494
487
// We iterate over all threads in the order of their indices because
495
488
// this allows us to have a deterministic scheduler.
496
489
for thread in self . threads . indices ( ) {
497
490
match self . timeout_callbacks . entry ( thread) {
498
491
Entry :: Occupied ( entry) =>
499
- if entry. get ( ) . call_time . get_wait_time ( ) == Duration :: new ( 0 , 0 ) {
492
+ if clock . get_wait_time ( & entry. get ( ) . call_time ) == Duration :: new ( 0 , 0 ) {
500
493
return Some ( ( thread, entry. remove ( ) . callback ) ) ;
501
494
} ,
502
495
Entry :: Vacant ( _) => { }
@@ -553,7 +546,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
553
546
/// used in stateless model checkers such as Loom: run the active thread as
554
547
/// long as we can and switch only when we have to (the active thread was
555
548
/// blocked, terminated, or has explicitly asked to be preempted).
556
- fn schedule ( & mut self ) -> InterpResult < ' tcx , SchedulingAction > {
549
+ fn schedule ( & mut self , clock : & Clock ) -> InterpResult < ' tcx , SchedulingAction > {
557
550
// Check whether the thread has **just** terminated (`check_terminated`
558
551
// checks whether the thread has popped all its stack and if yes, sets
559
552
// the thread state to terminated).
@@ -580,7 +573,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
580
573
// at the time of the call".
581
574
// <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
582
575
let potential_sleep_time =
583
- self . timeout_callbacks . values ( ) . map ( |info| info . call_time . get_wait_time ( ) ) . min ( ) ;
576
+ self . timeout_callbacks . values ( ) . map ( |info| clock . get_wait_time ( & info . call_time ) ) . min ( ) ;
584
577
if potential_sleep_time == Some ( Duration :: new ( 0 , 0 ) ) {
585
578
return Ok ( SchedulingAction :: ExecuteTimeoutCallback ) ;
586
579
}
@@ -615,7 +608,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
615
608
// All threads are currently blocked, but we have unexecuted
616
609
// timeout_callbacks, which may unblock some of the threads. Hence,
617
610
// sleep until the first callback.
618
- std:: thread:: sleep ( sleep_time) ;
611
+
612
+ clock. sleep ( sleep_time) ;
619
613
Ok ( SchedulingAction :: ExecuteTimeoutCallback )
620
614
} else {
621
615
throw_machine_stop ! ( TerminationInfo :: Deadlock ) ;
@@ -878,18 +872,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
878
872
#[ inline]
879
873
fn run_timeout_callback ( & mut self ) -> InterpResult < ' tcx > {
880
874
let this = self . eval_context_mut ( ) ;
881
- let ( thread, callback) =
882
- if let Some ( ( thread, callback) ) = this. machine . threads . get_ready_callback ( ) {
883
- ( thread, callback)
884
- } else {
885
- // get_ready_callback can return None if the computer's clock
886
- // was shifted after calling the scheduler and before the call
887
- // to get_ready_callback (see issue
888
- // https://github.com/rust-lang/miri/issues/1763). In this case,
889
- // just do nothing, which effectively just returns to the
890
- // scheduler.
891
- return Ok ( ( ) ) ;
892
- } ;
875
+ let ( thread, callback) = if let Some ( ( thread, callback) ) =
876
+ this. machine . threads . get_ready_callback ( & this. machine . clock )
877
+ {
878
+ ( thread, callback)
879
+ } else {
880
+ // get_ready_callback can return None if the computer's clock
881
+ // was shifted after calling the scheduler and before the call
882
+ // to get_ready_callback (see issue
883
+ // https://github.com/rust-lang/miri/issues/1763). In this case,
884
+ // just do nothing, which effectively just returns to the
885
+ // scheduler.
886
+ return Ok ( ( ) ) ;
887
+ } ;
893
888
// This back-and-forth with `set_active_thread` is here because of two
894
889
// design decisions:
895
890
// 1. Make the caller and not the callback responsible for changing
@@ -906,7 +901,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
906
901
#[ inline]
907
902
fn schedule ( & mut self ) -> InterpResult < ' tcx , SchedulingAction > {
908
903
let this = self . eval_context_mut ( ) ;
909
- this. machine . threads . schedule ( )
904
+ this. machine . threads . schedule ( & this . machine . clock )
910
905
}
911
906
912
907
/// Handles thread termination of the active thread: wakes up threads joining on this one,
0 commit comments