Skip to content

Commit 1149eba

Browse files
committed
Fix HighresTime discontinuity on Windows
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. This just applies part of this commit: joyent/libuv@44ecaa7
1 parent 00ee933 commit 1149eba

File tree

1 file changed

+11
-13
lines changed

1 file changed

+11
-13
lines changed

src/luanode_hrtime.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,20 @@
3131
static const char HRTIME_MT[] = "luanode_hrtime_mt";
3232

3333
#if defined (_WIN32)
34-
/* The resolution of the high-resolution clock. */
35-
static boost::uint64_t uv_hrtime_frequency_ = 0;
34+
/* Frequency (ticks per nanosecond) of the high-resolution clock. */
35+
static double uv_hrtime_frequency_ = 0;
3636

3737
class hrtime_init {
3838
public:
3939
hrtime_init() {
40-
LARGE_INTEGER frequency;
40+
LARGE_INTEGER perf_frequency;
4141

42-
if (!::QueryPerformanceFrequency(&frequency)) {
42+
if (::QueryPerformanceFrequency(&perf_frequency)) {
43+
uv_hrtime_frequency_ = (double) perf_frequency.QuadPart / (double) NANOSEC;
44+
}
45+
else {
4346
uv_hrtime_frequency_ = 0;
44-
return;
4547
}
46-
47-
uv_hrtime_frequency_ = frequency.QuadPart;
4848
}
4949
};
5050

@@ -71,7 +71,7 @@ boost::uint64_t LuaNode::HighresTime::Get () {
7171
LARGE_INTEGER counter;
7272

7373
/* If the performance frequency is zero, there's no support. */
74-
if (!uv_hrtime_frequency_) {
74+
if (uv_hrtime_frequency_ == 0) {
7575
/* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */
7676
return 0;
7777
}
@@ -82,11 +82,9 @@ boost::uint64_t LuaNode::HighresTime::Get () {
8282
}
8383

8484
/* Because we have no guarantee about the order of magnitude of the */
85-
/* performance counter frequency, and there may not be much headroom to */
86-
/* multiply by NANOSEC without overflowing, we use 128-bit math instead. */
87-
return ((boost::uint64_t) counter.LowPart * NANOSEC / uv_hrtime_frequency_) +
88-
(((boost::uint64_t) counter.HighPart * NANOSEC / uv_hrtime_frequency_)
89-
<< 32);
85+
/* performance counter frequency, integer math could cause this computation */
86+
/* to overflow. Therefore we resort to floating point math. */
87+
return (boost::uint64_t) ((double) counter.QuadPart / uv_hrtime_frequency_);
9088
}
9189
#elif defined (__APPLE__)
9290
boost::uint64_t LuaNode::HighresTime::Get () {

0 commit comments

Comments
 (0)