--- src/unix/darwin.c +++ src/unix/darwin.c @@ -58,8 +58,16 @@ uint64_t uv__hrtime(uv_clocktype_t type) { + uint64_t t; uv_once(&once, uv__hrtime_init_once); - return mach_continuous_time() * timebase.numer / timebase.denom; + t = mach_continuous_time(); + /* On i386/x86_64/arm64 Macs timebase is 1/1 (or close), but on PowerPC the + * timebase runs at tens of MHz, making numer/denom ~= 1000000000/33333333: + * the naive t * numer overflows uint64_t after mere minutes of uptime, + * wrapping the clock backwards and starving every libuv timer. Split + * the scaling so no intermediate value can exceed 2^64. */ + return (t / timebase.denom) * timebase.numer + + (t % timebase.denom) * timebase.numer / timebase.denom; }