Bruno Haible
2017-05-11 19:45:44 UTC
Comparison of the two gettimeofday implementations on native Windows:
* The mingw one, based on GetSystemTimeAsFileTime, produces values
that jump by 15.627 milliseconds on average:
delta
1494528421.290102
1494528421.305729 15627
1494528421.321355 15626
1494528421.337009 15654
1494528421.352608 15599
1494528421.368235 15627
1494528421.383861 15626
1494528421.399492 15631
1494528421.415118 15626
* The gnulib one, based on GetSystemTimePreciseAsFileTime, produces
values that jump by 1 or 2 microseconds on average.
(I measured this on Windows 10.) So, it's an improvement to use the
gnulib implementation even though the mingw one is strictly POSIX compliant.
2017-05-11 Bruno Haible <***@clisp.org>
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.
diff --git a/doc/posix-functions/gettimeofday.texi b/doc/posix-functions/gettimeofday.texi
index 6fe62a6..758cc9d 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 0d64885..14213da 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
<https://msdn.microsoft.com/en-us/library/ms724397.aspx>
or
GetSystemTimePreciseAsFileTime
- <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */
+ <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.
+ 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:
+ <http://www.windowstimestamp.com/description>. */
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 34adc64..8ee206e 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
* The mingw one, based on GetSystemTimeAsFileTime, produces values
that jump by 15.627 milliseconds on average:
delta
1494528421.290102
1494528421.305729 15627
1494528421.321355 15626
1494528421.337009 15654
1494528421.352608 15599
1494528421.368235 15627
1494528421.383861 15626
1494528421.399492 15631
1494528421.415118 15626
* The gnulib one, based on GetSystemTimePreciseAsFileTime, produces
values that jump by 1 or 2 microseconds on average.
(I measured this on Windows 10.) So, it's an improvement to use the
gnulib implementation even though the mingw one is strictly POSIX compliant.
2017-05-11 Bruno Haible <***@clisp.org>
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.
diff --git a/doc/posix-functions/gettimeofday.texi b/doc/posix-functions/gettimeofday.texi
index 6fe62a6..758cc9d 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 0d64885..14213da 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
<https://msdn.microsoft.com/en-us/library/ms724397.aspx>
or
GetSystemTimePreciseAsFileTime
- <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */
+ <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.
+ 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:
+ <http://www.windowstimestamp.com/description>. */
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 34adc64..8ee206e 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