summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qsemaphore.cpp
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 16:43:14 +0300
committerTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 16:43:14 +0300
commit29400a683f96867133b28299c0d0bd6bcf40df35 (patch)
treeb616dfb91ce111d61a34a67b28069561306575da /src/corelib/thread/qsemaphore.cpp
parent42e4ae042a4c86e58bcb8b6d2d59ba4a988285b4 (diff)
parent9c60c8b122e5eb74fe74e11b929c30aa19ec0dd3 (diff)
Merge remote-tracking branch 'origin/tqtc/lts-5.15.10' into tqtc/lts-5.15-opensourcev5.15.10-lts-lgpl
Diffstat (limited to 'src/corelib/thread/qsemaphore.cpp')
-rw-r--r--src/corelib/thread/qsemaphore.cpp9
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));