On an i7-8700 CPU @ 3.20GHz running a kernel where CLOCK_MONOTONIC_RAW is handled by the vDSO it cuts the call cost from ~45ns to ~25ns.
Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/kernel32/kernel_main.c | 31 ----------------------- dlls/kernel32/time.c | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/dlls/kernel32/kernel_main.c b/dlls/kernel32/kernel_main.c index d3420ece06..7a0cc93b7d 100644 --- a/dlls/kernel32/kernel_main.c +++ b/dlls/kernel32/kernel_main.c @@ -179,37 +179,6 @@ INT WINAPI MulDiv( INT nMultiplicand, INT nMultiplier, INT nDivisor) }
-/****************************************************************************** - * GetTickCount64 (KERNEL32.@) - */ -ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) -{ - LARGE_INTEGER counter, frequency; - - NtQueryPerformanceCounter( &counter, &frequency ); - return counter.QuadPart * 1000 / frequency.QuadPart; -} - - -/*********************************************************************** - * GetTickCount (KERNEL32.@) - * - * Get the number of milliseconds the system has been running. - * - * PARAMS - * None. - * - * RETURNS - * The current tick count. - * - * NOTES - * The value returned will wrap around every 2^32 milliseconds. - */ -DWORD WINAPI DECLSPEC_HOTPATCH GetTickCount(void) -{ - return GetTickCount64(); -} - /****************************************************************************** * GetSystemRegistryQuota (KERNEL32.@) */ diff --git a/dlls/kernel32/time.c b/dlls/kernel32/time.c index b946aa177e..35472c2400 100644 --- a/dlls/kernel32/time.c +++ b/dlls/kernel32/time.c @@ -63,6 +63,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(time); #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)(60 * 60 * 24)) #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
+/* return a monotonic time counter, in Win32 ticks */ +static inline ULONGLONG monotonic_counter(void) +{ + LARGE_INTEGER counter; + +#ifdef __APPLE__ + static mach_timebase_info_data_t timebase; + + if (!timebase.denom) mach_timebase_info( &timebase ); + return mach_absolute_time() * timebase.numer / timebase.denom / 100; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec ts; +#ifdef CLOCK_MONOTONIC_RAW + if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) + return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; +#endif + if (!clock_gettime( CLOCK_MONOTONIC, &ts )) + return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; +#endif + NtQueryPerformanceCounter( &counter, NULL ); + return counter.QuadPart; +} + static const WCHAR mui_stdW[] = { 'M','U','I','_','S','t','d',0 }; static const WCHAR mui_dltW[] = { 'M','U','I','_','D','l','t',0 };
@@ -1571,3 +1594,30 @@ BOOL WINAPI QueryUnbiasedInterruptTime(ULONGLONG *time) RtlQueryUnbiasedInterruptTime(time); return TRUE; } + +/****************************************************************************** + * GetTickCount64 (KERNEL32.@) + */ +ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) +{ + return monotonic_counter() / 10000; +} + +/*********************************************************************** + * GetTickCount (KERNEL32.@) + * + * Get the number of milliseconds the system has been running. + * + * PARAMS + * None. + * + * RETURNS + * The current tick count. + * + * NOTES + * The value returned will wrap around every 2^32 milliseconds. + */ +DWORD WINAPI DECLSPEC_HOTPATCH GetTickCount(void) +{ + return monotonic_counter() / 10000; +}