On an i7-8700 CPU @ 3.20GHz with HZ=1000 it cuts the call cost from ~18ns to ~12ns.
Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/kernel32/time.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/time.c b/dlls/kernel32/time.c index 41742894dd..6516bca972 100644 --- a/dlls/kernel32/time.c +++ b/dlls/kernel32/time.c @@ -59,6 +59,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(time); #define FILETIME2LL( pft, ll) \ ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
+#define TICKSPERSEC 10000000 +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)(60 * 60 * 24)) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) + static const WCHAR mui_stdW[] = { 'M','U','I','_','S','t','d',0 }; static const WCHAR mui_dltW[] = { 'M','U','I','_','D','l','t',0 };
@@ -764,7 +768,38 @@ void WINAPI GetSystemTimeAsFileTime( FILETIME *time ) { LARGE_INTEGER t;
- NtQuerySystemTime( &t ); +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */ + + if (clock_id == CLOCK_MONOTONIC) + { +#ifdef CLOCK_REALTIME_COARSE + struct timespec res; + + /* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */ + if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000) + clock_id = CLOCK_REALTIME_COARSE; + else +#endif /* CLOCK_REALTIME_COARSE */ + clock_id = CLOCK_REALTIME; + } + + if (!clock_gettime( clock_id, &ts )) + { + t.QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; + t.QuadPart += (ts.tv_nsec + 50) / 100; + } + else +#endif /* HAVE_CLOCK_GETTIME */ + { + struct timeval now; + + gettimeofday( &now, 0 ); + t.QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; + t.QuadPart += now.tv_usec * 10; + } + time->dwLowDateTime = t.u.LowPart; time->dwHighDateTime = t.u.HighPart; }
Huw Davies huw@codeweavers.com writes:
@@ -764,7 +768,38 @@ void WINAPI GetSystemTimeAsFileTime( FILETIME *time ) { LARGE_INTEGER t;
- NtQuerySystemTime( &t );
+#ifdef HAVE_CLOCK_GETTIME
- struct timespec ts;
- static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */
- if (clock_id == CLOCK_MONOTONIC)
- {
+#ifdef CLOCK_REALTIME_COARSE
struct timespec res;
/* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */
if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000)
clock_id = CLOCK_REALTIME_COARSE;
else
+#endif /* CLOCK_REALTIME_COARSE */
clock_id = CLOCK_REALTIME;
- }
- if (!clock_gettime( clock_id, &ts ))
- {
t.QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
t.QuadPart += (ts.tv_nsec + 50) / 100;
- }
- else
+#endif /* HAVE_CLOCK_GETTIME */
- {
struct timeval now;
gettimeofday( &now, 0 );
t.QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
t.QuadPart += now.tv_usec * 10;
- }
Do we really need to duplicate the entire thing?
If the extra call to ntdll is really that expensive, you could probably forward to it instead.
On Tue, May 14, 2019 at 08:31:29PM +0200, Alexandre Julliard wrote:
If the extra call to ntdll is really that expensive, you could probably forward to it instead.
Ah, nice. I've sent in a series that does that.
For GetTickCount64() I could do the same thing, but it would mean changing NtGetTickCount() to return a ULONGLONG. This should be fine as callers will just ignore the upper 32-bits (and hopefully there's nothing out there that relies on the wrapping). Is that ok?
I don't care too much about the changes I made to QueryPerformanceCounter(), that's a higher accuracy timer so can afford to be slower.
Huw.