QSemaphore: fix missed wakes with futex on Windows
We do this by making the 'futexNeedsWakeAllBit' to be part of both the expectedValue and the pointer we're waiting on. This makes sense since having the 'futexNeedsWakeAllBit' set is a requirement for starting a sleep. Thus we should condition sleeping on whether or not another thread unset it. Since the futexNeedsWakeAllBit is in the "topmost" bit of the pointer we wait on we'll need to use the full 64-bits on 64-bit platforms. This isn't enabled (nor was it an issue) for configurations with 'futexHasWaiterCount' since that works differently, and waits for the high 32 bits. Fixes: QTBUG-92148 Change-Id: I424c605f0120ea5e647c5bb19b00ff35eaf1608a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
b8802071ed
commit
587e3bb0ba
@ -200,16 +200,23 @@ futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValu
|
||||
|
||||
// indicate we're waiting
|
||||
start_wait:
|
||||
auto ptr = futexLow32(&u);
|
||||
auto ptr = [&u]() {
|
||||
if constexpr (futexHasWaiterCount)
|
||||
return futexLow32(&u);
|
||||
else
|
||||
return &u;
|
||||
}();
|
||||
if (n > 1 || !futexHasWaiterCount) {
|
||||
u.fetchAndOrRelaxed(futexNeedsWakeAllBit);
|
||||
curValue |= futexNeedsWakeAllBit;
|
||||
if (n > 1 && futexHasWaiterCount) {
|
||||
if constexpr (futexHasWaiterCount) {
|
||||
if (n > 1) {
|
||||
ptr = futexHigh32(&u);
|
||||
//curValue >>= 32; // but this is UB in 32-bit, so roundabout:
|
||||
// curValue >>= 32; // but this is UB in 32-bit, so roundabout:
|
||||
curValue = quint64(curValue) >> 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTimed && remainingTime > 0) {
|
||||
bool timedout = !futexWait(*ptr, curValue, remainingTime);
|
||||
@ -397,7 +404,7 @@ void QSemaphore::release(int n)
|
||||
futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg));
|
||||
}
|
||||
#else
|
||||
// Unset the bit and wake everyone. There are two possibibilies
|
||||
// Unset the bit and wake everyone. There are two possibilities
|
||||
// under which a thread can set the bit between the AND and the
|
||||
// futexWake:
|
||||
// 1) it did see the new counter value, but it wasn't enough for
|
||||
|
Loading…
Reference in New Issue
Block a user