[PATCH 6/7] kernel32: Implement GetTickCount() directly.

Huw Davies huw at codeweavers.com
Thu May 2 03:45:21 CDT 2019


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 at 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;
+}
-- 
2.17.1




More information about the wine-devel mailing list