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
@@ -189,9 +189,9 @@ pub enum Time {
189
189
190
190
impl Time {
191
191
/// How long do we have to wait from now until the specified time?
192
- fn get_wait_time ( & self ) -> Duration {
192
+ fn get_wait_time ( & self , clock : & Clock ) -> Duration {
193
193
match self {
194
- Time :: Monotonic ( instant) => instant. saturating_duration_since ( Instant :: now ( ) ) ,
194
+ Time :: Monotonic ( instant) => instant. duration_since ( clock . now ( ) ) ,
195
195
Time :: RealTime ( time) =>
196
196
time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: new ( 0 , 0 ) ) ,
197
197
}
@@ -490,13 +490,16 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
490
490
}
491
491
492
492
/// Get a callback that is ready to be called.
493
- fn get_ready_callback ( & mut self ) -> Option < ( ThreadId , TimeoutCallback < ' mir , ' tcx > ) > {
493
+ fn get_ready_callback (
494
+ & mut self ,
495
+ clock : & Clock ,
496
+ ) -> Option < ( ThreadId , TimeoutCallback < ' mir , ' tcx > ) > {
494
497
// We iterate over all threads in the order of their indices because
495
498
// this allows us to have a deterministic scheduler.
496
499
for thread in self . threads . indices ( ) {
497
500
match self . timeout_callbacks . entry ( thread) {
498
501
Entry :: Occupied ( entry) =>
499
- if entry. get ( ) . call_time . get_wait_time ( ) == Duration :: new ( 0 , 0 ) {
502
+ if entry. get ( ) . call_time . get_wait_time ( clock ) == Duration :: new ( 0 , 0 ) {
500
503
return Some ( ( thread, entry. remove ( ) . callback ) ) ;
501
504
} ,
502
505
Entry :: Vacant ( _) => { }
@@ -553,7 +556,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
553
556
/// used in stateless model checkers such as Loom: run the active thread as
554
557
/// long as we can and switch only when we have to (the active thread was
555
558
/// blocked, terminated, or has explicitly asked to be preempted).
556
- fn schedule ( & mut self ) -> InterpResult < ' tcx , SchedulingAction > {
559
+ fn schedule ( & mut self , clock : & Clock ) -> InterpResult < ' tcx , SchedulingAction > {
557
560
// Check whether the thread has **just** terminated (`check_terminated`
558
561
// checks whether the thread has popped all its stack and if yes, sets
559
562
// the thread state to terminated).
@@ -580,7 +583,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
580
583
// at the time of the call".
581
584
// <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
582
585
let potential_sleep_time =
583
- self . timeout_callbacks . values ( ) . map ( |info| info. call_time . get_wait_time ( ) ) . min ( ) ;
586
+ self . timeout_callbacks . values ( ) . map ( |info| info. call_time . get_wait_time ( clock ) ) . min ( ) ;
584
587
if potential_sleep_time == Some ( Duration :: new ( 0 , 0 ) ) {
585
588
return Ok ( SchedulingAction :: ExecuteTimeoutCallback ) ;
586
589
}
@@ -615,7 +618,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
615
618
// All threads are currently blocked, but we have unexecuted
616
619
// timeout_callbacks, which may unblock some of the threads. Hence,
617
620
// sleep until the first callback.
618
- std:: thread:: sleep ( sleep_time) ;
621
+
622
+ clock. sleep ( sleep_time) ;
619
623
Ok ( SchedulingAction :: ExecuteTimeoutCallback )
620
624
} else {
621
625
throw_machine_stop ! ( TerminationInfo :: Deadlock ) ;
@@ -865,6 +869,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
865
869
callback : TimeoutCallback < ' mir , ' tcx > ,
866
870
) {
867
871
let this = self . eval_context_mut ( ) ;
872
+ if !this. machine . communicate ( ) && matches ! ( call_time, Time :: RealTime ( ..) ) {
873
+ panic ! ( "cannot have `RealTime` callback with isolation enabled!" )
874
+ }
868
875
this. machine . threads . register_timeout_callback ( thread, call_time, callback) ;
869
876
}
870
877
@@ -878,18 +885,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
878
885
#[ inline]
879
886
fn run_timeout_callback ( & mut self ) -> InterpResult < ' tcx > {
880
887
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
- } ;
888
+ let ( thread, callback) = if let Some ( ( thread, callback) ) =
889
+ this. machine . threads . get_ready_callback ( & this. machine . clock )
890
+ {
891
+ ( thread, callback)
892
+ } else {
893
+ // get_ready_callback can return None if the computer's clock
894
+ // was shifted after calling the scheduler and before the call
895
+ // to get_ready_callback (see issue
896
+ // https://github.com/rust-lang/miri/issues/1763). In this case,
897
+ // just do nothing, which effectively just returns to the
898
+ // scheduler.
899
+ return Ok ( ( ) ) ;
900
+ } ;
893
901
// This back-and-forth with `set_active_thread` is here because of two
894
902
// design decisions:
895
903
// 1. Make the caller and not the callback responsible for changing
@@ -906,7 +914,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
906
914
#[ inline]
907
915
fn schedule ( & mut self ) -> InterpResult < ' tcx , SchedulingAction > {
908
916
let this = self . eval_context_mut ( ) ;
909
- this. machine . threads . schedule ( )
917
+ this. machine . threads . schedule ( & this . machine . clock )
910
918
}
911
919
912
920
/// Handles thread termination of the active thread: wakes up threads joining on this one,
0 commit comments