[tip: locking/urgent] locking/osq: Switch osq_wait_next()/atomic_cmpxchg() ordering
From: tip-bot2 for Peter Zijlstra
Date: Fri Nov 06 2026 - 05:25:40 EST
The following commit has been merged into the locking/urgent branch of tip:
Commit-ID: 1b9e01fcc47aff00d2fd64693c5dcd620eff5865
Gitweb: https://git.kernel.org/tip/1b9e01fcc47aff00d2fd64693c5dcd620eff5865
Author: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
AuthorDate: Tue, 15 Sep 2026 13:09:33 +02:00
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitterDate: Fri, 06 Nov 2026 11:16:14 +01:00
locking/osq: Switch osq_wait_next()/atomic_cmpxchg() ordering
The atomic_cmpxchg() in osq_wait_next() removes the current CPU's node
from the tail of the queue and puts @old_cpu back.
This is very much like an 'unlock', which is RELEASE, rather than
ACQUIRE.
Additionally, on success (the only case where the ordering is
effective), this returns NULL which means both callsites will do nothing
more, there are no subsequent operations to order against.
Furthermore, the osq_lock() caller will then return false, indicating
failure to acquire -- the mutex must go block. Again, not making a case
for ACQUIRE. Neither atomics nor locks provide ordering on failure.
Since ACQUIRE makes no sense, while RELEASE makes it more symmetric with
osq_unlock(), switch the ordering. This then makes osq_unlock()
consistently RELEASE.
Fixes: c55a6ffa6285 ("locking/osq: Relax atomic semantics")
Suggested-by: David Laight <david.laight.linux@xxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Waiman Long <longman@xxxxxxxxxx>
Cc: linux-kernel@xxxxxxxxxxxxxxx
---
kernel/locking/osq_lock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c
index b4233dc..98b12d7 100644
--- a/kernel/locking/osq_lock.c
+++ b/kernel/locking/osq_lock.c
@@ -59,7 +59,7 @@ osq_wait_next(struct optimistic_spin_queue *lock,
for (;;) {
if (atomic_read(&lock->tail) == curr &&
- atomic_cmpxchg_acquire(&lock->tail, curr, old_cpu) == curr) {
+ atomic_cmpxchg_release(&lock->tail, curr, old_cpu) == curr) {
/*
* We were the last queued, we moved @lock back. @prev
* will now observe @lock and will complete its