33use std:: cell:: RefCell ;
44use std:: collections:: hash_map:: Entry ;
55use std:: num:: TryFromIntError ;
6- use std:: time:: { Duration , Instant , SystemTime } ;
6+ use std:: time:: { Duration , SystemTime } ;
77
88use log:: trace;
99
@@ -16,6 +16,7 @@ use rustc_target::spec::abi::Abi;
1616
1717use crate :: concurrency:: data_race;
1818use crate :: concurrency:: sync:: SynchronizationState ;
19+ use crate :: shims:: time:: { Clock , Instant } ;
1920use crate :: * ;
2021
2122#[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
@@ -187,17 +188,6 @@ pub enum Time {
187188 RealTime ( SystemTime ) ,
188189}
189190
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-
201191/// Callbacks are used to implement timeouts. For example, waiting on a
202192/// conditional variable with a timeout creates a callback that is called after
203193/// the specified time and unblocks the thread. If another thread signals on the
@@ -490,13 +480,16 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
490480 }
491481
492482 /// 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 > ) > {
494487 // We iterate over all threads in the order of their indices because
495488 // this allows us to have a deterministic scheduler.
496489 for thread in self . threads . indices ( ) {
497490 match self . timeout_callbacks . entry ( thread) {
498491 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 ) {
500493 return Some ( ( thread, entry. remove ( ) . callback ) ) ;
501494 } ,
502495 Entry :: Vacant ( _) => { }
@@ -553,7 +546,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
553546 /// used in stateless model checkers such as Loom: run the active thread as
554547 /// long as we can and switch only when we have to (the active thread was
555548 /// 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 > {
557550 // Check whether the thread has **just** terminated (`check_terminated`
558551 // checks whether the thread has popped all its stack and if yes, sets
559552 // the thread state to terminated).
@@ -580,7 +573,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
580573 // at the time of the call".
581574 // <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
582575 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 ( ) ;
584577 if potential_sleep_time == Some ( Duration :: new ( 0 , 0 ) ) {
585578 return Ok ( SchedulingAction :: ExecuteTimeoutCallback ) ;
586579 }
@@ -615,7 +608,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
615608 // All threads are currently blocked, but we have unexecuted
616609 // timeout_callbacks, which may unblock some of the threads. Hence,
617610 // sleep until the first callback.
618- std:: thread:: sleep ( sleep_time) ;
611+
612+ clock. sleep ( sleep_time) ;
619613 Ok ( SchedulingAction :: ExecuteTimeoutCallback )
620614 } else {
621615 throw_machine_stop ! ( TerminationInfo :: Deadlock ) ;
@@ -878,18 +872,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
878872 #[ inline]
879873 fn run_timeout_callback ( & mut self ) -> InterpResult < ' tcx > {
880874 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+ } ;
893888 // This back-and-forth with `set_active_thread` is here because of two
894889 // design decisions:
895890 // 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
906901 #[ inline]
907902 fn schedule ( & mut self ) -> InterpResult < ' tcx , SchedulingAction > {
908903 let this = self . eval_context_mut ( ) ;
909- this. machine . threads . schedule ( )
904+ this. machine . threads . schedule ( & this . machine . clock )
910905 }
911906
912907 /// Handles thread termination of the active thread: wakes up threads joining on this one,
0 commit comments