From 8625e57a6e10f41b50d6912d1f9205533bae16b6 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 30 Apr 2017 12:15:08 +0200 Subject: [PATCH] gettimeofday: Provide higher resolution on native Windows. * lib/gettimeofday.c: Don't include . (GetSystemTimePreciseAsFileTimeFuncType): New variable. (initialize): Initialize it. (gettimeofday) [WINDOWS_NATIVE]: Use it, and convert from FILETIME to 'struct timeval'. Don't use _ftime(). * m4/gettimeofday.m4 (gl_PREREQ_GETTIMEOFDAY): Don't test for and _ftime. --- ChangeLog | 11 ++++++++ lib/gettimeofday.c | 62 ++++++++++++++++++++++++++++++++++++++++------ m4/gettimeofday.m4 | 7 ++---- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 818d6e2422..69b8ae78ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2017-04-30 Bruno Haible + + gettimeofday: Provide higher resolution on native Windows. + * lib/gettimeofday.c: Don't include . + (GetSystemTimePreciseAsFileTimeFuncType): New variable. + (initialize): Initialize it. + (gettimeofday) [WINDOWS_NATIVE]: Use it, and convert from FILETIME to + 'struct timeval'. Don't use _ftime(). + * m4/gettimeofday.m4 (gl_PREREQ_GETTIMEOFDAY): Don't test for + and _ftime. + 2017-04-30 Bruno Haible Document the problem with the Cygwin environment variable TZ. diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c index d6117bd514..a4a71a7481 100644 --- a/lib/gettimeofday.c +++ b/lib/gettimeofday.c @@ -24,8 +24,9 @@ #include -#if HAVE_SYS_TIMEB_H -# include +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define WINDOWS_NATIVE +# include #endif #if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME @@ -92,6 +93,28 @@ rpl_tzset (void) tzset (); *localtime_buffer_addr = save; } + +#endif + +#ifdef WINDOWS_NATIVE + +/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ +typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); +static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL; +static BOOL initialized = FALSE; + +static void +initialize (void) +{ + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) + { + GetSystemTimePreciseAsFileTimeFunc = + (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime"); + } + initialized = TRUE; +} + #endif /* This is a wrapper for gettimeofday. It is used only on systems @@ -130,12 +153,35 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz) #else -# if HAVE__FTIME - - struct _timeb timebuf; - _ftime (&timebuf); - tv->tv_sec = timebuf.time; - tv->tv_usec = timebuf.millitm * 1000; +# ifdef WINDOWS_NATIVE + + /* On native Windows, there are two ways to get the current time: + GetSystemTimeAsFileTime + + or + GetSystemTimePreciseAsFileTime + . */ + FILETIME current_time; + + if (!initialized) + initialize (); + if (GetSystemTimePreciseAsFileTimeFunc != NULL) + GetSystemTimePreciseAsFileTimeFunc (¤t_time); + else + GetSystemTimeAsFileTime (¤t_time); + + /* Convert from FILETIME to 'struct timeval'. */ + /* FILETIME: */ + ULONGLONG since_1601 = + ((ULONGLONG) current_time.dwHighDateTime << 32) + | (ULONGLONG) current_time.dwLowDateTime; + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap + years, in total 134774 days. */ + ULONGLONG since_1970 = + since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000; + ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10; + tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000; + tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000; # else diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4 index 4f501e5bf9..742b6c9e10 100644 --- a/m4/gettimeofday.m4 +++ b/m4/gettimeofday.m4 @@ -1,4 +1,4 @@ -# serial 21 +# serial 22 # Copyright (C) 2001-2003, 2005, 2007, 2009-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -132,7 +132,4 @@ AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [ ]) # Prerequisites of lib/gettimeofday.c. -AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [ - AC_CHECK_HEADERS([sys/timeb.h]) - AC_CHECK_FUNCS([_ftime]) -]) +AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [:]) -- 2.39.5