std: Fix early overflow in time calculation

Closes #6867
This commit is contained in:
LemonBoy 2020-10-30 19:30:02 +01:00 committed by Andrew Kelley
parent 2e1cef7508
commit 445d808bae

View File

@ -242,15 +242,24 @@ pub const Timer = struct {
fn nativeDurationToNanos(self: Timer, duration: u64) u64 { fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
if (is_windows) { if (is_windows) {
return @divFloor(duration * ns_per_s, self.frequency); return safeMulDiv(duration, ns_per_s, self.frequency);
} }
if (comptime std.Target.current.isDarwin()) { if (comptime std.Target.current.isDarwin()) {
return @divFloor(duration * self.frequency.numer, self.frequency.denom); return safeMulDiv(duration, self.frequency.numer, self.frequency.denom);
} }
return duration; return duration;
} }
}; };
// Calculate (a * b) / c without risk of overflowing too early because of the
// multiplication.
fn safeMulDiv(a: u64, b: u64, c: u64) u64 {
const q = a / c;
const r = a % c;
// (a * b) / c == (a / c) * b + ((a % c) * b) / c
return (q * b) + (r * b) / c;
}
test "sleep" { test "sleep" {
sleep(1); sleep(1);
} }