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>
This commit is contained in:
parent
30bea611df
commit
fc174a3728
@ -126,34 +126,32 @@ bool QBasicMutex::lockInternal(int timeout) Q_DECL_NOTHROW
|
|||||||
if (timeout >= 1)
|
if (timeout >= 1)
|
||||||
elapsedTimer.start();
|
elapsedTimer.start();
|
||||||
|
|
||||||
while (!fastTryLock()) {
|
// the mutex is locked already, set a bit indicating we're waiting
|
||||||
d = d_ptr.load();
|
while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
|
||||||
|
struct timespec ts, *pts = 0;
|
||||||
if (!d) // if d is 0, the mutex is unlocked
|
if (timeout >= 1) {
|
||||||
continue;
|
// recalculate the timeout
|
||||||
// the mutex is locked already, set a bit indicating we're waiting
|
qint64 xtimeout = qint64(timeout) * 1000 * 1000;
|
||||||
while (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) != 0) {
|
xtimeout -= elapsedTimer.nsecsElapsed();
|
||||||
struct timespec ts, *pts = 0;
|
if (xtimeout <= 0) {
|
||||||
if (timeout >= 1) {
|
// timer expired after we returned
|
||||||
// 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)
|
|
||||||
return false;
|
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());
|
Q_ASSERT(d_ptr.load());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user