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: Peter 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: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
ef31563e95
commit
e69a0ef766
|
@ -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;
|
||||
|
||||
flags = arch_local_cli_save();
|
||||
retval = v->counter;
|
||||
retval += i;
|
||||
v->counter = retval;
|
||||
arch_local_irq_restore(flags);
|
||||
#endif
|
||||
return retval;
|
||||
#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"); \
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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");
|
||||
|
||||
#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;
|
||||
#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; \
|
||||
}
|
||||
|
||||
#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
|
||||
|
||||
ATOMIC_OPS(add)
|
||||
ATOMIC_OPS(sub)
|
||||
|
||||
#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);
|
||||
|
|
Loading…
Reference in New Issue