Commit 2e57d1d6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull cmpxchg updates from Paul McKenney:
 "Provide one-byte and two-byte cmpxchg() support on sparc32, parisc,
  and csky

  This provides native one-byte and two-byte cmpxchg() support for
  sparc32 and parisc, courtesy of Al Viro. This support is provided by
  the same hashed-array-of-locks technique used for the other atomic
  operations provided for these two platforms.

  There is also emulated one-byte cmpxchg() support for csky using a new
  cmpxchg_emu_u8() function that uses a four-byte cmpxchg() to emulate
  the one-byte variant.

  Similar patches for emulation of one-byte cmpxchg() for arc, sh, and
  xtensa have not yet received maintainer acks, so they are slated for
  the v6.11 merge window"

* tag 'cmpxchg.2024.05.11a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
  csky: Emulate one-byte cmpxchg
  lib: Add one-byte emulation function
  parisc: add u16 support to cmpxchg()
  parisc: add missing export of __cmpxchg_u8()
  parisc: unify implementations of __cmpxchg_u{8,32,64}
  parisc: __cmpxchg_u32(): lift conversion into the callers
  sparc32: add __cmpxchg_u{8,16}() and teach __cmpxchg() to handle those sizes
  sparc32: unify __cmpxchg_u{32,64}
  sparc32: make the first argument of __cmpxchg_u64() volatile u64 *
  sparc32: make __cmpxchg_u32() return u32
parents c0b9620b 5800e77d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1617,4 +1617,7 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
	# strict alignment always, even with -falign-functions.
	def_bool CC_HAS_MIN_FUNCTION_ALIGNMENT || CC_IS_CLANG

config ARCH_NEED_CMPXCHG_1_EMU
	bool

endmenu
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ config CSKY
	select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
	select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
	select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
	select ARCH_NEED_CMPXCHG_1_EMU
	select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 && $(cc-option,-mbacktrace)
	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
	select COMMON_CLK
+10 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#ifdef CONFIG_SMP
#include <linux/bug.h>
#include <asm/barrier.h>
#include <linux/cmpxchg-emu.h>

#define __xchg_relaxed(new, ptr, size)				\
({								\
@@ -61,6 +62,9 @@
	__typeof__(old) __old = (old);				\
	__typeof__(*(ptr)) __ret;				\
	switch (size) {						\
	case 1:							\
		__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
		break;						\
	case 4:							\
		asm volatile (					\
		"1:	ldex.w		%0, (%3) \n"		\
@@ -91,6 +95,9 @@
	__typeof__(old) __old = (old);				\
	__typeof__(*(ptr)) __ret;				\
	switch (size) {						\
	case 1:							\
		__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
		break;						\
	case 4:							\
		asm volatile (					\
		"1:	ldex.w		%0, (%3) \n"		\
@@ -122,6 +129,9 @@
	__typeof__(old) __old = (old);				\
	__typeof__(*(ptr)) __ret;				\
	switch (size) {						\
	case 1:							\
		__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
		break;						\
	case 4:							\
		asm volatile (					\
		RELEASE_FENCE					\
+10 −12
Original line number Diff line number Diff line
@@ -56,26 +56,24 @@ __arch_xchg(unsigned long x, volatile void *ptr, int size)
/* bug catcher for when unsupported size is used - won't link */
extern void __cmpxchg_called_with_bad_pointer(void);

/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
				   unsigned int new_);
extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_);
/* __cmpxchg_u... defined in arch/parisc/lib/bitops.c */
extern u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new_);
extern u16 __cmpxchg_u16(volatile u16 *ptr, u16 old, u16 new_);
extern u32 __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_);

/* don't worry...optimizer will get rid of most of this */
static inline unsigned long
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
{
	switch (size) {
	return
#ifdef CONFIG_64BIT
	case 8: return __cmpxchg_u64((u64 *)ptr, old, new_);
		size == 8 ? __cmpxchg_u64(ptr, old, new_) :
#endif
	case 4: return __cmpxchg_u32((unsigned int *)ptr,
				     (unsigned int)old, (unsigned int)new_);
	case 1: return __cmpxchg_u8((u8 *)ptr, old & 0xff, new_ & 0xff);
	}
	__cmpxchg_called_with_bad_pointer();
	return old;
		size == 4 ? __cmpxchg_u32(ptr, old, new_) :
		size == 2 ? __cmpxchg_u16(ptr, old, new_) :
		size == 1 ? __cmpxchg_u8(ptr, old, new_) :
			(__cmpxchg_called_with_bad_pointer(), old);
}

#define arch_cmpxchg(ptr, o, n)						 \
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ EXPORT_SYMBOL(memset);
#include <linux/atomic.h>
EXPORT_SYMBOL(__xchg8);
EXPORT_SYMBOL(__xchg32);
EXPORT_SYMBOL(__cmpxchg_u8);
EXPORT_SYMBOL(__cmpxchg_u16);
EXPORT_SYMBOL(__cmpxchg_u32);
EXPORT_SYMBOL(__cmpxchg_u64);
#ifdef CONFIG_SMP
Loading