[PATCH v4 next 7/9] locking/osq: Use 'unsigned int' for next/prev/tail
From: David Laight
Date: Mon Sep 07 2026 - 04:48:40 EST
Consistently use 'unsigned int' for all the 'offset by 1' cpu numbers.
This makes the code only use one set of xchg primitives.
The unsigned type gives marginally better code inside per_cpu_ptr().
Signed-off-by: David Laight <david.laight.linux@xxxxxxxxx>
---
include/linux/osq_lock.h | 8 ++++----
kernel/locking/osq_lock.c | 31 +++++++++++++++----------------
2 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/include/linux/osq_lock.h b/include/linux/osq_lock.h
index ea8fb31379e3..9e637e265189 100644
--- a/include/linux/osq_lock.h
+++ b/include/linux/osq_lock.h
@@ -12,17 +12,17 @@ struct optimistic_spin_queue {
* Stores an encoded value of the CPU # of the tail node in the queue.
* If the queue is empty, then it's set to OSQ_UNLOCKED_VAL.
*/
- atomic_t tail;
+ unsigned int tail;
};
#define OSQ_UNLOCKED_VAL (0)
/* Init macro and function. */
-#define OSQ_LOCK_UNLOCKED { ATOMIC_INIT(OSQ_UNLOCKED_VAL) }
+#define OSQ_LOCK_UNLOCKED { OSQ_UNLOCKED_VAL }
static inline void osq_lock_init(struct optimistic_spin_queue *lock)
{
- atomic_set(&lock->tail, OSQ_UNLOCKED_VAL);
+ WRITE_ONCE(lock->tail, OSQ_UNLOCKED_VAL);
}
extern bool osq_lock(struct optimistic_spin_queue *lock);
@@ -30,7 +30,7 @@ extern void osq_unlock(struct optimistic_spin_queue *lock);
static inline bool osq_is_locked(struct optimistic_spin_queue *lock)
{
- return atomic_read(&lock->tail) != OSQ_UNLOCKED_VAL;
+ return READ_ONCE(lock->tail) != OSQ_UNLOCKED_VAL;
}
#endif
diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c
index 0f68ee017b54..144eb446c867 100644
--- a/kernel/locking/osq_lock.c
+++ b/kernel/locking/osq_lock.c
@@ -34,8 +34,8 @@
*/
struct optimistic_spin_node {
- int next; /* CPU number offset by 1, 0 if no next */
- int prev; /* CPU number offset by 1, 0 if lock held */
+ unsigned int next; /* CPU number offset by 1, 0 if no next */
+ unsigned int prev; /* CPU number offset by 1, 0 if lock held */
} __aligned(8);
static DEFINE_PER_CPU(struct optimistic_spin_node, osq_node);
@@ -44,16 +44,15 @@ static DEFINE_PER_CPU(struct optimistic_spin_node, osq_node);
* We use the value 0 to represent "no CPU", thus the encoded value
* will be the CPU number incremented by 1.
*/
-static inline int encode_cpu(int cpu_nr)
+static inline unsigned int encode_cpu(unsigned int cpu_nr)
{
return cpu_nr + 1;
}
-static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val)
+static inline struct optimistic_spin_node *
+decode_cpu(unsigned int encoded_cpu_val)
{
- int cpu_nr = encoded_cpu_val - 1;
-
- return per_cpu_ptr(&osq_node, cpu_nr);
+ return per_cpu_ptr(&osq_node, encoded_cpu_val - 1);
}
/*
@@ -72,17 +71,17 @@ static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val)
* When a lock request is being cancelled the caller needs 'next' to
* set node->prev->next = next.
*/
-static inline int
-osq_unlink_from_next(struct optimistic_spin_queue *lock, int prev)
+static inline unsigned int
+osq_unlink_from_next(struct optimistic_spin_queue *lock, unsigned int prev)
{
- int curr = encode_cpu(smp_processor_id());
+ unsigned int curr = encode_cpu(smp_processor_id());
struct optimistic_spin_node *node;
- int next;
+ unsigned int next;
for (;;) {
- int tail = atomic_read(&lock->tail);
+ unsigned int tail = READ_ONCE(lock->tail);
if (curr == tail &&
- atomic_try_cmpxchg_release(&lock->tail, &tail, prev)) {
+ try_cmpxchg_release(&lock->tail, &tail, prev)) {
/*
* We were the last queued, lock->tail now references
* prev (or is 0 if the list is now empty).
@@ -127,8 +126,8 @@ osq_unlink_from_next(struct optimistic_spin_queue *lock, int prev)
bool osq_lock(struct optimistic_spin_queue *lock)
{
struct optimistic_spin_node *node, *prev_ptr;
- int curr = encode_cpu(smp_processor_id());
- int next, prev;
+ unsigned int curr = encode_cpu(smp_processor_id());
+ unsigned int next, prev;
/*
* We need both ACQUIRE (pairs with corresponding RELEASE in
@@ -136,7 +135,7 @@ bool osq_lock(struct optimistic_spin_queue *lock)
* the node fields we just initialised) semantics when updating
* the lock tail.
*/
- prev = atomic_xchg(&lock->tail, curr);
+ prev = xchg(&lock->tail, curr);
if (prev == OSQ_UNLOCKED_VAL)
return true;
--
2.39.5