From baaec11b91ada3955f57b7ec7e3e92e4e333e363 Mon Sep 17 00:00:00 2001 From: Orvid King Date: Mon, 14 Sep 2015 15:53:54 -0700 Subject: [PATCH] Implement clock_getres for Windows Summary: Because the windows version of pthread very definitely does not implement the clock. The Cygwin and MinGW headers might, so let them still fall back to the pthread includes. Closes https://github.com/facebook/folly/pull/280 Reviewed By: @yfeldblum Differential Revision: D2419067 Pulled By: @JoelMarcey --- folly/detail/Clock.cpp | 131 ++++++++++++++++++++++++++++++++++++++++- folly/detail/Clock.h | 7 ++- 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/folly/detail/Clock.cpp b/folly/detail/Clock.cpp index d44a81c0..855645c4 100644 --- a/folly/detail/Clock.cpp +++ b/folly/detail/Clock.cpp @@ -48,7 +48,136 @@ int clock_getres(clockid_t clk_id, struct timespec* ts) { return 0; } -#elif _MSC_VER +#elif defined(_MSC_VER) +// The MSVC version has been extracted from the pthreads implemenation here: +// https://github.com/songdongsheng/libpthread +// Copyright(c) 2011, Dongsheng Song +// +// It is under the Apache License Version 2.0, just as the rest of the file is. +// It has been mostly stripped down to what we have. + +#include + +#define DELTA_EPOCH_IN_100NS INT64_C(116444736000000000) +#define POW10_7 INT64_C(10000000) +#define POW10_9 INT64_C(1000000000) + +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + switch (clock_id) { + case CLOCK_MONOTONIC: + { + LARGE_INTEGER pf; + + if (QueryPerformanceFrequency(&pf) == 0) + return -1; + + res->tv_sec = 0; + res->tv_nsec = (int)((POW10_9 + (pf.QuadPart >> 1)) / pf.QuadPart); + if (res->tv_nsec < 1) + res->tv_nsec = 1; + + return 0; + } + + case CLOCK_REALTIME: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + { + DWORD timeAdjustment, timeIncrement; + BOOL isTimeAdjustmentDisabled; + + (void)GetSystemTimeAdjustment( + &timeAdjustment, + &timeIncrement, + &isTimeAdjustmentDisabled + ); + res->tv_sec = 0; + res->tv_nsec = timeIncrement * 100; + + return 0; + } + default: + break; + } + + return -1; +} + +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + unsigned __int64 t; + LARGE_INTEGER pf, pc; + union { + unsigned __int64 u64; + FILETIME ft; + } ct, et, kt, ut; + + switch (clock_id) { + case CLOCK_REALTIME: + { + GetSystemTimeAsFileTime(&ct.ft); + t = ct.u64 - DELTA_EPOCH_IN_100NS; + tp->tv_sec = t / POW10_7; + tp->tv_nsec = ((int)(t % POW10_7)) * 100; + + return 0; + } + + case CLOCK_MONOTONIC: + { + if (QueryPerformanceFrequency(&pf) == 0) + return -1; + + if (QueryPerformanceCounter(&pc) == 0) + return -1; + + tp->tv_sec = pc.QuadPart / pf.QuadPart; + tp->tv_nsec = (int)( + ((pc.QuadPart % pf.QuadPart) * POW10_9 + (pf.QuadPart >> 1)) / + pf.QuadPart + ); + if (tp->tv_nsec >= POW10_9) { + tp->tv_sec++; + tp->tv_nsec -= POW10_9; + } + + return 0; + } + + case CLOCK_PROCESS_CPUTIME_ID: + { + if (0 == GetProcessTimes(GetCurrentProcess(), + &ct.ft, &et.ft, &kt.ft, &ut.ft)) { + return -1; + } + t = kt.u64 + ut.u64; + tp->tv_sec = t / POW10_7; + tp->tv_nsec = ((int)(t % POW10_7)) * 100; + + return 0; + } + + case CLOCK_THREAD_CPUTIME_ID: + { + if (0 == GetThreadTimes(GetCurrentThread(), + &ct.ft, &et.ft, &kt.ft, &ut.ft)) { + return -1; + } + t = kt.u64 + ut.u64; + tp->tv_sec = t / POW10_7; + tp->tv_nsec = ((int)(t % POW10_7)) * 100; + + return 0; + } + + default: + break; + } + + return -1; +} +#elif defined(__CYGWIN__) || defined(__MINGW__) // using winpthreads from mingw-w64 // has clock_gettime and friends // make sure to include as well for typedefs of timespec/etc diff --git a/folly/detail/Clock.h b/folly/detail/Clock.h index de7130d3..a090b66b 100644 --- a/folly/detail/Clock.h +++ b/folly/detail/Clock.h @@ -28,12 +28,17 @@ #endif /* For windows, we'll use pthread's time implementations */ -#ifdef _MSC_VER +#if defined(__CYGWIN__) || defined(__MINGW__) #include #include #else typedef uint8_t clockid_t; #define CLOCK_REALTIME 0 +#ifdef _MSC_VER +#define CLOCK_MONOTONIC 1 +#define CLOCK_PROCESS_CPUTIME_ID 2 +#define CLOCK_THREAD_CPUTIME_ID 3 +#endif int clock_gettime(clockid_t clk_id, struct timespec* ts); int clock_getres(clockid_t clk_id, struct timespec* ts); -- 2.34.1