diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2012-08-11 14:47:10 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-14 03:45:50 +0200 |
commit | fc174a37283306f3f5c06efeda22d5164820c164 (patch) | |
tree | 3e96b1d780babc36425866f38fab214d51fccc1c /src/corelib | |
parent | 30bea611df2d95b53b63273ac867d9bd0a181edf (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.cpp | 48 |
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; } |