First attempt

This commit is contained in:
tiif 2024-06-07 22:07:49 +08:00
parent 773415d28f
commit 844450ae3a
2 changed files with 34 additions and 7 deletions

View File

@ -6,7 +6,7 @@
/// This number is pretty random, but it has been shown to approximately cause /// 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. /// some sample programs to run within an order of magnitude of real time on desktop CPUs.
/// (See `tests/pass/shims/time-with-isolation*.rs`.) /// (See `tests/pass/shims/time-with-isolation*.rs`.)
const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000; const NANOSECONDS_PER_BASIC_BLOCK: u128 = 5000;
#[derive(Debug)] #[derive(Debug)]
pub struct Instant { pub struct Instant {
@ -16,7 +16,7 @@ pub struct Instant {
#[derive(Debug)] #[derive(Debug)]
enum InstantKind { enum InstantKind {
Host(StdInstant), Host(StdInstant),
Virtual { nanoseconds: u64 }, Virtual { nanoseconds: u128 },
} }
impl Instant { impl Instant {
@ -25,9 +25,8 @@ pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
InstantKind::Host(instant) => InstantKind::Host(instant) =>
instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }), instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }),
InstantKind::Virtual { nanoseconds } => InstantKind::Virtual { nanoseconds } =>
u128::from(nanoseconds) nanoseconds
.checked_add(duration.as_nanos()) .checked_add(duration.as_nanos())
.and_then(|n| u64::try_from(n).ok())
.map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }), .map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }),
} }
} }
@ -39,7 +38,19 @@ pub fn duration_since(&self, earlier: Instant) -> Duration {
( (
InstantKind::Virtual { nanoseconds }, InstantKind::Virtual { nanoseconds },
InstantKind::Virtual { nanoseconds: earlier }, InstantKind::Virtual { nanoseconds: earlier },
) => Duration::from_nanos(nanoseconds.saturating_sub(earlier)), ) => {
// Trade some nanosecond precision to prevent as much overflow as possible.
let duration = match u64::try_from(
// Manually convert from nanosecond to millisecond.
// If it exceeded u64::MAX millisecond, we will just use u64::MAX millisecond,
// Duration can't take in more than u64::MAX millisecond.
nanoseconds.saturating_sub(earlier).saturating_div(1_000_000),
) {
Ok(millisecond) => Duration::from_millis(millisecond),
_ => Duration::from_millis(u64::MAX),
};
Duration::new(duration.as_secs(), duration.subsec_nanos())
}
_ => panic!("all `Instant` must be of the same kind"), _ => panic!("all `Instant` must be of the same kind"),
} }
} }
@ -59,7 +70,7 @@ enum ClockKind {
}, },
Virtual { Virtual {
/// The "current virtual time". /// The "current virtual time".
nanoseconds: Cell<u64>, nanoseconds: Cell<u128>,
}, },
} }
@ -93,7 +104,7 @@ pub fn sleep(&self, duration: Duration) {
ClockKind::Host { .. } => std::thread::sleep(duration), ClockKind::Host { .. } => std::thread::sleep(duration),
ClockKind::Virtual { nanoseconds } => { ClockKind::Virtual { nanoseconds } => {
// Just pretend that we have slept for some time. // Just pretend that we have slept for some time.
let nanos: u64 = duration.as_nanos().try_into().unwrap(); let nanos: u128 = duration.as_nanos().try_into().unwrap();
nanoseconds.update(|x| x + nanos); nanoseconds.update(|x| x + nanos);
} }
} }

View File

@ -280,7 +280,23 @@ fn concurrent_wait_wake() {
assert!(woken > 0 && woken < rounds); assert!(woken > 0 && woken < rounds);
} }
// Reproduce of https://github.com/rust-lang/miri/issues/3647.
fn large_timeout() {
let futex: i32 = 123;
unsafe {
libc::syscall(
libc::SYS_futex,
addr_of!(futex),
libc::FUTEX_WAIT,
123,
&libc::timespec { tv_sec: 184467440839020, tv_nsec: 117558982 },
);
}
}
fn main() { fn main() {
large_timeout();
wake_nobody(); wake_nobody();
wake_dangling(); wake_dangling();
wait_wrong_val(); wait_wrong_val();