summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2011-07-14 12:43:44 (GMT)
committerOlivier Goffart <olivier.goffart@nokia.com>2011-07-15 12:50:39 (GMT)
commitb66db48934bc13cc7439e0fc9c8ec54122678a02 (patch)
treee500fe7cd1d8fd269a9ef5a0fa91dcce74174dd1 /src/corelib
parent34fc612144f204d130307dc9d64657340a9d7f7d (diff)
downloadQt-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.cpp28
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;
}