@@ -407,7 +407,7 @@ impl VisitProvenance for Frame<'_, Provenance, FrameExtra<'_>> {
407
407
408
408
/// The moment in time when a blocked thread should be woken up.
409
409
#[ derive( Debug ) ]
410
- pub enum Timeout {
410
+ enum Timeout {
411
411
Monotonic ( Instant ) ,
412
412
RealTime ( SystemTime ) ,
413
413
}
@@ -421,6 +421,34 @@ impl Timeout {
421
421
time. duration_since ( SystemTime :: now ( ) ) . unwrap_or ( Duration :: ZERO ) ,
422
422
}
423
423
}
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 ,
424
452
}
425
453
426
454
/// A set of threads.
@@ -995,13 +1023,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
995
1023
fn block_thread (
996
1024
& mut self ,
997
1025
reason : BlockReason ,
998
- timeout : Option < Timeout > ,
1026
+ timeout : Option < ( TimeoutClock , TimeoutAnchor , Duration ) > ,
999
1027
callback : impl UnblockCallback < ' tcx > + ' tcx ,
1000
1028
) {
1001
1029
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
+ } ) ;
1005
1050
this. machine . threads . block_thread ( reason, timeout, callback) ;
1006
1051
}
1007
1052
0 commit comments