From c192e6496269528341320aa556e41b3553ad9357 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 28 Feb 2012 14:55:22 +0100 Subject: Use private futexes for QMutex on Linux if they're available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/corelib/thread/qmutex_linux.cpp | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'src/corelib/thread/qmutex_linux.cpp') 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 #include #include #include +#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(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() -- cgit v1.2.3