mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-01-07 03:00:15 +01:00
Bug 18121 - Use a monotonic clock for pthread timeouts
Patch based on one from Keith Mok <ek9852@gmail.com>, some followup work from Janne Karhunen <Janne.Karhunen@gmail.com>. We don't want condition variable timeouts to be affected by the system clock. Use the POSIX CLOCK_MONOTONIC if available.
This commit is contained in:
parent
f4e15893e5
commit
ae24bb35e2
2 changed files with 65 additions and 3 deletions
25
configure.in
25
configure.in
|
|
@ -696,8 +696,31 @@ 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_SEARCH_LIBS([clock_getres],[rt],[THREAD_LIBS="$THREAD_LIBS -lrt"])
|
||||
AC_MSG_CHECKING([for CLOCK_MONOTONIC])
|
||||
AC_TRY_COMPILE([#include <time.h>
|
||||
#include <pthread.h>
|
||||
], [
|
||||
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
|
||||
|
|
|
|||
|
|
@ -33,6 +33,15 @@
|
|||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* 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_MONOTONIC_CLOCK
|
||||
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 (DBusCondVar *cond,
|
|||
|
||||
_dbus_assert (pmutex->count > 0);
|
||||
_dbus_assert (pthread_equal (pmutex->holder, pthread_self ()));
|
||||
|
||||
|
||||
#ifdef HAVE_MONOTONIC_CLOCK
|
||||
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_functions =
|
|||
_dbus_pthread_mutex_unlock
|
||||
};
|
||||
|
||||
static void
|
||||
check_monotonic_clock (void)
|
||||
{
|
||||
#ifdef HAVE_MONOTONIC_CLOCK
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue