Skip to content

Commit 844450a

Browse files
committed
First attempt
1 parent 773415d commit 844450a

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

src/tools/miri/src/clock.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::time::{Duration, Instant as StdInstant};
66
/// This number is pretty random, but it has been shown to approximately cause
77
/// some sample programs to run within an order of magnitude of real time on desktop CPUs.
88
/// (See `tests/pass/shims/time-with-isolation*.rs`.)
9-
const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000;
9+
const NANOSECONDS_PER_BASIC_BLOCK: u128 = 5000;
1010

1111
#[derive(Debug)]
1212
pub struct Instant {
@@ -16,7 +16,7 @@ pub struct Instant {
1616
#[derive(Debug)]
1717
enum InstantKind {
1818
Host(StdInstant),
19-
Virtual { nanoseconds: u64 },
19+
Virtual { nanoseconds: u128 },
2020
}
2121

2222
impl Instant {
@@ -25,9 +25,8 @@ impl Instant {
2525
InstantKind::Host(instant) =>
2626
instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }),
2727
InstantKind::Virtual { nanoseconds } =>
28-
u128::from(nanoseconds)
28+
nanoseconds
2929
.checked_add(duration.as_nanos())
30-
.and_then(|n| u64::try_from(n).ok())
3130
.map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }),
3231
}
3332
}
@@ -39,7 +38,19 @@ impl Instant {
3938
(
4039
InstantKind::Virtual { nanoseconds },
4140
InstantKind::Virtual { nanoseconds: earlier },
42-
) => Duration::from_nanos(nanoseconds.saturating_sub(earlier)),
41+
) => {
42+
// Trade some nanosecond precision to prevent as much overflow as possible.
43+
let duration = match u64::try_from(
44+
// Manually convert from nanosecond to millisecond.
45+
// If it exceeded u64::MAX millisecond, we will just use u64::MAX millisecond,
46+
// Duration can't take in more than u64::MAX millisecond.
47+
nanoseconds.saturating_sub(earlier).saturating_div(1_000_000),
48+
) {
49+
Ok(millisecond) => Duration::from_millis(millisecond),
50+
_ => Duration::from_millis(u64::MAX),
51+
};
52+
Duration::new(duration.as_secs(), duration.subsec_nanos())
53+
}
4354
_ => panic!("all `Instant` must be of the same kind"),
4455
}
4556
}
@@ -59,7 +70,7 @@ enum ClockKind {
5970
},
6071
Virtual {
6172
/// The "current virtual time".
62-
nanoseconds: Cell<u64>,
73+
nanoseconds: Cell<u128>,
6374
},
6475
}
6576

@@ -93,7 +104,7 @@ impl Clock {
93104
ClockKind::Host { .. } => std::thread::sleep(duration),
94105
ClockKind::Virtual { nanoseconds } => {
95106
// Just pretend that we have slept for some time.
96-
let nanos: u64 = duration.as_nanos().try_into().unwrap();
107+
let nanos: u128 = duration.as_nanos().try_into().unwrap();
97108
nanoseconds.update(|x| x + nanos);
98109
}
99110
}

src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,23 @@ fn concurrent_wait_wake() {
280280
assert!(woken > 0 && woken < rounds);
281281
}
282282

283+
// Reproduce of https://github.com/rust-lang/miri/issues/3647.
284+
fn large_timeout() {
285+
let futex: i32 = 123;
286+
287+
unsafe {
288+
libc::syscall(
289+
libc::SYS_futex,
290+
addr_of!(futex),
291+
libc::FUTEX_WAIT,
292+
123,
293+
&libc::timespec { tv_sec: 184467440839020, tv_nsec: 117558982 },
294+
);
295+
}
296+
}
297+
283298
fn main() {
299+
large_timeout();
284300
wake_nobody();
285301
wake_dangling();
286302
wait_wrong_val();

0 commit comments

Comments
 (0)