diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2012-08-11 13:51:26 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-14 03:45:50 +0200 |
commit | 3acaa648f0ffd03c4695d0be7ed25e73724e4417 (patch) | |
tree | ac6f7576748270a048659fa91443236bb5cc1c26 /src/corelib/thread/qmutex_linux.cpp | |
parent | c40af42658eb8bc7dea5620d0ad788e6e8a6ec16 (diff) |
Hoist the recursive mutex check out of the inner loop
A non-recursive mutex doesn't suddenly become recursive, so we don't
need to check it multiple times.
Change-Id: Id040254b6142d320a7bd3111491082ad09968404
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/thread/qmutex_linux.cpp')
-rw-r--r-- | src/corelib/thread/qmutex_linux.cpp | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index 3fb3db258f..e14660cc37 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -116,40 +116,46 @@ static inline QMutexData *dummyFutexValue() bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW { + // we're here because fastTryLock() has just failed + QMutexData *d = d_ptr.load(); + if (quintptr(d) > 0x3) { //d == dummyLocked() || d == dummyFutexValue() + Q_ASSERT(d->recursive); + return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout); + } + QElapsedTimer elapsedTimer; if (timeout >= 1) elapsedTimer.start(); while (!fastTryLock()) { - QMutexData *d = d_ptr.load(); + d = d_ptr.load(); if (!d) // if d is 0, the mutex is unlocked continue; - - if (quintptr(d) <= 0x3) { //d == dummyLocked() || d == dummyFutexValue() - if (timeout == 0) - return false; - 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; - } - int r = _q_futex(&d_ptr, FUTEX_WAIT, quintptr(dummyFutexValue()), pts); - if (r != 0 && errno == ETIMEDOUT) + if (timeout == 0) + return false; + + // 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; } - Q_ASSERT(d->recursive); - return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout); + return true; } Q_ASSERT(d_ptr.load()); return true; |