* lib/gettime-res.c, modules/gettime-res: New files. * lib/timespec.h (gettime_res): New decl. * m4/clock_time.m4 (gl_CLOCK_TIME): Also check for clock_getres. * m4/gettime.m4 (gl_GETTIME_RES): New macro. --- ChangeLog | 6 +++ doc/posix-functions/clock_getres.texi | 3 ++ lib/gettime-res.c | 78 +++++++++++++++++++++++++++ lib/timespec.h | 1 + m4/clock_time.m4 | 7 +-- m4/gettime.m4 | 10 +++- modules/gettime-res | 30 +++++++++++ 7 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 lib/gettime-res.c create mode 100644 modules/gettime-res
diff --git a/ChangeLog b/ChangeLog index 23c87e8e1..8b25c542b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2021-12-28 Paul Eggert <[email protected]> + gettime-res: new module + * lib/gettime-res.c, modules/gettime-res: New files. + * lib/timespec.h (gettime_res): New decl. + * m4/clock_time.m4 (gl_CLOCK_TIME): Also check for clock_getres. + * m4/gettime.m4 (gl_GETTIME_RES): New macro. + gettime: port better to non-POSIX C2x C2x requires a function timespec_get; prefer that to gettimeofday, since it has better resolution. diff --git a/doc/posix-functions/clock_getres.texi b/doc/posix-functions/clock_getres.texi index 09536ff3b..1381c4649 100644 --- a/doc/posix-functions/clock_getres.texi +++ b/doc/posix-functions/clock_getres.texi @@ -16,3 +16,6 @@ Portability problems not fixed by Gnulib: This function is missing on some platforms: Mac OS X 10.11, Minix 3.1.8, mingw, MSVC 14. @end itemize + +The Gnulib module @code{gettime-res} is a partial substitute; it implements +the @code{CLOCK_REALTIME} functionality of @code{clock_getres}. diff --git a/lib/gettime-res.c b/lib/gettime-res.c new file mode 100644 index 000000000..0d7f1cfea --- /dev/null +++ b/lib/gettime-res.c @@ -0,0 +1,78 @@ +/* Get the system clock resolution. + + Copyright 2021 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert. */ + +#include <config.h> + +#include "timespec.h" + +static long int +gcd (long int a, long int b) +{ + while (b != 0) + { + long int r = a % b; + a = b; + b = r; + } + return a; +} + +/* Return the system time resolution in nanoseconds. */ + +long int +gettime_res (void) +{ + struct timespec res; +#if defined CLOCK_REALTIME && HAVE_CLOCK_GETRES + clock_getres (CLOCK_REALTIME, &res); +#elif defined HAVE_TIMESPEC_GETRES + timespec_getres (&res, TIME_UTC); +#else + /* Guess high and let the later code deduce better. */ + res.tv_sec = 1; + res.tv_nsec = 0; +#endif + + /* On all Gnulib platforms the following calculations do not overflow. */ + + long int hz = TIMESPEC_HZ; + long int r = hz * res.tv_sec + res.tv_nsec; + + /* On some platforms, clock_getres (CLOCK_REALTIME, ...) yields a + too-large resolution, under the mistaken theory that it should + return the timer interval. For example, on AIX 7.2 POWER8 + clock_getres yields 1 cs even though clock_gettime yields 1 µs + resolution. Work around the problem with high probability by + trying clock_gettime several times and observing the resulting + bounds on resolution. */ + for (int i = 0; 1 < r && i < 32; i++) + { + struct timespec now = current_timespec (); + r = gcd (r, now.tv_nsec ? now.tv_nsec : hz * now.tv_sec); + } + + return r; +} + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/lib/timespec.h b/lib/timespec.h index 94a5db751..68da20268 100644 --- a/lib/timespec.h +++ b/lib/timespec.h @@ -88,6 +88,7 @@ timespectod (struct timespec a) return a.tv_sec + a.tv_nsec / 1e9; } +long int gettime_res (void); struct timespec current_timespec (void); void gettime (struct timespec *) _GL_ARG_NONNULL ((1)); int settime (struct timespec const *) _GL_ARG_NONNULL ((1)); diff --git a/m4/clock_time.m4 b/m4/clock_time.m4 index c3b9e7ea4..543099c98 100644 --- a/m4/clock_time.m4 +++ b/m4/clock_time.m4 @@ -1,10 +1,11 @@ -# clock_time.m4 serial 10 +# clock_time.m4 serial 11 dnl Copyright (C) 2002-2006, 2009-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. -# Check for clock_gettime and clock_settime, and set LIB_CLOCK_GETTIME. +# Check for clock_getres, clock_gettime and clock_settime, +# and set LIB_CLOCK_GETTIME. # For a program named, say foo, you should add a line like the following # in the corresponding Makefile.am file: # foo_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) @@ -26,6 +27,6 @@ AC_DEFUN([gl_CLOCK_TIME], AC_SEARCH_LIBS([clock_gettime], [rt posix4], [test "$ac_cv_search_clock_gettime" = "none required" || LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime]) - AC_CHECK_FUNCS([clock_gettime clock_settime]) + AC_CHECK_FUNCS([clock_getres clock_gettime clock_settime]) LIBS=$gl_saved_libs ]) diff --git a/m4/gettime.m4 b/m4/gettime.m4 index cb58bc8eb..43447f28e 100644 --- a/m4/gettime.m4 +++ b/m4/gettime.m4 @@ -1,4 +1,4 @@ -# gettime.m4 serial 10 +# gettime.m4 serial 11 dnl Copyright (C) 2002, 2004-2006, 2009-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,3 +11,11 @@ AC_DEFUN([gl_GETTIME], AC_REQUIRE([gl_TIMESPEC]) AC_CHECK_FUNCS_ONCE([timespec_get]) ]) + +AC_DEFUN([gl_GETTIME_RES], +[ + dnl Prerequisites of lib/gettime-res.c. + AC_REQUIRE([gl_CLOCK_TIME]) + AC_REQUIRE([gl_TIMESPEC]) + AC_CHECK_FUNCS_ONCE([timespec_getres]) +]) diff --git a/modules/gettime-res b/modules/gettime-res new file mode 100644 index 000000000..90f3e81d5 --- /dev/null +++ b/modules/gettime-res @@ -0,0 +1,30 @@ +Description: +Return current time resolution + +Files: +lib/gettime-res.c +m4/gettime.m4 + +Depends-on: +clock-time +gettime +timespec +extensions + +configure.ac: +gl_GETTIME_RES + +Makefile.am: +lib_SOURCES += gettime-res.c + +Include: +"timespec.h" + +Link: +$(LIB_CLOCK_GETTIME) + +License: +LGPL + +Maintainer: +Paul Eggert, Jim Meyering -- 2.33.1
