Rollup merge of #22788 - vadimcn:fix-precise_time_ns, r=pnkfelix
which starts happening after ~2 hours of machine uptime. Closes #17845
This commit is contained in:
commit
fb92e312d9
@ -12,6 +12,8 @@ use ops::Sub;
|
||||
use time::Duration;
|
||||
use sync::{Once, ONCE_INIT};
|
||||
|
||||
const NANOS_PER_SEC: i64 = 1_000_000_000;
|
||||
|
||||
pub struct SteadyTime {
|
||||
t: libc::LARGE_INTEGER,
|
||||
}
|
||||
@ -24,7 +26,7 @@ impl SteadyTime {
|
||||
}
|
||||
|
||||
pub fn ns(&self) -> u64 {
|
||||
self.t as u64 * 1_000_000_000 / frequency() as u64
|
||||
mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,6 +47,27 @@ impl<'a> Sub for &'a SteadyTime {
|
||||
|
||||
fn sub(self, other: &SteadyTime) -> Duration {
|
||||
let diff = self.t as i64 - other.t as i64;
|
||||
Duration::microseconds(diff * 1_000_000 / frequency() as i64)
|
||||
Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64))
|
||||
}
|
||||
}
|
||||
|
||||
// Computes (value*numer)/denom without overflow, as long as both
|
||||
// (numer*denom) and the overall result fit into i64 (which is the case
|
||||
// for our time conversions).
|
||||
fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
|
||||
let q = value / denom;
|
||||
let r = value % denom;
|
||||
// Decompose value as (value/denom*denom + value%denom),
|
||||
// substitute into (value*numer)/denom and simplify.
|
||||
// r < denom, so (denom*numer) is the upper bound of (r*numer)
|
||||
q * numer + r * numer / denom
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_muldiv() {
|
||||
assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000), 1_000_000_000_001_000);
|
||||
assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000);
|
||||
assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000), 1_000_000_000_001_000);
|
||||
assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000);
|
||||
assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000), 1_000_000_000_001_000);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user