diff options
Diffstat (limited to 'src/corelib/thread/qsemaphore.cpp')
-rw-r--r-- | src/corelib/thread/qsemaphore.cpp | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 1d01fc1b28..3ecdee3747 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -354,7 +354,12 @@ void QSemaphore::release(int n) quintptr nn = unsigned(n); if (futexHasWaiterCount) nn |= quint64(nn) << 32; // token count replicated in high word - quintptr prevValue = u.fetchAndAddRelease(nn); + quintptr prevValue = u.loadRelaxed(); + quintptr newValue; + do { // loop just to ensure the operations are done atomically + newValue = prevValue + nn; + newValue &= (futexNeedsWakeAllBit - 1); + } while (!u.testAndSetRelease(prevValue, newValue, prevValue)); if (futexNeedsWake(prevValue)) { #ifdef FUTEX_OP if (futexHasWaiterCount) { @@ -376,7 +381,6 @@ void QSemaphore::release(int n) quint32 oparg = 0; quint32 cmp = FUTEX_OP_CMP_NE; quint32 cmparg = 0; - u.fetchAndAndRelease(futexNeedsWakeAllBit - 1); futexWakeOp(*futexLow32(&u), n, INT_MAX, *futexHigh32(&u), FUTEX_OP(op, oparg, cmp, cmparg)); return; } @@ -388,7 +392,6 @@ void QSemaphore::release(int n) // its acquisition anyway, so it has to wait; // 2) it did not see the new counter value, in which case its // futexWait will fail. - u.fetchAndAndRelease(futexNeedsWakeAllBit - 1); if (futexHasWaiterCount) { futexWakeAll(*futexLow32(&u)); futexWakeAll(*futexHigh32(&u)); |