summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-08-11 14:47:10 +0200
committerQt by Nokia <qt-info@nokia.com>2012-09-14 03:45:50 +0200
commitfc174a37283306f3f5c06efeda22d5164820c164 (patch)
tree3e96b1d780babc36425866f38fab214d51fccc1c /src/corelib
parent30bea611df2d95b53b63273ac867d9bd0a181edf (diff)
Simplify the futex lock loop: no need for nested while
Once we enter the inner loop, we never exit it except to return from the lockInternal() function, so the rest is never executed again. As a consequence of this, we won't try to fastTryLock() twice per mutex. Therefore, for a non-recursive mutex, if lockInternal() is entered, we'll definitely need to use futexes. Change-Id: Ice617ed27449c1fbdc112a159a86cd0660125e13 Reviewed-by: Lars Knoll <lars.knoll@nokia.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/thread/qmutex_linux.cpp48
1 files changed, 23 insertions, 25 deletions
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index a17e9d0a24..50d33c0441 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -126,34 +126,32 @@ bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
if (timeout >= 1)
elapsedTimer.start();
- while (!fastTryLock()) {
- d = d_ptr.load();
-
- if (!d) // if d is 0, the mutex is unlocked
- continue;
- // the mutex is locked already, set a bit indicating we're waiting
- while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
- struct timespec ts, *pts = 0;
- if (timeout >= 1) {
- // recalculate the timeout
- qint64 xtimeout = qint64(timeout) * 1000 * 1000;
- xtimeout -= elapsedTimer.nsecsElapsed();
- if (xtimeout <= 0) {
- // timer expired after we returned
- return false;
- }
- ts.tv_sec = xtimeout / Q_INT64_C(1000) / 1000 / 1000;
- ts.tv_nsec = xtimeout % (Q_INT64_C(1000) * 1000 * 1000);
- pts = &ts;
- }
-
- // successfully set the waiting bit, now sleep
- int r = _q_futex(&d_ptr, FUTEX_WAIT, quintptr(dummyFutexValue()), pts);
- if (r != 0 && errno == ETIMEDOUT)
+ // the mutex is locked already, set a bit indicating we're waiting
+ while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
+ struct timespec ts, *pts = 0;
+ if (timeout >= 1) {
+ // recalculate the timeout
+ qint64 xtimeout = qint64(timeout) * 1000 * 1000;
+ xtimeout -= elapsedTimer.nsecsElapsed();
+ if (xtimeout <= 0) {
+ // timer expired after we returned
return false;
+ }
+ ts.tv_sec = xtimeout / Q_INT64_C(1000) / 1000 / 1000;
+ ts.tv_nsec = xtimeout % (Q_INT64_C(1000) * 1000 * 1000);
+ pts = &ts;
}
- return true;
+
+ // successfully set the waiting bit, now sleep
+ int r = _q_futex(&d_ptr, FUTEX_WAIT, quintptr(dummyFutexValue()), pts);
+ if (r != 0 && errno == ETIMEDOUT)
+ return false;
+
+ // we got woken up, so try to acquire the mutex
+ // note we must set to dummyFutexValue because there could be other threads
+ // also waiting
}
+
Q_ASSERT(d_ptr.load());
return true;
}