| Message ID | 20260922173354.14404-4-brads@mainlining.org |
|---|---|
| State | New |
| Headers | show |
| Series | Add two-byte cmpxchg emulation and wire it into the architectures | expand |
On Tue, 22 Sep 2026 17:33:52 +0000 Bradley Morgan <brads@mainlining.org> wrote: You missed v4 from the subject line of all the patches. > SH has no byte or halfword atomic memory operations, so the __cmpxchg() > switch routes case 1 through cmpxchg_emu_u8() and lets case 2 fall > through to __cmpxchg_called_with_bad_pointer(), which is declared but > never defined, so a two-byte cmpxchg() fails at link time. Route case > 2 through the new cmpxchg_emu_u16(), which takes the old and new > values as unsigned long, so the (unsigned long) casts move off the > call and into _old_ and _new_ declarations that type check the old > and new arguments against *ptr through (unsigned long)(0 ? *ptr : _o_), > the idiom David Laight suggested, so cmpxchg(&p, 4, 5) no longer > compiles silently. > > Acked-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> > Signed-off-by: Bradley Morgan <brads@mainlining.org> > --- > arch/sh/include/asm/cmpxchg.h | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h > index 1e5dc5ccf7bf..b87f59107b4e 100644 > --- a/arch/sh/include/asm/cmpxchg.h > +++ b/arch/sh/include/asm/cmpxchg.h > @@ -59,6 +59,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, > switch (size) { > case 1: > return cmpxchg_emu_u8(ptr, old, new); > + case 2: > + return cmpxchg_emu_u16(ptr, old, new); > case 4: > return __cmpxchg_u32(ptr, old, new); > } > @@ -70,8 +72,10 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, > ({ \ > __typeof__(*(ptr)) _o_ = (o); \ > __typeof__(*(ptr)) _n_ = (n); \ > - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ > - (unsigned long)_n_, sizeof(*(ptr))); \ > + unsigned long _old_ = (unsigned long)(0 ? *ptr : _o_); \ > + unsigned long _new_ = (unsigned long)(0 ? *ptr : _n_); \ > + (__typeof__(*(ptr))) __cmpxchg((ptr), _old_, \ > + _new_, sizeof(*(ptr))); \ Minor niggle if you have to do these again... That line doesn't look long enough to need splitting. More generally if you add 'unsigned long _rval_' and put a final cast at the bottom the the #define the code will probably look neater. David > }) > > #include <asm-generic/cmpxchg-local.h>
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h index 1e5dc5ccf7bf..b87f59107b4e 100644 --- a/arch/sh/include/asm/cmpxchg.h +++ b/arch/sh/include/asm/cmpxchg.h @@ -59,6 +59,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, switch (size) { case 1: return cmpxchg_emu_u8(ptr, old, new); + case 2: + return cmpxchg_emu_u16(ptr, old, new); case 4: return __cmpxchg_u32(ptr, old, new); } @@ -70,8 +72,10 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, ({ \ __typeof__(*(ptr)) _o_ = (o); \ __typeof__(*(ptr)) _n_ = (n); \ - (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ - (unsigned long)_n_, sizeof(*(ptr))); \ + unsigned long _old_ = (unsigned long)(0 ? *ptr : _o_); \ + unsigned long _new_ = (unsigned long)(0 ? *ptr : _n_); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), _old_, \ + _new_, sizeof(*(ptr))); \ }) #include <asm-generic/cmpxchg-local.h>