summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel P <pavlov.pavel@gmail.com>2018-11-26 15:10:10 -0800
committerJay Satiro <raysatiro@yahoo.com>2018-12-23 02:30:37 -0500
commite9ababd4f5aff042dd3b5a4f9568f22e6604d115 (patch)
tree57d2927109db050fa429e5e78fee5045e085edcd
parentc98ee5f67f497195c9127cc70fa53a487f994cd5 (diff)
downloadcurl-e9ababd4f5aff042dd3b5a4f9568f22e6604d115.tar.gz
timeval: Use high resolution timestamps on Windows
- Use QueryPerformanceCounter on Windows Vista+ There is confusing info floating around that QueryPerformanceCounter can leap etc, which might have been true long time ago, but no longer the case nowadays (perhaps starting from WinXP?). Also, boost and std::chrono::steady_clock use QueryPerformanceCounter in a similar way. Prior to this change GetTickCount or GetTickCount64 was used, which has lower resolution. That is still the case for <= XP. Fixes https://github.com/curl/curl/issues/3309 Closes https://github.com/curl/curl/pull/3318
-rw-r--r--lib/timeval.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/lib/timeval.c b/lib/timeval.c
index dce1a761e..2d7c782fa 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -21,29 +21,36 @@
***************************************************************************/
#include "timeval.h"
+#include "system_win32.h"
#if defined(WIN32) && !defined(MSDOS)
struct curltime Curl_now(void)
{
- /*
- ** GetTickCount() is available on _all_ Windows versions from W95 up
- ** to nowadays. Returns milliseconds elapsed since last system boot,
- ** increases monotonically and wraps once 49.7 days have elapsed.
- */
struct curltime now;
-#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
- (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
- (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
- DWORD milliseconds = GetTickCount();
- now.tv_sec = milliseconds / 1000;
- now.tv_usec = (milliseconds % 1000) * 1000;
-#else
- ULONGLONG milliseconds = GetTickCount64();
- now.tv_sec = (time_t) (milliseconds / 1000);
- now.tv_usec = (unsigned int) (milliseconds % 1000) * 1000;
-#endif
-
+ static LARGE_INTEGER freq;
+ static int isVistaOrGreater = -1;
+ if(isVistaOrGreater == -1) {
+ if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ isVistaOrGreater = 1;
+ QueryPerformanceFrequency(&freq);
+ }
+ else
+ isVistaOrGreater = 0;
+ }
+ if(isVistaOrGreater == 1) { /* QPC timer might have issues pre-Vista */
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+ now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
+ now.tv_usec =
+ (int)((count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart);
+ }
+ else {
+ DWORD milliseconds = GetTickCount();
+ now.tv_sec = milliseconds / 1000;
+ now.tv_usec = (milliseconds % 1000) * 1000;
+ }
return now;
}