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>
This commit is contained in:
parent
efa0f1f0a7
commit
c192e64962
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user