summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qmutex_linux.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-08-11 13:51:26 +0200
committerQt by Nokia <qt-info@nokia.com>2012-09-14 03:45:50 +0200
commit3acaa648f0ffd03c4695d0be7ed25e73724e4417 (patch)
treeac6f7576748270a048659fa91443236bb5cc1c26 /src/corelib/thread/qmutex_linux.cpp
parentc40af42658eb8bc7dea5620d0ad788e6e8a6ec16 (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.cpp54
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;