diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs index fd0c121626b..3f86767277a 100644 --- a/src/tools/miri/src/clock.rs +++ b/src/tools/miri/src/clock.rs @@ -6,7 +6,7 @@ use std::time::{Duration, Instant as StdInstant}; /// This number is pretty random, but it has been shown to approximately cause /// some sample programs to run within an order of magnitude of real time on desktop CPUs. /// (See `tests/pass/shims/time-with-isolation*.rs`.) -const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000; +const NANOSECONDS_PER_BASIC_BLOCK: u128 = 5000; #[derive(Debug)] pub struct Instant { @@ -16,7 +16,7 @@ pub struct Instant { #[derive(Debug)] enum InstantKind { Host(StdInstant), - Virtual { nanoseconds: u64 }, + Virtual { nanoseconds: u128 }, } impl Instant { @@ -25,9 +25,8 @@ impl Instant { InstantKind::Host(instant) => instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }), InstantKind::Virtual { nanoseconds } => - u128::from(nanoseconds) + nanoseconds .checked_add(duration.as_nanos()) - .and_then(|n| u64::try_from(n).ok()) .map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }), } } @@ -39,7 +38,17 @@ impl Instant { ( InstantKind::Virtual { nanoseconds }, InstantKind::Virtual { nanoseconds: earlier }, - ) => Duration::from_nanos(nanoseconds.saturating_sub(earlier)), + ) => { + let duration = nanoseconds.saturating_sub(earlier); + // `Duration` does not provide a nice constructor from a `u128` of nanoseconds, + // so we have to implement this ourselves. + // It is possible for second to overflow because u64::MAX < (u128::MAX / 1e9). + // It will be saturated to u64::MAX seconds if the value after division exceeds u64::MAX. + let seconds = u64::try_from(duration / 1_000_000_000).unwrap_or(u64::MAX); + // It is impossible for nanosecond to overflow because u32::MAX > 1e9. + let nanosecond = u32::try_from(duration.wrapping_rem(1_000_000_000)).unwrap(); + Duration::new(seconds, nanosecond) + } _ => panic!("all `Instant` must be of the same kind"), } } @@ -59,7 +68,7 @@ enum ClockKind { }, Virtual { /// The "current virtual time". - nanoseconds: Cell, + nanoseconds: Cell, }, } @@ -93,8 +102,11 @@ impl Clock { ClockKind::Host { .. } => std::thread::sleep(duration), ClockKind::Virtual { nanoseconds } => { // Just pretend that we have slept for some time. - let nanos: u64 = duration.as_nanos().try_into().unwrap(); - nanoseconds.update(|x| x + nanos); + let nanos: u128 = duration.as_nanos(); + nanoseconds.update(|x| { + x.checked_add(nanos) + .expect("Miri's virtual clock cannot represent an execution this long") + }); } } }