diff options
Diffstat (limited to 'lib/atomic64.c')
| -rw-r--r-- | lib/atomic64.c | 32 | 
1 files changed, 28 insertions, 4 deletions
diff --git a/lib/atomic64.c b/lib/atomic64.c index 2886ebac6567..53c2d5edc826 100644 --- a/lib/atomic64.c +++ b/lib/atomic64.c @@ -96,17 +96,41 @@ long long atomic64_##op##_return(long long a, atomic64_t *v)		\  }									\  EXPORT_SYMBOL(atomic64_##op##_return); +#define ATOMIC64_FETCH_OP(op, c_op)					\ +long long atomic64_fetch_##op(long long a, atomic64_t *v)		\ +{									\ +	unsigned long flags;						\ +	raw_spinlock_t *lock = lock_addr(v);				\ +	long long val;							\ +									\ +	raw_spin_lock_irqsave(lock, flags);				\ +	val = v->counter;						\ +	v->counter c_op a;						\ +	raw_spin_unlock_irqrestore(lock, flags);			\ +	return val;							\ +}									\ +EXPORT_SYMBOL(atomic64_fetch_##op); +  #define ATOMIC64_OPS(op, c_op)						\  	ATOMIC64_OP(op, c_op)						\ -	ATOMIC64_OP_RETURN(op, c_op) +	ATOMIC64_OP_RETURN(op, c_op)					\ +	ATOMIC64_FETCH_OP(op, c_op)  ATOMIC64_OPS(add, +=)  ATOMIC64_OPS(sub, -=) -ATOMIC64_OP(and, &=) -ATOMIC64_OP(or, |=) -ATOMIC64_OP(xor, ^=)  #undef ATOMIC64_OPS +#define ATOMIC64_OPS(op, c_op)						\ +	ATOMIC64_OP(op, c_op)						\ +	ATOMIC64_OP_RETURN(op, c_op)					\ +	ATOMIC64_FETCH_OP(op, c_op) + +ATOMIC64_OPS(and, &=) +ATOMIC64_OPS(or, |=) +ATOMIC64_OPS(xor, ^=) + +#undef ATOMIC64_OPS +#undef ATOMIC64_FETCH_OP  #undef ATOMIC64_OP_RETURN  #undef ATOMIC64_OP  |