diff --git a/tokio/src/runtime/time/source.rs b/tokio/src/runtime/time/source.rs index e371c207cdb..e3ba8d790c0 100644 --- a/tokio/src/runtime/time/source.rs +++ b/tokio/src/runtime/time/source.rs @@ -22,9 +22,11 @@ impl TimeSource { pub(crate) fn instant_to_tick(&self, t: Instant) -> u64 { // round up let dur: Duration = t.saturating_duration_since(self.start_time); - let ms = dur.as_millis(); - - ms.try_into().unwrap_or(MAX_SAFE_MILLIS_DURATION) + let ms = dur + .as_millis() + .try_into() + .unwrap_or(MAX_SAFE_MILLIS_DURATION); + ms.min(MAX_SAFE_MILLIS_DURATION) } pub(crate) fn tick_to_duration(&self, t: u64) -> Duration { @@ -34,4 +36,10 @@ impl TimeSource { pub(crate) fn now(&self, clock: &Clock) -> u64 { self.instant_to_tick(clock.now()) } + + #[cfg(test)] + #[allow(dead_code)] + pub(super) fn start_time(&self) -> Instant { + self.start_time + } } diff --git a/tokio/src/runtime/time/tests/mod.rs b/tokio/src/runtime/time/tests/mod.rs index 676cf55f9c6..0e453433691 100644 --- a/tokio/src/runtime/time/tests/mod.rs +++ b/tokio/src/runtime/time/tests/mod.rs @@ -267,3 +267,17 @@ fn poll_process_levels_targeted() { handle.process_at_time(0, 192); handle.process_at_time(0, 192); } + +#[test] +#[cfg(not(loom))] +fn instant_to_tick_max() { + use crate::runtime::time::entry::MAX_SAFE_MILLIS_DURATION; + + let rt = rt(true); + let handle = rt.handle().inner.driver().time(); + + let start_time = handle.time_source.start_time(); + let long_future = start_time + std::time::Duration::from_millis(MAX_SAFE_MILLIS_DURATION + 1); + + assert!(handle.time_source.instant_to_tick(long_future) <= MAX_SAFE_MILLIS_DURATION); +}