summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qmutex_p.h2
-rw-r--r--src/corelib/thread/qmutex_unix.cpp43
2 files changed, 39 insertions, 6 deletions
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index e23be94..2d45cfb 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -78,7 +78,7 @@ public:
#if defined(Q_OS_MAC)
semaphore_t mach_semaphore;
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
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 ce1bfc2..e872187 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -56,11 +56,15 @@
#if defined(Q_OS_MAC)
# include <mach/mach.h>
# include <mach/task.h>
+#elif defined(Q_OS_LINUX)
+# include <linux/futex.h>
+# include <sys/syscall.h>
+# include <unistd.h>
#endif
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_MAC)
+#if !defined(Q_OS_MAC) && !defined(Q_OS_LINUX)
static void report_error(int code, const char *where, const char *what)
{
if (code != 0)
@@ -76,7 +80,7 @@ QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
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
+#elif !defined(Q_OS_LINUX)
wakeup = false;
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
@@ -89,7 +93,7 @@ QMutexPrivate::~QMutexPrivate()
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
+#elif !defined(Q_OS_LINUX)
report_error(pthread_cond_destroy(&cond), "QMutex", "cv destroy");
report_error(pthread_mutex_destroy(&mutex), "QMutex", "mutex destroy");
#endif
@@ -122,7 +126,36 @@ void QMutexPrivate::wakeUp()
semaphore_signal(mach_semaphore);
}
-#else // !Q_OS_MAC
+#elif defined(Q_OS_LINUX)
+
+static inline int _q_futex(volatile int *addr, int op, int val, const struct timespec *timeout, int *addr2, int val2)
+{
+ return syscall(SYS_futex, addr, op, val, timeout, addr2, val2);
+}
+
+bool QMutexPrivate::wait(int timeout)
+{
+ while (contenders.fetchAndStoreAcquire(2) > 0) {
+ struct timespec ts, *pts = 0;
+ if (timeout >= 0) {
+ ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
+ ts.tv_sec = (timeout / 1000);
+ pts = &ts;
+ }
+ int r = _q_futex(&contenders._q_value, FUTEX_WAIT, 2, pts, 0, 0);
+ if (r != 0 && errno == ETIMEDOUT)
+ return false;
+ }
+ return true;
+}
+
+void QMutexPrivate::wakeUp()
+{
+ (void) contenders.fetchAndStoreRelease(0);
+ (void) _q_futex(&contenders._q_value, FUTEX_WAKE, 1, 0, 0, 0);
+}
+
+#else // !Q_OS_MAC && !Q_OS_LINUX
bool QMutexPrivate::wait(int timeout)
{
@@ -166,7 +199,7 @@ void QMutexPrivate::wakeUp()
report_error(pthread_mutex_unlock(&mutex), "QMutex::unlock", "mutex unlock");
}
-#endif // !Q_OS_MAC
+#endif // !Q_OS_MAC && !Q_OS_LINUX
QT_END_NAMESPACE