From 055746f501699057db7ec353e19778064da5e084 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 11 May 2017 21:38:28 +0200 Subject: [PATCH] gettimeofday: Increase precision on mingw. * m4/gettimeofday.m4 (gl_FUNC_GETTIMEOFDAY): Require AC_CANONICAL_HOST. Set REPLACE_GETTIMEOFDAY to 1 on mingw. * lib/gettimeofday.c (gettimeofday): On native Windows, use the GetSystemTimePreciseAsFileTime based implementation always. * doc/posix-functions/gettimeofday.texi: Mention precision problem on mingw. --- ChangeLog | 10 ++++ doc/posix-functions/gettimeofday.texi | 5 +- lib/gettimeofday.c | 71 +++++++++++++++------------ m4/gettimeofday.m4 | 10 +++- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7f9c88f01..0da6a99175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2017-05-11 Bruno Haible + + gettimeofday: Increase precision on mingw. + * m4/gettimeofday.m4 (gl_FUNC_GETTIMEOFDAY): Require AC_CANONICAL_HOST. + Set REPLACE_GETTIMEOFDAY to 1 on mingw. + * lib/gettimeofday.c (gettimeofday): On native Windows, use the + GetSystemTimePreciseAsFileTime based implementation always. + * doc/posix-functions/gettimeofday.texi: Mention precision problem on + mingw. + 2017-05-11 Bruno Haible poll: Fix confusion between SOCKETs and FDs on native Windows. diff --git a/doc/posix-functions/gettimeofday.texi b/doc/posix-functions/gettimeofday.texi index 6fe62a66b5..758cc9dcf0 100644 --- a/doc/posix-functions/gettimeofday.texi +++ b/doc/posix-functions/gettimeofday.texi @@ -10,7 +10,7 @@ Portability problems fixed by Gnulib: @itemize @item This function is missing on some platforms: -mingw, MSVC 9. +MSVC 9. @item This function is declared with a nonstandard function prototype (only one argument, or ``...'' after the first argument) on some platforms. @@ -27,6 +27,9 @@ appropriate type for use in avoiding a compiler warning if assigning On some platforms, @code{gettimeofday} clobbers the buffer in which @code{localtime} returns its result: Mac OS X 10.0. +@item +This function has only a precision of 15.6 milliseconds on some platforms: +mingw. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c index 0d64885026..14213da462 100644 --- a/lib/gettimeofday.c +++ b/lib/gettimeofday.c @@ -64,42 +64,20 @@ int gettimeofday (struct timeval *restrict tv, void *restrict tz) { #undef gettimeofday -#if HAVE_GETTIMEOFDAY -# if GETTIMEOFDAY_CLOBBERS_LOCALTIME - /* Save and restore the contents of the buffer used for localtime's - result around the call to gettimeofday. */ - struct tm save = *localtime_buffer_addr; -# endif - -# if defined timeval /* 'struct timeval' overridden by gnulib? */ -# undef timeval - struct timeval otv; - int result = gettimeofday (&otv, (struct timezone *) tz); - if (result == 0) - { - tv->tv_sec = otv.tv_sec; - tv->tv_usec = otv.tv_usec; - } -# else - int result = gettimeofday (tv, (struct timezone *) tz); -# endif - -# if GETTIMEOFDAY_CLOBBERS_LOCALTIME - *localtime_buffer_addr = save; -# endif - - return result; - -#else - -# ifdef WINDOWS_NATIVE +#ifdef WINDOWS_NATIVE /* On native Windows, there are two ways to get the current time: GetSystemTimeAsFileTime or GetSystemTimePreciseAsFileTime - . */ + . + GetSystemTimeAsFileTime produces values that jump by increments of + 15.627 milliseconds (!) on average. + Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2 + microseconds. + More discussion on this topic: + . */ FILETIME current_time; if (!initialized) @@ -122,6 +100,36 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz) tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000; tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000; + return 0; + +#else + +# if HAVE_GETTIMEOFDAY +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + /* Save and restore the contents of the buffer used for localtime's + result around the call to gettimeofday. */ + struct tm save = *localtime_buffer_addr; +# endif + +# if defined timeval /* 'struct timeval' overridden by gnulib? */ +# undef timeval + struct timeval otv; + int result = gettimeofday (&otv, (struct timezone *) tz); + if (result == 0) + { + tv->tv_sec = otv.tv_sec; + tv->tv_usec = otv.tv_usec; + } +# else + int result = gettimeofday (tv, (struct timezone *) tz); +# endif + +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + *localtime_buffer_addr = save; +# endif + + return result; + # else # if !defined OK_TO_USE_1S_CLOCK @@ -131,9 +139,8 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz) tv->tv_sec = time (NULL); tv->tv_usec = 0; -# endif - return 0; +# endif #endif } diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4 index 34adc64778..8ee206eea2 100644 --- a/m4/gettimeofday.m4 +++ b/m4/gettimeofday.m4 @@ -1,4 +1,4 @@ -# serial 22 +# serial 23 # Copyright (C) 2001-2003, 2005, 2007, 2009-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -9,9 +9,10 @@ dnl From Jim Meyering. AC_DEFUN([gl_FUNC_GETTIMEOFDAY], [ + AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([gl_HEADER_SYS_TIME_H]) - AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS]) AC_CHECK_FUNCS_ONCE([gettimeofday]) gl_gettimeofday_timezone=void @@ -54,6 +55,11 @@ int gettimeofday (struct timeval *restrict, struct timezone *restrict); if test $REPLACE_STRUCT_TIMEVAL = 1; then REPLACE_GETTIMEOFDAY=1 fi + dnl On mingw, the original gettimeofday has only a precision of 15.6 + dnl milliseconds. So override it. + case "$host_os" in + mingw*) REPLACE_GETTIMEOFDAY=1 ;; + esac fi AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone], [Define this to 'void' or 'struct timezone' to match the system's -- 2.39.5