summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qmutex_linux.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-02-28 14:55:22 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-25 06:30:16 +0200
commitc192e6496269528341320aa556e41b3553ad9357 (patch)
tree120cd69ecc34264499aa74cffc28574e92cd4a61 /src/corelib/thread/qmutex_linux.cpp
parentefa0f1f0a7c7e76f58b802b06629ca1799a89f8b (diff)
Use private futexes for QMutex on Linux if they're available
Futexes on Linux can be used across processes, for inter-process synchronisation. The private flag tells the kernel that this futex is not used with other processes, so it does not need to check for waiters outside the current process. This feature had been proposed in Merge Request 25, but was lost. Change-Id: Ieafa8b8df0949bd9ae73709b3ec63f7709b0b2a6 Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Diffstat (limited to 'src/corelib/thread/qmutex_linux.cpp')
-rw-r--r--src/corelib/thread/qmutex_linux.cpp37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index b1618f7fc9..1bb5e77e77 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -45,15 +45,47 @@
#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qmutex_p.h"
-# include "qelapsedtimer.h"
+#include "qelapsedtimer.h"
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <errno.h>
+#ifndef QT_LINUX_FUTEX
+# error "Qt build is broken: qmutex_linux.cpp is being built but futex support is not wanted"
+#endif
+
QT_BEGIN_NAMESPACE
+static inline int futexFlags()
+{
+ int value = 0;
+#if defined(FUTEX_PRIVATE_FLAG)
+ // check if the kernel supports extra futex flags
+ // FUTEX_PRIVATE_FLAG appeared in v2.6.22
+ static QBasicAtomicInt futexFlagSupport = Q_BASIC_ATOMIC_INITIALIZER(-1);
+
+ value = futexFlagSupport.load();
+ if (value == -1) {
+ // try an operation that has no side-effects: wake up 42 threads
+ // futex will return -1 (errno==ENOSYS) if the flag isn't supported
+ // there should be no other error conditions
+ value = syscall(SYS_futex, &futexFlagSupport,
+ FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
+ 42, 0, 0, 0);
+ if (value != -1) {
+ value = FUTEX_PRIVATE_FLAG;
+ futexFlagSupport.store(value);
+ return value;
+ }
+ value = 0;
+ futexFlagSupport.store(value);
+ }
+#endif
+ return value;
+}
+
static inline int _q_futex(void *addr, int op, int val, const struct timespec *timeout)
{
volatile int *int_addr = reinterpret_cast<volatile int *>(addr);
@@ -62,7 +94,8 @@ static inline int _q_futex(void *addr, int op, int val, const struct timespec *t
#endif
int *addr2 = 0;
int val2 = 0;
- return syscall(SYS_futex, int_addr, op, val, timeout, addr2, val2);
+
+ return syscall(SYS_futex, int_addr, op | futexFlags(), val, timeout, addr2, val2);
}
static inline QMutexData *dummyFutexValue()