@@ -407,7 +407,7 @@ impl VisitProvenance for Frame<'_, Provenance, FrameExtra<'_>> {
407407
408408/// The moment in time when a blocked thread should be woken up.
409409#[ derive( Debug ) ]
410- pub enum Timeout {
410+ enum Timeout {
411411 Monotonic ( Instant ) ,
412412 RealTime ( SystemTime ) ,
413413}
@@ -421,6 +421,34 @@ impl Timeout {
421421 time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: ZERO ) ,
422422 }
423423 }
424+
425+ /// Will try to add `duration`, but if that overflows it may add less.
426+ fn add_lossy ( & self , duration : Duration ) -> Self {
427+ match self {
428+ Timeout :: Monotonic ( i) => Timeout :: Monotonic ( i. add_lossy ( duration) ) ,
429+ Timeout :: RealTime ( s) => {
430+ // If this overflows, try adding just 1h and assume that will not overflow.
431+ Timeout :: RealTime (
432+ s. checked_add ( duration)
433+ . unwrap_or_else ( || s. checked_add ( Duration :: from_secs ( 3600 ) ) . unwrap ( ) ) ,
434+ )
435+ }
436+ }
437+ }
438+ }
439+
440+ /// The clock to use for the timeout you are asking for.
441+ #[ derive( Debug , Copy , Clone ) ]
442+ pub enum TimeoutClock {
443+ Monotonic ,
444+ RealTime ,
445+ }
446+
447+ /// Whether the timeout is relative or absolute.
448+ #[ derive( Debug , Copy , Clone ) ]
449+ pub enum TimeoutAnchor {
450+ Relative ,
451+ Absolute ,
424452}
425453
426454/// A set of threads.
@@ -995,13 +1023,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9951023 fn block_thread (
9961024 & mut self ,
9971025 reason : BlockReason ,
998- timeout : Option < Timeout > ,
1026+ timeout : Option < ( TimeoutClock , TimeoutAnchor , Duration ) > ,
9991027 callback : impl UnblockCallback < ' tcx > + ' tcx ,
10001028 ) {
10011029 let this = self . eval_context_mut ( ) ;
1002- if !this. machine . communicate ( ) && matches ! ( timeout, Some ( Timeout :: RealTime ( ..) ) ) {
1003- panic ! ( "cannot have `RealTime` callback with isolation enabled!" )
1004- }
1030+ let timeout = timeout. map ( |( clock, anchor, duration) | {
1031+ let anchor = match clock {
1032+ TimeoutClock :: RealTime => {
1033+ assert ! (
1034+ this. machine. communicate( ) ,
1035+ "cannot have `RealTime` timeout with isolation enabled!"
1036+ ) ;
1037+ Timeout :: RealTime ( match anchor {
1038+ TimeoutAnchor :: Absolute => SystemTime :: UNIX_EPOCH ,
1039+ TimeoutAnchor :: Relative => SystemTime :: now ( ) ,
1040+ } )
1041+ }
1042+ TimeoutClock :: Monotonic =>
1043+ Timeout :: Monotonic ( match anchor {
1044+ TimeoutAnchor :: Absolute => this. machine . clock . epoch ( ) ,
1045+ TimeoutAnchor :: Relative => this. machine . clock . now ( ) ,
1046+ } ) ,
1047+ } ;
1048+ anchor. add_lossy ( duration)
1049+ } ) ;
10051050 this. machine . threads . block_thread ( reason, timeout, callback) ;
10061051 }
10071052
0 commit comments