diff options
Diffstat (limited to 'include/asm-generic/atomic.h')
| -rw-r--r-- | include/asm-generic/atomic.h | 47 | 
1 files changed, 47 insertions, 0 deletions
| diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 74f1a3704d7a..9ed8b987185b 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -61,6 +61,18 @@ static inline int atomic_##op##_return(int i, atomic_t *v)		\  	return c c_op i;						\  } +#define ATOMIC_FETCH_OP(op, c_op)					\ +static inline int atomic_fetch_##op(int i, atomic_t *v)			\ +{									\ +	int c, old;							\ +									\ +	c = v->counter;							\ +	while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)		\ +		c = old;						\ +									\ +	return c;							\ +} +  #else  #include <linux/irqflags.h> @@ -88,6 +100,20 @@ static inline int atomic_##op##_return(int i, atomic_t *v)		\  	return ret;							\  } +#define ATOMIC_FETCH_OP(op, c_op)					\ +static inline int atomic_fetch_##op(int i, atomic_t *v)			\ +{									\ +	unsigned long flags;						\ +	int ret;							\ +									\ +	raw_local_irq_save(flags);					\ +	ret = v->counter;						\ +	v->counter = v->counter c_op i;					\ +	raw_local_irq_restore(flags);					\ +									\ +	return ret;							\ +} +  #endif /* CONFIG_SMP */  #ifndef atomic_add_return @@ -98,6 +124,26 @@ ATOMIC_OP_RETURN(add, +)  ATOMIC_OP_RETURN(sub, -)  #endif +#ifndef atomic_fetch_add +ATOMIC_FETCH_OP(add, +) +#endif + +#ifndef atomic_fetch_sub +ATOMIC_FETCH_OP(sub, -) +#endif + +#ifndef atomic_fetch_and +ATOMIC_FETCH_OP(and, &) +#endif + +#ifndef atomic_fetch_or +ATOMIC_FETCH_OP(or, |) +#endif + +#ifndef atomic_fetch_xor +ATOMIC_FETCH_OP(xor, ^) +#endif +  #ifndef atomic_and  ATOMIC_OP(and, &)  #endif @@ -110,6 +156,7 @@ ATOMIC_OP(or, |)  ATOMIC_OP(xor, ^)  #endif +#undef ATOMIC_FETCH_OP  #undef ATOMIC_OP_RETURN  #undef ATOMIC_OP |