From e4fad946131afe888c7884c42c8c5d1b0945feae Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 28 Aug 2006 03:05:42 +0000 Subject: [PATCH] Check for clock_gettime. Use Posix monotonic clocks instead of 2006-08-27 Matthias Clasen * configure.in: Check for clock_gettime. * glib/gtimer.c: Use Posix monotonic clocks instead of gettimeofday when available. (#336114, William Jon McCann) --- ChangeLog | 6 +++ configure.in | 6 +++ glib/gtimer.c | 109 ++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 108 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab63155fa..619ef5910 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-08-27 Matthias Clasen + + * configure.in: Check for clock_gettime. + * glib/gtimer.c: Use Posix monotonic clocks instead of + gettimeofday when available. (#336114, William Jon McCann) + 2006-08-25 Matthias Clasen * configure.in: Fix the pthread compiler flag detection. diff --git a/configure.in b/configure.in index a6ca7771c..4f78684f2 100644 --- a/configure.in +++ b/configure.in @@ -856,6 +856,12 @@ AC_MSG_RESULT(unsigned $glib_size_type) # Check for some functions AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf stpcpy strcasecmp strncasecmp poll getcwd nanosleep vasprintf setenv unsetenv getc_unlocked readlink symlink) +AC_CHECK_FUNCS(clock_gettime, [], [ + AC_CHECK_LIB(rt, clock_gettime, [ + AC_DEFINE(HAVE_CLOCK_GETTIME, 1) + LIBS="$LIBS -lrt" + ]) +]) AC_CHECK_HEADERS(crt_externs.h) AC_CHECK_FUNCS(_NSGetEnviron) diff --git a/glib/gtimer.c b/glib/gtimer.c index 69b49571a..85688816b 100644 --- a/glib/gtimer.c +++ b/glib/gtimer.c @@ -50,27 +50,56 @@ #include "glib.h" #include "galias.h" +#define G_NSEC_PER_SEC 1000000000 struct _GTimer { #ifdef G_OS_WIN32 guint64 start; guint64 end; -#else /* !G_OS_WIN32 */ +#elif HAVE_CLOCK_GETTIME + struct timespec start; + struct timespec end; + gint clock; +#else /* uses gettimeofday */ struct timeval start; struct timeval end; -#endif /* !G_OS_WIN32 */ +#endif guint active : 1; }; #ifdef G_OS_WIN32 -# define GETTIME(v) \ +# define GETTIME(v) \ GetSystemTimeAsFileTime ((FILETIME *)&v) -#else /* !G_OS_WIN32 */ -# define GETTIME(v) \ +#elif HAVE_CLOCK_GETTIME +# define GETTIME(v) \ + clock_gettime (posix_clock, &v) +#else +# define GETTIME(v) \ gettimeofday (&v, NULL) -#endif /* !G_OS_WIN32 */ +#endif + +#ifdef HAVE_CLOCK_GETTIME +static gint posix_clock = 0; + +static void +init_posix_clock (void) +{ + static gboolean initialized = FALSE; + + if (!initialized) + { + initialized = TRUE; +#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK >= 0 + if (sysconf (_SC_MONOTONIC_CLOCK) >= 0) + posix_clock = CLOCK_MONOTONIC; + else +#endif + posix_clock = CLOCK_REALTIME; + } +} +#endif GTimer* g_timer_new (void) @@ -80,6 +109,10 @@ g_timer_new (void) timer = g_new (GTimer, 1); timer->active = TRUE; +#ifdef HAVE_CLOCK_GETTIME + init_posix_clock (); +#endif + GETTIME (timer->start); return timer; @@ -126,9 +159,11 @@ g_timer_continue (GTimer *timer) { #ifdef G_OS_WIN32 guint64 elapsed; +#elif HAVE_CLOCK_GETTIME + struct timespec elapsed; #else struct timeval elapsed; -#endif /* G_OS_WIN32 */ +#endif g_return_if_fail (timer != NULL); g_return_if_fail (timer->active == FALSE); @@ -146,7 +181,29 @@ g_timer_continue (GTimer *timer) timer->start -= elapsed; -#else /* !G_OS_WIN32 */ +#elif HAVE_CLOCK_GETTIME + + if (timer->start.tv_nsec > timer->end.tv_nsec) + { + timer->end.tv_nsec += G_NSEC_PER_SEC; + timer->end.tv_sec--; + } + + elapsed.tv_nsec = timer->end.tv_nsec - timer->start.tv_nsec; + elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec; + + GETTIME (timer->start); + + if (timer->start.tv_nsec < elapsed.tv_nsec) + { + timer->start.tv_nsec += G_NSEC_PER_SEC; + timer->start.tv_sec--; + } + + timer->start.tv_nsec -= elapsed.tv_nsec; + timer->start.tv_sec -= elapsed.tv_sec; + +#else if (timer->start.tv_usec > timer->end.tv_usec) { @@ -180,9 +237,11 @@ g_timer_elapsed (GTimer *timer, gdouble total; #ifdef G_OS_WIN32 gint64 elapsed; +#elif HAVE_CLOCK_GETTIME + struct timespec elapsed; #else struct timeval elapsed; -#endif /* G_OS_WIN32 */ +#endif g_return_val_if_fail (timer != NULL, 0); @@ -196,9 +255,33 @@ g_timer_elapsed (GTimer *timer, if (microseconds) *microseconds = (elapsed / 10) % 1000000; -#else /* !G_OS_WIN32 */ +#elif HAVE_CLOCK_GETTIME if (timer->active) - gettimeofday (&timer->end, NULL); + GETTIME (timer->end); + + if (timer->start.tv_nsec > timer->end.tv_nsec) + { + timer->end.tv_nsec += G_NSEC_PER_SEC; + timer->end.tv_sec--; + } + + elapsed.tv_nsec = timer->end.tv_nsec - timer->start.tv_nsec; + elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec; + + total = elapsed.tv_sec + ((gdouble) elapsed.tv_nsec / (gdouble) G_NSEC_PER_SEC); + if (total < 0) + { + total = 0; + + if (microseconds) + *microseconds = 0; + } + else if (microseconds) + *microseconds = elapsed.tv_nsec / 1000; + +#else + if (timer->active) + GETTIME (timer->end); if (timer->start.tv_usec > timer->end.tv_usec) { @@ -209,7 +292,7 @@ g_timer_elapsed (GTimer *timer, elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec; elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec; - total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6); + total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / (gdouble) G_USEC_PER_SEC); if (total < 0) { total = 0; @@ -220,7 +303,7 @@ g_timer_elapsed (GTimer *timer, else if (microseconds) *microseconds = elapsed.tv_usec; -#endif /* !G_OS_WIN32 */ +#endif return total; }