[PATCH v3 3/5] csky: Emulate two-byte cmpxchg

From: Bradley Morgan

Date: Thu Sep 17 2026 - 13:56:22 EST


CSKY has no two-byte atomic compare and swap, so the __cmpxchg()
switches in cmpxchg.h let case 2 fall through to the undefined
__cmpxchg_called_with_bad_pointer(), failing at link time. Route case
2 through the new cmpxchg_emu_u16(), which takes the old and new
values as unsigned long and narrows them itself, so the (uintptr_t)
casts on __old and __new come off in all three switch instances.
The (u16) casts are gone for the same reason.

The __old and __new declarations were typed __typeof__(old) and
__typeof__(new), which skips the pointer-integer type check, so
cmpxchg(&p, 4, 5) compiled silently. Typing them through
(unsigned long)(0 ? *(ptr) : (old)) keeps the value conversion while
making the compiler reject mismatched types, the idiom David
Laight suggested. The same check is added for new.

Signed-off-by: Bradley Morgan <brads@xxxxxxxxxxxxxx>
---
arch/csky/include/asm/cmpxchg.h | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/csky/include/asm/cmpxchg.h b/arch/csky/include/asm/cmpxchg.h
index db6dda47184e..29dc56e4b7f1 100644
--- a/arch/csky/include/asm/cmpxchg.h
+++ b/arch/csky/include/asm/cmpxchg.h
@@ -57,13 +57,16 @@
#define __cmpxchg_relaxed(ptr, old, new, size) \
({ \
__typeof__(ptr) __ptr = (ptr); \
- __typeof__(new) __new = (new); \
- __typeof__(new) __tmp; \
- __typeof__(old) __old = (old); \
+ unsigned long __old = (unsigned long)(0 ? *(ptr) : (old)); \
+ unsigned long __new = (unsigned long)(0 ? *(ptr) : (new)); \
+ unsigned long __tmp; \
__typeof__(*(ptr)) __ret; \
switch (size) { \
case 1: \
- __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, __old, __new); \
+ break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, __old, __new); \
break; \
case 4: \
asm volatile ( \
@@ -90,13 +93,16 @@
#define __cmpxchg_acquire(ptr, old, new, size) \
({ \
__typeof__(ptr) __ptr = (ptr); \
- __typeof__(new) __new = (new); \
- __typeof__(new) __tmp; \
- __typeof__(old) __old = (old); \
+ unsigned long __old = (unsigned long)(0 ? *(ptr) : (old)); \
+ unsigned long __new = (unsigned long)(0 ? *(ptr) : (new)); \
+ unsigned long __tmp; \
__typeof__(*(ptr)) __ret; \
switch (size) { \
case 1: \
- __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, __old, __new); \
+ break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, __old, __new); \
break; \
case 4: \
asm volatile ( \
@@ -124,13 +130,16 @@
#define __cmpxchg(ptr, old, new, size) \
({ \
__typeof__(ptr) __ptr = (ptr); \
- __typeof__(new) __new = (new); \
- __typeof__(new) __tmp; \
- __typeof__(old) __old = (old); \
+ unsigned long __old = (unsigned long)(0 ? *(ptr) : (old)); \
+ unsigned long __new = (unsigned long)(0 ? *(ptr) : (new)); \
+ unsigned long __tmp; \
__typeof__(*(ptr)) __ret; \
switch (size) { \
case 1: \
- __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, __old, __new); \
+ break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, __old, __new); \
break; \
case 4: \
asm volatile ( \
--
2.47.3