Set some attributes on pthread condattrs
Make them use the monotonic clock if that's available. On Mac, the monotonic clock is not available -- Qt fakes monotonic support by using the Mach timebase -- so we need to use gettimeofday. Change-Id: Iaea0b0c0de1b4802780e2476dc3643b703db392c Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
70a9caf4de
commit
15d7044c82
@ -70,6 +70,8 @@
|
||||
# define QT_LINUX_FUTEX
|
||||
#endif
|
||||
|
||||
struct timespec;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMutexData
|
||||
@ -137,6 +139,13 @@ public:
|
||||
#endif //QT_LINUX_FUTEX
|
||||
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
// helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp
|
||||
// they are in qwaitcondition_unix.cpp actually
|
||||
void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where);
|
||||
void qt_abstime_for_timeout(struct timespec *ts, int timeout);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QMUTEX_P_H
|
||||
|
@ -42,11 +42,14 @@
|
||||
#include "qplatformdefs.h"
|
||||
#include "qmutex.h"
|
||||
#include "qstring.h"
|
||||
#include "qelapsedtimer.h"
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
#include "qatomic.h"
|
||||
#include "qmutex_p.h"
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(Q_OS_VXWORKS) && defined(wakeup)
|
||||
#undef wakeup
|
||||
@ -64,7 +67,7 @@ QMutexPrivate::QMutexPrivate()
|
||||
: wakeup(false)
|
||||
{
|
||||
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
|
||||
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
||||
qt_initialize_pthread_cond(&cond, "QMutex");
|
||||
}
|
||||
|
||||
QMutexPrivate::~QMutexPrivate()
|
||||
@ -81,12 +84,8 @@ bool QMutexPrivate::wait(int timeout)
|
||||
if (timeout < 0) {
|
||||
errorCode = pthread_cond_wait(&cond, &mutex);
|
||||
} else {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000;
|
||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
qt_abstime_for_timeout(&ti, timeout);
|
||||
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||
}
|
||||
if (errorCode) {
|
||||
|
@ -45,11 +45,15 @@
|
||||
#include "qreadwritelock.h"
|
||||
#include "qatomic.h"
|
||||
#include "qstring.h"
|
||||
#include "qelapsedtimer.h"
|
||||
#include "private/qcore_unix_p.h"
|
||||
|
||||
#include "qmutex_p.h"
|
||||
#include "qreadwritelock_p.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
|
||||
@ -61,6 +65,38 @@ static void report_error(int code, const char *where, const char *what)
|
||||
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
||||
}
|
||||
|
||||
void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
|
||||
{
|
||||
pthread_condattr_t condattr;
|
||||
|
||||
pthread_condattr_init(&condattr);
|
||||
#if !defined(Q_OS_MAC) && (_POSIX_MONOTONIC_CLOCK-0 >= 0)
|
||||
if (QElapsedTimer::clockType() == QElapsedTimer::MonotonicClock)
|
||||
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
|
||||
#endif
|
||||
report_error(pthread_cond_init(cond, &condattr), where, "cv init");
|
||||
pthread_condattr_destroy(&condattr);
|
||||
}
|
||||
|
||||
void qt_abstime_for_timeout(timespec *ts, int timeout)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
// on Mac, qt_gettime() (on qelapsedtimer_mac.cpp) returns ticks related to the Mach absolute time
|
||||
// that doesn't work with pthread
|
||||
// Mac also doesn't have clock_gettime
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
*ts = qt_gettime();
|
||||
#endif
|
||||
|
||||
ts->tv_sec += timeout / 1000;
|
||||
ts->tv_nsec += timeout % 1000 * Q_UINT64_C(1000) * 1000;
|
||||
normalizedTimespec(*ts);
|
||||
}
|
||||
|
||||
class QWaitConditionPrivate {
|
||||
public:
|
||||
pthread_mutex_t mutex;
|
||||
@ -73,14 +109,8 @@ public:
|
||||
int code;
|
||||
forever {
|
||||
if (time != ULONG_MAX) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (time % 1000) * 1000) * 1000;
|
||||
ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
|
||||
qt_abstime_for_timeout(&ti, time);
|
||||
code = pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||
} else {
|
||||
code = pthread_cond_wait(&cond, &mutex);
|
||||
@ -114,7 +144,7 @@ QWaitCondition::QWaitCondition()
|
||||
{
|
||||
d = new QWaitConditionPrivate;
|
||||
report_error(pthread_mutex_init(&d->mutex, NULL), "QWaitCondition", "mutex init");
|
||||
report_error(pthread_cond_init(&d->cond, NULL), "QWaitCondition", "cv init");
|
||||
qt_initialize_pthread_cond(&d->cond, "QWaitCondition");
|
||||
d->waiters = d->wakeups = 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user