From: "tip-bot2 for David Laight" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: David Laight <david.laight.linux@gmail.com>,
"Peter Zijlstra (Intel)" <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Waiman Long <longman@redhat.com>,
x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [tip: locking/core] locking/osq: Use CPU number for 'next' pointer
Date: Fri, 06 Nov 2026 10:25:33 -0000 [thread overview]
Message-ID: <179396073328.1009794.8798304514620219910.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20260907084133.3696-7-david.laight.linux@gmail.com>
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 8e7c6217be7f8c016975f5b0954f6736b9ac42cf
Gitweb: https://git.kernel.org/tip/8e7c6217be7f8c016975f5b0954f6736b9ac42cf
Author: David Laight <david.laight.linux@gmail.com>
AuthorDate: Mon, 07 Sep 2026 09:41:30 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Fri, 06 Nov 2026 11:16:24 +01:00
locking/osq: Use CPU number for 'next' pointer
There is only one write done through node->next (setting prev) when
'node' is being removed. So the code can consistently use the CPU
numbers pretty much throughout (this was suggested by Linus a while
back).
This reduces struct optimistic_spin_node to 8 bytes. This is currently
padded out to a cache line which is silly. Change to be __aligned(8) so
that it isn't split between cache lines.
Accesses to 'other CPU' data are very limited and only happen during
the enqueue and dequeue operation.
[ peterz: Rewrote it completely ]
Signed-off-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Waiman Long <longman@redhat.com>
Link: https://patch.msgid.link/20260907084133.3696-7-david.laight.linux@gmail.com
---
kernel/locking/osq_lock.c | 49 ++++++++++++++++++--------------------
1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c
index a6c89e5..735bf62 100644
--- a/kernel/locking/osq_lock.c
+++ b/kernel/locking/osq_lock.c
@@ -13,11 +13,11 @@
*/
struct optimistic_spin_node {
- struct optimistic_spin_node *next;
+ int next_cpu; /* CPU number offset by 1 */
int prev_cpu; /* CPU number offset by 1 */
-};
+} __aligned(8);
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct optimistic_spin_node, osq_node);
+static DEFINE_PER_CPU(struct optimistic_spin_node, osq_node);
/*
* We use the value 0 to represent "no CPU", thus the encoded value
@@ -44,22 +44,21 @@ static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val)
* For osq_unlock() there is never a previous node and old_cpu is
* set to OSQ_UNLOCKED_VAL.
*/
-static inline struct optimistic_spin_node *
-osq_wait_unlink_next(struct optimistic_spin_queue *lock,
- int old_cpu)
+static inline int
+osq_wait_unlink_next(struct optimistic_spin_queue *lock, int old_cpu)
{
struct optimistic_spin_node *next, *node = this_cpu_ptr(&osq_node);
- int curr = encode_cpu(smp_processor_id());
+ int next_cpu, node_cpu = encode_cpu(smp_processor_id());
for (;;) {
- if (atomic_read(&lock->tail) == curr &&
- atomic_cmpxchg_release(&lock->tail, curr, old_cpu) == curr) {
+ if (atomic_read(&lock->tail) == node_cpu &&
+ atomic_cmpxchg_release(&lock->tail, node_cpu, old_cpu) == node_cpu) {
/*
* We were the last queued, we moved @lock back. @prev
* will now observe @lock and will complete its
* unlock()/unqueue().
*/
- return NULL;
+ return 0;
}
/*
@@ -72,9 +71,9 @@ osq_wait_unlink_next(struct optimistic_spin_queue *lock,
* wait for either @lock to point to us, through its Step-B, or
* wait for a new @node->next from its Step-C.
*/
- if (node->next) {
- next = xchg(&node->next, NULL);
- if (next)
+ if (node->next_cpu) {
+ next_cpu = xchg(&node->next_cpu, 0);
+ if (next_cpu)
break;
}
@@ -84,16 +83,16 @@ osq_wait_unlink_next(struct optimistic_spin_queue *lock,
/*
* Unlink @node from @next.
*/
+ next = decode_cpu(next_cpu);
WRITE_ONCE(next->prev_cpu, old_cpu);
- return next;
+ return next_cpu;
}
/*
* Set prev->next; this is the counterpart of osq_wait_unlink_next() in that
* by setting ->next the wait is terminated and progress is resumed.
*/
-static inline void osq_link_next(struct optimistic_spin_node *prev,
- struct optimistic_spin_node *next)
+static inline void osq_link_next(struct optimistic_spin_node *prev, int next_cpu)
{
/*
* Suppose:
@@ -128,17 +127,17 @@ static inline void osq_link_next(struct optimistic_spin_node *prev,
*
* Which would result in list corruption.
*/
- smp_store_release(&prev->next, next);
+ smp_store_release(&prev->next_cpu, next_cpu);
}
bool osq_lock(struct optimistic_spin_queue *lock)
{
struct optimistic_spin_node *node = this_cpu_ptr(&osq_node);
- struct optimistic_spin_node *prev, *next;
- int curr = encode_cpu(smp_processor_id());
- int prev_cpu;
+ int node_cpu = encode_cpu(smp_processor_id());
+ struct optimistic_spin_node *prev;
+ int prev_cpu, next_cpu;
- node->next = NULL;
+ node->next_cpu = 0;
/*
* We need both ACQUIRE (pairs with corresponding RELEASE in
@@ -146,13 +145,13 @@ bool osq_lock(struct optimistic_spin_queue *lock)
* the node fields we just initialised) semantics when updating
* the lock tail.
*/
- prev_cpu = atomic_xchg(&lock->tail, curr);
+ prev_cpu = atomic_xchg(&lock->tail, node_cpu);
if (prev_cpu == OSQ_UNLOCKED_VAL)
return true;
prev = decode_cpu(prev_cpu);
node->prev_cpu = prev_cpu;
- osq_link_next(prev, node);
+ osq_link_next(prev, node_cpu);
/*
* Normally @prev is untouchable after the above store; because at that
@@ -191,8 +190,8 @@ bool osq_lock(struct optimistic_spin_queue *lock)
prev = decode_cpu(prev_cpu);
- if (data_race(prev->next) == node &&
- cmpxchg(&prev->next, node, NULL) == node)
+ if (data_race(prev->next_cpu) == node_cpu &&
+ cmpxchg(&prev->next_cpu, node_cpu, 0) == node_cpu)
break;
/*
next prev parent reply other threads:[~2026-11-06 10:25 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 8:41 [PATCH v4 next 0/9] locking/osq_lock: Optimisations to osq_lock code David Laight
2026-09-07 8:41 ` [PATCH v4 next 1/9] locking/osq_lock: Add some comments about how it works David Laight
2026-09-09 14:57 ` Waiman Long
2026-09-07 8:41 ` [PATCH v4 next 2/9] locking/osq_lock: Save the cpu number for 'prev' not the node address David Laight
2026-09-09 17:36 ` Waiman Long
2026-09-15 8:33 ` Peter Zijlstra
2026-09-15 10:26 ` Peter Zijlstra
2026-09-15 11:11 ` David Laight
2026-09-15 17:27 ` Waiman Long
2026-11-06 10:25 ` [tip: locking/core] locking/osq: Save the CPU number for 'prev', " tip-bot2 for David Laight
2026-09-07 8:41 ` [PATCH v4 next 3/9] locking/osq_lock: Set prev_cpu=0 instead of locked=1 David Laight
2026-09-09 18:01 ` Waiman Long
2026-09-09 18:52 ` David Laight
2026-09-14 12:01 ` Peter Zijlstra
2026-09-14 13:10 ` David Laight
2026-09-14 12:03 ` Peter Zijlstra
2026-09-14 13:08 ` David Laight
2026-09-15 8:40 ` Peter Zijlstra
2026-09-15 10:14 ` David Laight
2026-09-15 8:50 ` Peter Zijlstra
2026-09-15 10:20 ` David Laight
2026-09-15 10:40 ` Peter Zijlstra
2026-09-15 13:13 ` Peter Zijlstra
2026-09-15 13:15 ` Peter Zijlstra
2026-09-15 13:55 ` David Laight
2026-09-15 14:01 ` Peter Zijlstra
2026-09-15 17:47 ` David Laight
2026-09-16 8:08 ` Peter Zijlstra
2026-11-06 10:25 ` [tip: locking/core] locking/osq: " tip-bot2 for David Laight
2026-09-07 8:41 ` [PATCH v4 next 4/9] locking/osq_lock: Delete 'fast path' code from osq_unlock() David Laight
2026-09-15 14:15 ` Peter Zijlstra
2026-09-16 10:56 ` Peter Zijlstra
2026-09-07 8:41 ` [PATCH v4 next 5/9] locking/osq_lock: Avoid writing to node->next in the osq_lock() fast path David Laight
2026-09-07 8:41 ` [PATCH v4 next 6/9] locking/osq: Use cpu number for 'next' pointer David Laight
2026-11-06 10:25 ` tip-bot2 for David Laight [this message]
2026-09-07 8:41 ` [PATCH v4 next 7/9] locking/osq: Use 'unsigned int' for next/prev/tail David Laight
2026-09-07 8:41 ` [PATCH v4 next 8/9] locking/osq: inline encode_cpu() and rename decode_cpu() David Laight
2026-09-07 8:41 ` [PATCH v4 next 9/9] locking/osq_lock: Swap next<->prev and tail<->head David Laight
2026-09-07 16:08 ` [PATCH v4 next 0/9] locking/osq_lock: Optimisations to osq_lock code Linus Torvalds
2026-09-07 17:27 ` David Laight
2026-09-09 14:15 ` Haakon Bugge
2026-09-09 19:09 ` David Laight
2026-09-09 20:14 ` Waiman Long
2026-09-09 20:33 ` Waiman Long
2026-09-10 9:45 ` Haakon Bugge
2026-09-10 11:00 ` David Laight
2026-09-10 11:31 ` Haakon Bugge
2026-09-10 12:05 ` David Laight
2026-09-10 15:30 ` Haakon Bugge
2026-09-10 16:22 ` Waiman Long
2026-09-11 17:15 ` David Laight
2026-09-14 11:46 ` Haakon Bugge
2026-09-14 13:24 ` David Laight
2026-09-11 10:08 ` David Laight
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=179396073328.1009794.8798304514620219910.tip-bot2@tip-bot2 \
--to=tip-bot2@linutronix.de \
--cc=david.laight.linux@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=longman@redhat.com \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=torvalds@linux-foundation.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®