summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-09-16 13:46:43 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-12-20 15:49:46 (GMT)
commitcf17b743d2fe84ab259b7232ab07b58a1872e18e (patch)
tree7a0dfd1f21ba9041de7c39c6947adeacf9e4d8e5 /src
parent87bab705ded31559941020d3c500f43f571f9c16 (diff)
downloadQt-cf17b743d2fe84ab259b7232ab07b58a1872e18e.zip
Qt-cf17b743d2fe84ab259b7232ab07b58a1872e18e.tar.gz
Qt-cf17b743d2fe84ab259b7232ab07b58a1872e18e.tar.bz2
Improve QMutex contention performance on Mac OS X
Use a Mach semaphore to implement QMutexPrivate::wait() and ::wakeup(). This makes QMutex perform more or less identically the same as pthread_mutex_t when contended. Reviewed-by: joao
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qmutex_p.h8
-rw-r--r--src/corelib/thread/qmutex_unix.cpp53
2 files changed, 59 insertions, 2 deletions
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index 57a6062..e23be94 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -58,6 +58,10 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qmutex.h>
+#if defined(Q_OS_MAC)
+# include <mach/semaphore.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QMutexPrivate : public QMutexData {
@@ -72,7 +76,9 @@ public:
Qt::HANDLE owner;
uint count;
-#if defined(Q_OS_UNIX)
+#if defined(Q_OS_MAC)
+ semaphore_t mach_semaphore;
+#elif defined(Q_OS_UNIX)
volatile bool wakeup;
pthread_mutex_t mutex;
pthread_cond_t cond;
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index dcf8b9f..ce1bfc2 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -53,28 +53,77 @@
#undef wakeup
#endif
+#if defined(Q_OS_MAC)
+# include <mach/mach.h>
+# include <mach/task.h>
+#endif
+
QT_BEGIN_NAMESPACE
+#if !defined(Q_OS_MAC)
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
}
+#endif
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
- : QMutexData(mode), lastSpinCount(0), owner(0), count(0), wakeup(false)
+ : QMutexData(mode), lastSpinCount(0), owner(0), count(0)
{
+#if defined(Q_OS_MAC)
+ kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to create semaphore, error %d", r);
+#else
+ wakeup = false;
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
+#endif
}
QMutexPrivate::~QMutexPrivate()
{
+#if defined(Q_OS_MAC)
+ kern_return_t r = semaphore_destroy(mach_task_self(), mach_semaphore);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: failed to destroy semaphore, error %d", r);
+#else
report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
+#endif
}
+#if defined(Q_OS_MAC)
+
+bool QMutexPrivate::wait(int timeout)
+{
+ if (contenders.fetchAndAddAcquire(1) == 0) {
+ // lock acquired without waiting
+ return true;
+ }
+ bool returnValue;
+ if (timeout < 0) {
+ returnValue = semaphore_wait(mach_semaphore) == KERN_SUCCESS;
+ } else {
+ mach_timespec_t ts;
+ ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
+ ts.tv_sec = (timeout / 1000);
+ kern_return_t r = semaphore_timedwait(mach_semaphore, ts);
+ returnValue = r == KERN_SUCCESS;
+ }
+ contenders.deref();
+ return returnValue;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ semaphore_signal(mach_semaphore);
+}
+
+#else // !Q_OS_MAC
+
bool QMutexPrivate::wait(int timeout)
{
if (contenders.fetchAndAddAcquire(1) == 0) {
@@ -117,6 +166,8 @@ void QMutexPrivate::wakeUp()
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
}
+#endif // !Q_OS_MAC
+
QT_END_NAMESPACE
#endif // QT_NO_THREAD