2009-05-13 22:56:29 +00:00
# ifndef _ASM_GENERIC_ATOMIC_LONG_H
# define _ASM_GENERIC_ATOMIC_LONG_H
2006-01-06 00:11:20 -08:00
/*
* Copyright ( C ) 2005 Silicon Graphics , Inc .
2008-07-04 09:59:22 -07:00
* Christoph Lameter
2006-01-06 00:11:20 -08:00
*
* Allows to provide arch independent atomic definitions without the need to
* edit all arch specific atomic . h files .
*/
2006-01-08 01:00:29 -08:00
# include <asm/types.h>
2006-01-06 00:11:20 -08:00
/*
* Suppport for atomic_long_t
*
* Casts for parameters are avoided for existing atomic functions in order to
* avoid issues with cast - as - lval under gcc 4. x and other limitations that the
* macros of a platform may have .
*/
# if BITS_PER_LONG == 64
typedef atomic64_t atomic_long_t ;
# define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i)
2015-08-06 17:54:38 +01:00
# define ATOMIC_LONG_PFX(x) atomic64 ## x
2006-01-06 00:11:20 -08:00
2015-08-06 17:54:38 +01:00
# else
2006-01-06 00:11:20 -08:00
typedef atomic_t atomic_long_t ;
# define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)
2015-08-06 17:54:38 +01:00
# define ATOMIC_LONG_PFX(x) atomic ## x
# endif
2015-08-06 17:54:39 +01:00
# define ATOMIC_LONG_READ_OP(mo) \
2015-09-18 13:22:52 +02:00
static inline long atomic_long_read # # mo ( const atomic_long_t * l ) \
2015-08-06 17:54:39 +01:00
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
return ( long ) ATOMIC_LONG_PFX ( _read # # mo ) ( v ) ; \
2006-01-06 00:11:20 -08:00
}
2015-08-06 17:54:39 +01:00
ATOMIC_LONG_READ_OP ( )
ATOMIC_LONG_READ_OP ( _acquire )
2006-01-06 00:11:20 -08:00
2015-08-06 17:54:39 +01:00
# undef ATOMIC_LONG_READ_OP
2006-01-06 00:11:20 -08:00
2015-08-06 17:54:39 +01:00
# define ATOMIC_LONG_SET_OP(mo) \
static inline void atomic_long_set # # mo ( atomic_long_t * l , long i ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
ATOMIC_LONG_PFX ( _set # # mo ) ( v , i ) ; \
}
ATOMIC_LONG_SET_OP ( )
ATOMIC_LONG_SET_OP ( _release )
# undef ATOMIC_LONG_SET_OP
# define ATOMIC_LONG_ADD_SUB_OP(op, mo) \
static inline long \
atomic_long_ # # op # # _return # # mo ( long i , atomic_long_t * l ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
return ( long ) ATOMIC_LONG_PFX ( _ # # op # # _return # # mo ) ( i , v ) ; \
2006-01-06 00:11:20 -08:00
}
2015-08-06 17:54:39 +01:00
ATOMIC_LONG_ADD_SUB_OP ( add , )
ATOMIC_LONG_ADD_SUB_OP ( add , _relaxed )
ATOMIC_LONG_ADD_SUB_OP ( add , _acquire )
ATOMIC_LONG_ADD_SUB_OP ( add , _release )
ATOMIC_LONG_ADD_SUB_OP ( sub , )
ATOMIC_LONG_ADD_SUB_OP ( sub , _relaxed )
ATOMIC_LONG_ADD_SUB_OP ( sub , _acquire )
ATOMIC_LONG_ADD_SUB_OP ( sub , _release )
# undef ATOMIC_LONG_ADD_SUB_OP
# define atomic_long_cmpxchg_relaxed(l, old, new) \
( ATOMIC_LONG_PFX ( _cmpxchg_relaxed ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( l ) , \
( old ) , ( new ) ) )
# define atomic_long_cmpxchg_acquire(l, old, new) \
( ATOMIC_LONG_PFX ( _cmpxchg_acquire ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( l ) , \
( old ) , ( new ) ) )
# define atomic_long_cmpxchg_release(l, old, new) \
( ATOMIC_LONG_PFX ( _cmpxchg_release ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( l ) , \
( old ) , ( new ) ) )
# define atomic_long_cmpxchg(l, old, new) \
( ATOMIC_LONG_PFX ( _cmpxchg ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( l ) , ( old ) , ( new ) ) )
# define atomic_long_xchg_relaxed(v, new) \
( ATOMIC_LONG_PFX ( _xchg_relaxed ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( v ) , ( new ) ) )
# define atomic_long_xchg_acquire(v, new) \
( ATOMIC_LONG_PFX ( _xchg_acquire ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( v ) , ( new ) ) )
# define atomic_long_xchg_release(v, new) \
( ATOMIC_LONG_PFX ( _xchg_release ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( v ) , ( new ) ) )
# define atomic_long_xchg(v, new) \
( ATOMIC_LONG_PFX ( _xchg ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( v ) , ( new ) ) )
2006-01-06 00:11:20 -08:00
2016-03-17 14:22:41 -07:00
static __always_inline void atomic_long_inc ( atomic_long_t * l )
2006-01-06 00:11:20 -08:00
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2006-01-06 00:11:20 -08:00
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _inc ) ( v ) ;
2006-01-06 00:11:20 -08:00
}
2016-03-17 14:22:41 -07:00
static __always_inline void atomic_long_dec ( atomic_long_t * l )
2006-01-06 00:11:20 -08:00
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2006-01-06 00:11:20 -08:00
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _dec ) ( v ) ;
2006-01-06 00:11:20 -08:00
}
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
# define ATOMIC_LONG_FETCH_OP(op, mo) \
static inline long \
atomic_long_fetch_ # # op # # mo ( long i , atomic_long_t * l ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
return ( long ) ATOMIC_LONG_PFX ( _fetch_ # # op # # mo ) ( i , v ) ; \
}
ATOMIC_LONG_FETCH_OP ( add , )
ATOMIC_LONG_FETCH_OP ( add , _relaxed )
ATOMIC_LONG_FETCH_OP ( add , _acquire )
ATOMIC_LONG_FETCH_OP ( add , _release )
ATOMIC_LONG_FETCH_OP ( sub , )
ATOMIC_LONG_FETCH_OP ( sub , _relaxed )
ATOMIC_LONG_FETCH_OP ( sub , _acquire )
ATOMIC_LONG_FETCH_OP ( sub , _release )
ATOMIC_LONG_FETCH_OP ( and , )
ATOMIC_LONG_FETCH_OP ( and , _relaxed )
ATOMIC_LONG_FETCH_OP ( and , _acquire )
ATOMIC_LONG_FETCH_OP ( and , _release )
ATOMIC_LONG_FETCH_OP ( andnot , )
ATOMIC_LONG_FETCH_OP ( andnot , _relaxed )
ATOMIC_LONG_FETCH_OP ( andnot , _acquire )
ATOMIC_LONG_FETCH_OP ( andnot , _release )
ATOMIC_LONG_FETCH_OP ( or , )
ATOMIC_LONG_FETCH_OP ( or , _relaxed )
ATOMIC_LONG_FETCH_OP ( or , _acquire )
ATOMIC_LONG_FETCH_OP ( or , _release )
ATOMIC_LONG_FETCH_OP ( xor , )
ATOMIC_LONG_FETCH_OP ( xor , _relaxed )
ATOMIC_LONG_FETCH_OP ( xor , _acquire )
ATOMIC_LONG_FETCH_OP ( xor , _release )
2016-06-28 14:56:51 -07:00
# undef ATOMIC_LONG_FETCH_OP
# define ATOMIC_LONG_FETCH_INC_DEC_OP(op, mo) \
static inline long \
atomic_long_fetch_ # # op # # mo ( atomic_long_t * l ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
return ( long ) ATOMIC_LONG_PFX ( _fetch_ # # op # # mo ) ( v ) ; \
}
ATOMIC_LONG_FETCH_INC_DEC_OP ( inc , )
ATOMIC_LONG_FETCH_INC_DEC_OP ( inc , _relaxed )
ATOMIC_LONG_FETCH_INC_DEC_OP ( inc , _acquire )
ATOMIC_LONG_FETCH_INC_DEC_OP ( inc , _release )
ATOMIC_LONG_FETCH_INC_DEC_OP ( dec , )
ATOMIC_LONG_FETCH_INC_DEC_OP ( dec , _relaxed )
ATOMIC_LONG_FETCH_INC_DEC_OP ( dec , _acquire )
ATOMIC_LONG_FETCH_INC_DEC_OP ( dec , _release )
# undef ATOMIC_LONG_FETCH_INC_DEC_OP
2015-09-18 15:04:59 +02:00
# define ATOMIC_LONG_OP(op) \
2016-03-17 14:22:41 -07:00
static __always_inline void \
2015-09-18 15:04:59 +02:00
atomic_long_ # # op ( long i , atomic_long_t * l ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
ATOMIC_LONG_PFX ( _ # # op ) ( i , v ) ; \
2006-01-06 00:11:20 -08:00
}
2015-09-18 15:04:59 +02:00
ATOMIC_LONG_OP ( add )
ATOMIC_LONG_OP ( sub )
ATOMIC_LONG_OP ( and )
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new
atomic primitives add on the generic infrastructure to expose and use
it.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-04-18 00:54:38 +02:00
ATOMIC_LONG_OP ( andnot )
2015-09-18 15:04:59 +02:00
ATOMIC_LONG_OP ( or )
ATOMIC_LONG_OP ( xor )
2006-01-06 00:11:20 -08:00
2015-09-18 15:04:59 +02:00
# undef ATOMIC_LONG_OP
2006-01-06 00:11:20 -08:00
2007-05-08 00:34:19 -07:00
static inline int atomic_long_sub_and_test ( long i , atomic_long_t * l )
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2007-05-08 00:34:19 -07:00
2015-08-06 17:54:38 +01:00
return ATOMIC_LONG_PFX ( _sub_and_test ) ( i , v ) ;
2007-05-08 00:34:19 -07:00
}
static inline int atomic_long_dec_and_test ( atomic_long_t * l )
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2007-05-08 00:34:19 -07:00
2015-08-06 17:54:38 +01:00
return ATOMIC_LONG_PFX ( _dec_and_test ) ( v ) ;
2007-05-08 00:34:19 -07:00
}
static inline int atomic_long_inc_and_test ( atomic_long_t * l )
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2007-05-08 00:34:19 -07:00
2015-08-06 17:54:38 +01:00
return ATOMIC_LONG_PFX ( _inc_and_test ) ( v ) ;
2007-05-08 00:34:19 -07:00
}
static inline int atomic_long_add_negative ( long i , atomic_long_t * l )
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2007-05-08 00:34:19 -07:00
2015-08-06 17:54:38 +01:00
return ATOMIC_LONG_PFX ( _add_negative ) ( i , v ) ;
2007-05-08 00:34:19 -07:00
}
2015-09-30 13:03:11 -07:00
# define ATOMIC_LONG_INC_DEC_OP(op, mo) \
static inline long \
atomic_long_ # # op # # _return # # mo ( atomic_long_t * l ) \
{ \
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ; \
\
return ( long ) ATOMIC_LONG_PFX ( _ # # op # # _return # # mo ) ( v ) ; \
2007-05-08 00:34:19 -07:00
}
2015-09-30 13:03:11 -07:00
ATOMIC_LONG_INC_DEC_OP ( inc , )
ATOMIC_LONG_INC_DEC_OP ( inc , _relaxed )
ATOMIC_LONG_INC_DEC_OP ( inc , _acquire )
ATOMIC_LONG_INC_DEC_OP ( inc , _release )
ATOMIC_LONG_INC_DEC_OP ( dec , )
ATOMIC_LONG_INC_DEC_OP ( dec , _relaxed )
ATOMIC_LONG_INC_DEC_OP ( dec , _acquire )
ATOMIC_LONG_INC_DEC_OP ( dec , _release )
# undef ATOMIC_LONG_INC_DEC_OP
2007-05-08 00:34:19 -07:00
2007-05-08 00:34:38 -07:00
static inline long atomic_long_add_unless ( atomic_long_t * l , long a , long u )
{
2015-08-06 17:54:38 +01:00
ATOMIC_LONG_PFX ( _t ) * v = ( ATOMIC_LONG_PFX ( _t ) * ) l ;
2007-05-08 00:34:38 -07:00
2015-08-06 17:54:38 +01:00
return ( long ) ATOMIC_LONG_PFX ( _add_unless ) ( v , a , u ) ;
2007-05-08 00:34:38 -07:00
}
2007-05-08 00:34:19 -07:00
2015-08-06 17:54:38 +01:00
# define atomic_long_inc_not_zero(l) \
ATOMIC_LONG_PFX ( _inc_not_zero ) ( ( ATOMIC_LONG_PFX ( _t ) * ) ( l ) )
2006-12-06 20:40:28 -08:00
2009-05-13 22:56:29 +00:00
# endif /* _ASM_GENERIC_ATOMIC_LONG_H */