Use Posix monotonic clocks instead of gettimeofday when available.

2006-08-27  Matthias Clasen  <mclasen@redhat.com>

	* glib/gtimer.c: Use Posix monotonic clocks instead of
	gettimeofday when available.  (#336114, William Jon McCann)
This commit is contained in:
Matthias Clasen 2006-08-28 03:01:33 +00:00 committed by Matthias Clasen
parent f54e7ee475
commit 72520d46bc
2 changed files with 101 additions and 13 deletions

View File

@ -1,3 +1,8 @@
2006-08-27 Matthias Clasen <mclasen@redhat.com>
* glib/gtimer.c: Use Posix monotonic clocks instead of
gettimeofday when available. (#336114, William Jon McCann)
2006-08-26 Matthias Clasen <mclasen@redhat.com>
* glib/gutils.h:

View File

@ -50,16 +50,21 @@
#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;
};
@ -67,10 +72,34 @@ struct _GTimer
#ifdef G_OS_WIN32
# define GETTIME(v) \
GetSystemTimeAsFileTime ((FILETIME *)&v)
#else /* !G_OS_WIN32 */
#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;
}