Index: dbus-1.2.12/configure.in =================================================================== --- dbus-1.2.12.orig/configure.in +++ dbus-1.2.12/configure.in @@ -925,8 +925,30 @@ if $dbus_use_libxml; then fi # Thread lib detection -AC_CHECK_FUNC(pthread_cond_timedwait,,[AC_CHECK_LIB(pthread,pthread_cond_timedwait, +AC_CHECK_FUNC(pthread_cond_timedwait,[AC_CHECK_LIB(pthread,pthread_cond_timedwait, [THREAD_LIBS="-lpthread"])]) +save_libs="$LIBS" +LIBS="$LIBS $THREAD_LIBS" +AC_CHECK_FUNC(pthread_condattr_setclock,have_pthread_condattr_setclock=true,have_pthread_condattr_setclock=false) +if test x$have_pthread_condattr_setclock = xtrue; then + AC_MSG_CHECKING([for CLOCK_MONOTONIC]) + AC_TRY_COMPILE([#include +#include +], [ +struct timespec monotonic_timer; +pthread_condattr_t attr; +pthread_condattr_init (&attr); +pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); +clock_getres (CLOCK_MONOTONIC,&monotonic_timer); +], have_clock_monotonic=true, have_clock_monotonic=false) +if test x$have_clock_monotonic = xtrue; then + AC_MSG_RESULT([found]) + AC_DEFINE(HAVE_MONOTONIC_CLOCK, 1, [Define if we have CLOCK_MONOTONIC]) +else + AC_MSG_RESULT([not found]) +fi +fi +LIBS="$save_libs" # SELinux detection if test x$enable_selinux = xno ; then Index: dbus-1.2.12/dbus/dbus-sysdeps-pthread.c =================================================================== --- dbus-1.2.12.orig/dbus/dbus-sysdeps-pthread.c +++ dbus-1.2.12/dbus/dbus-sysdeps-pthread.c @@ -33,6 +33,15 @@ #include #endif +#include + +/* Whether we have a "monotonic" clock; i.e. a clock not affected by + * changes in system time. + * This is initialized once in check_monotonic_clock below. + * https://bugs.freedesktop.org/show_bug.cgi?id=18121 + */ +static dbus_bool_t have_monotonic_clock = 0; + typedef struct { pthread_mutex_t lock; /**< lock protecting count field */ volatile int count; /**< count of how many times lock holder has recursively locked */ @@ -184,13 +193,21 @@ static DBusCondVar * _dbus_pthread_condvar_new (void) { DBusCondVarPThread *pcond; + pthread_condattr_t attr; int result; pcond = dbus_new (DBusCondVarPThread, 1); if (pcond == NULL) return NULL; - result = pthread_cond_init (&pcond->cond, NULL); + pthread_condattr_init (&attr); +#ifdef HAVE_CLOCK_MONOTONIC + if (have_monotonic_clock) + pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); +#endif + + result = pthread_cond_init (&pcond->cond, &attr); + pthread_condattr_destroy (&attr); if (result == EAGAIN || result == ENOMEM) { @@ -248,7 +265,18 @@ _dbus_pthread_condvar_wait_timeout (DBus _dbus_assert (pmutex->count > 0); _dbus_assert (pthread_equal (pmutex->holder, pthread_self ())); - + +#ifdef HAVE_CLOCK_MONOTONIC + if (have_monotonic_clock) + { + struct timespec monotonic_timer; + clock_gettime (CLOCK_MONOTONIC,&monotonic_timer); + time_now.tv_sec = monotonic_timer.tv_sec; + time_now.tv_usec = monotonic_timer.tv_nsec / 1000; + } + else + /* This else falls through to gettimeofday */ +#endif gettimeofday (&time_now, NULL); end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000; @@ -317,8 +345,19 @@ static const DBusThreadFunctions pthread _dbus_pthread_mutex_unlock }; +static void +check_monotonic_clock (void) +{ +#ifdef HAVE_CLOCK_MONOTONIC + struct timespec dummy; + if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0) + have_monotonic_clock = TRUE; +#endif +} + dbus_bool_t _dbus_threads_init_platform_specific (void) { + check_monotonic_clock (); return dbus_threads_init (&pthread_functions); } Index: dbus-1.2.12/dbus/dbus-sysdeps-unix.c =================================================================== --- dbus-1.2.12.orig/dbus/dbus-sysdeps-unix.c +++ dbus-1.2.12/dbus/dbus-sysdeps-unix.c @@ -2013,6 +2013,16 @@ void _dbus_get_current_time (long *tv_sec, long *tv_usec) { +#ifdef HAVE_CLOCK_MONOTONIC + struct timespec monotonic_timer; + + clock_gettime (CLOCK_MONOTONIC, &monotonic_timer); + + if (tv_sec) + *tv_sec = monotonic_timer.tv_sec; + if (tv_usec) + *tv_usec = monotonic_timer.tv_nsec / 1000; +#else struct timeval t; gettimeofday (&t, NULL); @@ -2021,6 +2031,7 @@ _dbus_get_current_time (long *tv_sec, *tv_sec = t.tv_sec; if (tv_usec) *tv_usec = t.tv_usec; +#endif } /**