diff options
author | Thiago Macieira <thiago@kde.org> | 2011-07-14 12:43:44 (GMT) |
---|---|---|
committer | Olivier Goffart <olivier.goffart@nokia.com> | 2011-07-15 12:50:39 (GMT) |
commit | b66db48934bc13cc7439e0fc9c8ec54122678a02 (patch) | |
tree | e500fe7cd1d8fd269a9ef5a0fa91dcce74174dd1 /src/corelib | |
parent | 34fc612144f204d130307dc9d64657340a9d7f7d (diff) | |
download | Qt-b66db48934bc13cc7439e0fc9c8ec54122678a02.zip Qt-b66db48934bc13cc7439e0fc9c8ec54122678a02.tar.gz Qt-b66db48934bc13cc7439e0fc9c8ec54122678a02.tar.bz2 |
Fix the timeout calculation for futexes in QMutex.
Recalculate how much time is remaining.
This commit needs to be backported to 4.8.
Change-Id: Ib587335bb90306e65969bb26256fb388f8f6bd24
Merge-request: 20
Reviewed-by: Olivier Goffart <olivier.goffart@nokia.com>
Reviewed-on: http://codereview.qt.nokia.com/1666
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
(cherry picked from commit 412ef92162f8874a1585221125c31ef5f8ccc9cb)
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/thread/qmutex_unix.cpp | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 12bc795..e692e19 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -60,6 +60,7 @@ # include <linux/futex.h> # include <sys/syscall.h> # include <unistd.h> +# include <QtCore/qelapsedtimer.h> #endif QT_BEGIN_NAMESPACE @@ -138,16 +139,31 @@ static inline int _q_futex(volatile int *addr, int op, int val, const struct tim bool QMutexPrivate::wait(int timeout) { + struct timespec ts, *pts = 0; + QElapsedTimer timer; + if (timeout >= 0) { + ts.tv_nsec = ((timeout % 1000) * 1000) * 1000; + ts.tv_sec = (timeout / 1000); + pts = &ts; + timer.start(); + } 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; + + if (pts) { + // recalculate the timeout + qint64 xtimeout = timeout * 1000 * 1000; + xtimeout -= timer.nsecsElapsed(); + if (xtimeout < 0) { + // timer expired after we returned + return false; + } + + ts.tv_sec = timeout / Q_INT64_C(1000) / 1000 / 1000; + ts.tv_nsec = timeout % (Q_INT64_C(1000) * 1000 * 1000); + } } return true; } |