From: "Paul E. McKenney" <paulmck@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: Bradley Morgan <brads@mainlining.org>,
Vineet Gupta <vgupta@kernel.org>, Guo Ren <guoren@kernel.org>,
Yoshinori Sato <ysato@users.sourceforge.jp>,
Rich Felker <dalias@libc.org>,
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>,
Chris Zankel <chris@zankel.net>,
Max Filippov <jcmvbkbc@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
Arnd Bergmann <arnd@kernel.org>,
David Laight <david.laight.linux@gmail.com>,
linux-snps-arc@lists.infradead.org, linux-csky@vger.kernel.org,
linux-sh@vger.kernel.org, kernel-team@meta.com,
"Paul E . McKenney" <paulmck@kernel.org>
Subject: [PATCH 1/5] lib: Add two-byte cmpxchg emulation function
Date: Wed, 7 Oct 2026 13:36:32 -0700 [thread overview]
Message-ID: <20261007203636.1982188-1-paulmck@kernel.org> (raw)
In-Reply-To: <7f398d4a-7fae-4382-9cc4-8627e8aa912b@paulmck-laptop>
From: Bradley Morgan <brads@mainlining.org>
cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
cmpxchg() for the architectures lacking native one-byte atomics.
The same architectures also lack native two-byte cmpxchg(), where
such an operation is not supported and either fails to compile via
BUILD_BUG() or fails to link, because the bad pointer sentinels
these architectures declare are never defined.
Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
word with READ_ONCE(), splices the two target bytes through a union
and loops on cmpxchg() of the full word until the compare succeeds.
Like cmpxchg_emu_u8() it is fully ordered.
Unlike cmpxchg_emu_u8() it casts the old and new values to u16
internally and returns unsigned long, taking the old and new values
as unsigned long, per the suggestion from David Laight. The switch
statements in the architecture macros instantiate every size case,
so a cmpxchg() on a pointer type checks the two-byte case as well,
and a u16 parameter or return would make the macro casts and return
conversions warn there. With unsigned long parameters and return the
call sites need no narrowing casts, pointer exchanges compile warning
free, and the function still compares and returns exactly the 16 bits
the caller asked for, which matches the hardware cmpxchg r16
behaviour where a 16-bit compare only looks at the low 16 bits of
the register.
cmpxchg_emu_u8() keeps returning the old value unmasked, so a caller
that passes a wider old than 8 bits still gets it back as passed,
matching the behaviour the one-byte emulator always had.
The Kconfig symbol gating this file is renamed from
ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
selects both the one-byte and the two-byte emulation.
[ paulmck: Apply kernel test robot feedback. ]
Suggested-by: Paul E. McKenney <paulmck@kernel.org>
Suggested-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Bradley Morgan <brads@mainlining.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Reviewed-by: David Laight <david.laight.linux@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@kernel.org>
---
include/linux/cmpxchg-emu.h | 4 +++-
lib/cmpxchg-emu.c | 38 +++++++++++++++++++++++++++++++++----
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
index 998deec67740a..2db70f1e39253 100644
--- a/include/linux/cmpxchg-emu.h
+++ b/include/linux/cmpxchg-emu.h
@@ -4,12 +4,14 @@
* lacking direct support for these sizes. These are implemented in terms
* of 4-byte cmpxchg operations.
*
- * Copyright (C) 2024 Paul E. McKenney.
+ * Copyright (C) 2024 Paul E. McKenney <paulmck@kernel.org>
+ * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org>
*/
#ifndef __LINUX_CMPXCHG_EMU_H
#define __LINUX_CMPXCHG_EMU_H
uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
+unsigned long cmpxchg_emu_u16(volatile u16 *p, unsigned long old, unsigned long new);
#endif /* __LINUX_CMPXCHG_EMU_H */
diff --git a/lib/cmpxchg-emu.c b/lib/cmpxchg-emu.c
index 27f6f97cb60dd..25c69224a7597 100644
--- a/lib/cmpxchg-emu.c
+++ b/lib/cmpxchg-emu.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Emulated 1-byte cmpxchg operation for architectures lacking direct
- * support for this size. This is implemented in terms of 4-byte cmpxchg
- * operations.
+ * Emulated 1-byte and 2-byte cmpxchg operations for architectures lacking
+ * direct support for these sizes. These are implemented in terms of
+ * 4-byte cmpxchg operations.
*
- * Copyright (C) 2024 Paul E. McKenney.
+ * Copyright (C) 2024 Paul E. McKenney <paulmck@kernel.org>
+ * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org>
*/
#include <linux/types.h>
@@ -43,3 +44,32 @@ uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new)
return old;
}
EXPORT_SYMBOL_GPL(cmpxchg_emu_u8);
+
+union u16_32 {
+ u16 h[2];
+ u32 w;
+};
+
+/* Emulate two-byte cmpxchg() in terms of 4-byte cmpxchg. */
+unsigned long cmpxchg_emu_u16(volatile u16 *p, unsigned long old, unsigned long new)
+{
+ u32 *p32 = (u32 *)(((uintptr_t)p) & ~0x3);
+ int i = (((uintptr_t)p) & 0x2) / 2;
+ union u16_32 old32;
+ union u16_32 new32;
+ u32 ret;
+
+ WARN_ON_ONCE(((uintptr_t)p) & 0x1);
+ ret = READ_ONCE(*p32);
+ do {
+ old32.w = ret;
+ if (old32.h[i] != (u16)old)
+ return (unsigned long)old32.h[i];
+ new32.w = old32.w;
+ new32.h[i] = (u16)new;
+ instrument_atomic_read_write(p, 2);
+ ret = data_race(cmpxchg(p32, old32.w, new32.w)); // Overridden above.
+ } while (ret != old32.w);
+ return (u16)old;
+}
+EXPORT_SYMBOL_GPL(cmpxchg_emu_u16);
--
2.40.1
next prev parent reply other threads:[~2026-10-07 20:36 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 20:36 [PATCH 0/5] Provide two-byte cmpxchg() emulation Paul E. McKenney
2026-10-07 20:36 ` Paul E. McKenney [this message]
2026-10-07 20:36 ` [PATCH 2/5] sh: Emulate two-byte cmpxchg Paul E. McKenney
2026-10-07 20:36 ` [PATCH 3/5] ARC: " Paul E. McKenney
2026-10-07 20:48 ` Vineet Gupta
2026-10-07 20:58 ` Paul E. McKenney
2026-10-07 20:36 ` [PATCH 4/5] csky: " Paul E. McKenney
2026-10-08 5:54 ` Guo Ren
2026-10-07 20:36 ` [PATCH 5/5] xtensa: " Paul E. McKenney
2026-10-07 20:44 ` [PATCH 0/5] Provide two-byte cmpxchg() emulation Bradley Morgan
2026-10-07 20:50 ` Paul E. McKenney
-- strict thread matches above, loose matches on Subject: below --
2026-09-22 17:33 [PATCH v4 0/5] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
2026-09-22 17:33 ` [PATCH 1/5] lib: Add two-byte cmpxchg emulation function Bradley Morgan
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=20261007203636.1982188-1-paulmck@kernel.org \
--to=paulmck@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=arnd@kernel.org \
--cc=brads@mainlining.org \
--cc=chris@zankel.net \
--cc=dalias@libc.org \
--cc=david.laight.linux@gmail.com \
--cc=glaubitz@physik.fu-berlin.de \
--cc=guoren@kernel.org \
--cc=jcmvbkbc@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-csky@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=linux-snps-arc@lists.infradead.org \
--cc=vgupta@kernel.org \
--cc=ysato@users.sourceforge.jp \
/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®