summaryrefslogtreecommitdiff
path: root/dbus
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2009-07-10 22:27:55 -0400
committerColin Walters <walters@verbum.org>2009-07-14 15:40:24 -0400
commit2e286c8a27f30a5eb4933a84754e1c8059ec3805 (patch)
tree2b6dfefeeae7c3ef5a31aba71bcf95f133e72877 /dbus
parent943b9d3944a507d106613dbf3fa678c6a0bcbade (diff)
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. (cherry picked from commit ae24bb35e2ee3ecde990f55852982b573754ec43)
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-sysdeps-pthread.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c
index b7c37066..46e4204d 100644
--- a/dbus/dbus-sysdeps-pthread.c
+++ b/dbus/dbus-sysdeps-pthread.c
@@ -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);
}