Commit e69a0ef7 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

locking,arch,mn10300: Fold atomic_ops



Many of the atomic op implementations are the same except for one
instruction; fold the lot into a few CPP macros and reduce LoC.

This also prepares for easy addition of new ops.

Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: linux-am33-list@redhat.com
Link: http://lkml.kernel.org/r/20140508135852.605324173@infradead.org


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent ef31563e
Loading
Loading
Loading
Loading
+42 −83
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@
 * @v: pointer of type atomic_t
 *
 * Atomically reads the value of @v.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
#define atomic_read(v)	(ACCESS_ONCE((v)->counter))

@@ -43,102 +42,62 @@
 * @i: required value
 *
 * Atomically sets the value of @v to @i.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
#define atomic_set(v, i) (((v)->counter) = (i))

/**
 * atomic_add_return - add integer to atomic variable
 * @i: integer value to add
 * @v: pointer of type atomic_t
 *
 * Atomically adds @i to @v and returns the result
 * Note that the guaranteed useful range of an atomic_t is only 24 bits.
 */
static inline int atomic_add_return(int i, atomic_t *v)
{
	int retval;
#ifdef CONFIG_SMP
	int status;

	asm volatile(
		"1:	mov	%4,(_AAR,%3)	\n"
		"	mov	(_ADR,%3),%1	\n"
		"	add	%5,%1		\n"
		"	mov	%1,(_ADR,%3)	\n"
		"	mov	(_ADR,%3),%0	\n"	/* flush */
		"	mov	(_ASR,%3),%0	\n"
		"	or	%0,%0		\n"
		"	bne	1b		\n"
		: "=&r"(status), "=&r"(retval), "=m"(v->counter)
		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
		: "memory", "cc");

#else
	unsigned long flags;
#define ATOMIC_OP(op)							\
static inline void atomic_##op(int i, atomic_t *v)			\
{									\
	int retval, status;						\
									\
	asm volatile(							\
		"1:	mov	%4,(_AAR,%3)	\n"			\
		"	mov	(_ADR,%3),%1	\n"			\
		"	" #op "	%5,%1		\n"			\
		"	mov	%1,(_ADR,%3)	\n"			\
		"	mov	(_ADR,%3),%0	\n"	/* flush */	\
		"	mov	(_ASR,%3),%0	\n"			\
		"	or	%0,%0		\n"			\
		"	bne	1b		\n"			\
		: "=&r"(status), "=&r"(retval), "=m"(v->counter)	\
		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)	\
		: "memory", "cc");					\
}

	flags = arch_local_cli_save();
	retval = v->counter;
	retval += i;
	v->counter = retval;
	arch_local_irq_restore(flags);
#endif
	return retval;
#define ATOMIC_OP_RETURN(op)						\
static inline int atomic_##op##_return(int i, atomic_t *v)		\
{									\
	int retval, status;						\
									\
	asm volatile(							\
		"1:	mov	%4,(_AAR,%3)	\n"			\
		"	mov	(_ADR,%3),%1	\n"			\
		"	" #op "	%5,%1		\n"			\
		"	mov	%1,(_ADR,%3)	\n"			\
		"	mov	(_ADR,%3),%0	\n"	/* flush */	\
		"	mov	(_ASR,%3),%0	\n"			\
		"	or	%0,%0		\n"			\
		"	bne	1b		\n"			\
		: "=&r"(status), "=&r"(retval), "=m"(v->counter)	\
		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)	\
		: "memory", "cc");					\
	return retval;							\
}

/**
 * atomic_sub_return - subtract integer from atomic variable
 * @i: integer value to subtract
 * @v: pointer of type atomic_t
 *
 * Atomically subtracts @i from @v and returns the result
 * Note that the guaranteed useful range of an atomic_t is only 24 bits.
 */
static inline int atomic_sub_return(int i, atomic_t *v)
{
	int retval;
#ifdef CONFIG_SMP
	int status;
#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)

	asm volatile(
		"1:	mov	%4,(_AAR,%3)	\n"
		"	mov	(_ADR,%3),%1	\n"
		"	sub	%5,%1		\n"
		"	mov	%1,(_ADR,%3)	\n"
		"	mov	(_ADR,%3),%0	\n"	/* flush */
		"	mov	(_ASR,%3),%0	\n"
		"	or	%0,%0		\n"
		"	bne	1b		\n"
		: "=&r"(status), "=&r"(retval), "=m"(v->counter)
		: "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i)
		: "memory", "cc");
ATOMIC_OPS(add)
ATOMIC_OPS(sub)

#else
	unsigned long flags;
	flags = arch_local_cli_save();
	retval = v->counter;
	retval -= i;
	v->counter = retval;
	arch_local_irq_restore(flags);
#endif
	return retval;
}
#undef ATOMIC_OPS
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP

static inline int atomic_add_negative(int i, atomic_t *v)
{
	return atomic_add_return(i, v) < 0;
}

static inline void atomic_add(int i, atomic_t *v)
{
	atomic_add_return(i, v);
}

static inline void atomic_sub(int i, atomic_t *v)
{
	atomic_sub_return(i, v);
}

static inline void atomic_inc(atomic_t *v)
{
	atomic_add_return(1, v);