Commit 82b993e8 authored by Mark Rutland's avatar Mark Rutland Committed by Peter Zijlstra
Browse files

locking/atomic: cmpxchg: support ARCH_ATOMIC



We'd like all architectures to convert to ARCH_ATOMIC, as this will
enable functionality, and once all architectures are converted it will
be possible to make significant cleanups to the atomic headers.

A number of architectures use asm-generic/cmpxchg.h or
asm-generic/cmpxhg-local.h, and it's impractical to convert the headers
and all these architectures in one go. To make it possible to convert
them one-by-one, let's make the asm-generic implementation function as
either cmpxchg*() or arch_cmpxchg*() depending on whether ARCH_ATOMIC is
selected. To do this, the generic implementations are prefixed as
generic_cmpxchg_*(), and preprocessor definitions map
cmpxchg_*()/arch_cmpxchg_*() onto these as appropriate.

Once all users are moved over to ARCH_ATOMIC the ifdeffery in the header
can be simplified and/or removed entirely.

For existing users (none of which select ARCH_ATOMIC), there should be
no functional change as a result of this patch.

Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210525140232.53872-13-mark.rutland@arm.com
parent 6988631b
Loading
Loading
Loading
Loading
+44 −17
Original line number Diff line number Diff line
@@ -14,16 +14,14 @@
#include <linux/types.h>
#include <linux/irqflags.h>

#ifndef xchg

/*
 * This function doesn't exist, so you'll get a linker error if
 * something tries to do an invalidly-sized xchg().
 */
extern void __xchg_called_with_bad_pointer(void);
extern void __generic_xchg_called_with_bad_pointer(void);

static inline
unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
{
	unsigned long ret, flags;

@@ -75,35 +73,64 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
#endif /* CONFIG_64BIT */

	default:
		__xchg_called_with_bad_pointer();
		__generic_xchg_called_with_bad_pointer();
		return x;
	}
}

#define xchg(ptr, x) ({							\
#define generic_xchg(ptr, x) ({							\
	((__typeof__(*(ptr)))							\
		__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));	\
		__generic_xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));	\
})

#endif /* xchg */

/*
 * Atomic compare and exchange.
 */
#include <asm-generic/cmpxchg-local.h>

#ifndef cmpxchg_local
#define cmpxchg_local(ptr, o, n) ({					       \
#define generic_cmpxchg_local(ptr, o, n) ({					\
	((__typeof__(*(ptr)))__generic_cmpxchg_local((ptr), (unsigned long)(o),	\
			(unsigned long)(n), sizeof(*(ptr))));			\
})

#define generic_cmpxchg64_local(ptr, o, n) \
	__generic_cmpxchg64_local((ptr), (o), (n))


#ifdef CONFIG_ARCH_ATOMIC

#ifndef arch_xchg
#define arch_xchg		generic_xchg
#endif

#ifndef arch_cmpxchg_local
#define arch_cmpxchg_local	generic_cmpxchg_local
#endif

#ifndef arch_cmpxchg64_local
#define arch_cmpxchg64_local	generic_cmpxchg64_local
#endif

#define arch_cmpxchg		arch_cmpxchg_local
#define arch_cmpxchg64		arch_cmpxchg64_local

#else /* CONFIG_ARCH_ATOMIC */

#ifndef xchg
#define xchg			generic_xchg
#endif

#ifndef cmpxchg_local
#define cmpxchg_local		generic_cmpxchg_local
#endif

#ifndef cmpxchg64_local
#define cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n))
#define cmpxchg64_local		generic_cmpxchg64_local
#endif

#define cmpxchg(ptr, o, n)	cmpxchg_local((ptr), (o), (n))
#define cmpxchg64(ptr, o, n)	cmpxchg64_local((ptr), (o), (n))
#define cmpxchg			cmpxchg_local
#define cmpxchg64		cmpxchg64_local

#endif /* CONFIG_ARCH_ATOMIC */

#endif /* __ASM_GENERIC_CMPXCHG_H */