Commit 2523c67b authored by Will Deacon's avatar Will Deacon Committed by Russell King
Browse files

ARM: 7852/1: cmpxchg: implement barrier-less cmpxchg64_local



Our cmpxchg64 macros are wrappers around atomic64_cmpxchg. Whilst this is
great for code re-use, there is a case for barrier-less cmpxchg where it
is known to be safe (for example cmpxchg64_local and cmpxchg-based
lockrefs).

This patch introduces a 64-bit cmpxchg implementation specifically
for the cmpxchg64_* macros, so that it can be later used by the lockref
code.

Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 494e492d
Loading
Loading
Loading
Loading
+42 −10
Original line number Diff line number Diff line
@@ -223,6 +223,42 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
	return ret;
}

static inline unsigned long long __cmpxchg64(unsigned long long *ptr,
					     unsigned long long old,
					     unsigned long long new)
{
	unsigned long long oldval;
	unsigned long res;

	__asm__ __volatile__(
"1:	ldrexd		%1, %H1, [%3]\n"
"	teq		%1, %4\n"
"	teqeq		%H1, %H4\n"
"	bne		2f\n"
"	strexd		%0, %5, %H5, [%3]\n"
"	teq		%0, #0\n"
"	bne		1b\n"
"2:"
	: "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
	: "r" (ptr), "r" (old), "r" (new)
	: "cc");

	return oldval;
}

static inline unsigned long long __cmpxchg64_mb(unsigned long long *ptr,
						unsigned long long old,
						unsigned long long new)
{
	unsigned long long ret;

	smp_mb();
	ret = __cmpxchg64(ptr, old, new);
	smp_mb();

	return ret;
}

#define cmpxchg_local(ptr,o,n)						\
	((__typeof__(*(ptr)))__cmpxchg_local((ptr),			\
				       (unsigned long)(o),		\
@@ -230,16 +266,12 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
				       sizeof(*(ptr))))

#define cmpxchg64(ptr, o, n)						\
	((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr),	\
						atomic64_t,		\
						counter),		\
	((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),			\
					(unsigned long long)(o),	\
					(unsigned long long)(n)))

#define cmpxchg64_local(ptr, o, n)					\
	((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr),	\
						local64_t,		\
						a),			\
	((__typeof__(*(ptr)))__cmpxchg64((ptr),				\
					(unsigned long long)(o),	\
					(unsigned long long)(n)))