windows/timer: fix uv_hrtime discontinuity
Large performance counter frequency values would cause overflows, even when 64-bit integers were used to do the multiplication with NANOSEC. Fix this by using floating point math instead. Fixes #850
This commit is contained in:
parent
5812e19bf6
commit
44ecaa7c98
@ -59,20 +59,24 @@
|
||||
static char *process_title;
|
||||
static CRITICAL_SECTION process_title_lock;
|
||||
|
||||
/* The tick frequency of the high-resolution clock. */
|
||||
static uint64_t hrtime_frequency_ = 0;
|
||||
/* Frequency (ticks per nanosecond) of the high-resolution clock. */
|
||||
static double hrtime_frequency_ = 0;
|
||||
|
||||
|
||||
/*
|
||||
* One-time intialization code for functionality defined in util.c.
|
||||
*/
|
||||
void uv__util_init() {
|
||||
LARGE_INTEGER perf_frequency;
|
||||
|
||||
/* Initialize process title access mutex. */
|
||||
InitializeCriticalSection(&process_title_lock);
|
||||
|
||||
/* Retrieve high-resolution timer frequency. */
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER*) &hrtime_frequency_))
|
||||
hrtime_frequency_ = 0;
|
||||
if (QueryPerformanceFrequency(&perf_frequency))
|
||||
hrtime_frequency_ = (double) perf_frequency.QuadPart / (double) NANOSEC;
|
||||
else
|
||||
hrtime_frequency_= 0;
|
||||
}
|
||||
|
||||
|
||||
@ -447,7 +451,7 @@ uint64_t uv_hrtime(void) {
|
||||
uv__once_init();
|
||||
|
||||
/* If the performance frequency is zero, there's no support. */
|
||||
if (!hrtime_frequency_) {
|
||||
if (hrtime_frequency_ == 0) {
|
||||
/* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */
|
||||
return 0;
|
||||
}
|
||||
@ -457,12 +461,11 @@ uint64_t uv_hrtime(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Because we have no guarantee about the order of magnitude of the */
|
||||
/* performance counter frequency, and there may not be much headroom to */
|
||||
/* multiply by NANOSEC without overflowing, we use 128-bit math instead. */
|
||||
return ((uint64_t) counter.LowPart * NANOSEC / hrtime_frequency_) +
|
||||
(((uint64_t) counter.HighPart * NANOSEC / hrtime_frequency_)
|
||||
<< 32);
|
||||
/* Because we have no guarantee about the order of magnitude of the
|
||||
* performance counter frequency, integer math could cause this computation
|
||||
* to overflow. Therefore we resort to floating point math.
|
||||
*/
|
||||
return (uint64_t) ((double) counter.QuadPart / hrtime_frequency_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user