11da177e4SLinus Torvalds #ifndef _ASM_GENERIC_LOCAL_H 21da177e4SLinus Torvalds #define _ASM_GENERIC_LOCAL_H 31da177e4SLinus Torvalds 41da177e4SLinus Torvalds #include <linux/percpu.h> 5*60063497SArun Sharma #include <linux/atomic.h> 61da177e4SLinus Torvalds #include <asm/types.h> 71da177e4SLinus Torvalds 82cf8d82dSAndrew Morton /* 92cf8d82dSAndrew Morton * A signed long type for operations which are atomic for a single CPU. 102cf8d82dSAndrew Morton * Usually used in combination with per-cpu variables. 112cf8d82dSAndrew Morton * 122cf8d82dSAndrew Morton * This is the default implementation, which uses atomic_long_t. Which is 132cf8d82dSAndrew Morton * rather pointless. The whole point behind local_t is that some processors 142cf8d82dSAndrew Morton * can perform atomic adds and subtracts in a manner which is atomic wrt IRQs 152cf8d82dSAndrew Morton * running on this CPU. local_t allows exploitation of such capabilities. 162cf8d82dSAndrew Morton */ 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds /* Implement in terms of atomics. */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds /* Don't use typedef: don't want them to be mixed with atomic_t's. */ 211da177e4SLinus Torvalds typedef struct 221da177e4SLinus Torvalds { 23f5f5370dSKyle McMartin atomic_long_t a; 241da177e4SLinus Torvalds } local_t; 251da177e4SLinus Torvalds 26f5f5370dSKyle McMartin #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } 271da177e4SLinus Torvalds 282cf8d82dSAndrew Morton #define local_read(l) atomic_long_read(&(l)->a) 29f5f5370dSKyle McMartin #define local_set(l,i) atomic_long_set((&(l)->a),(i)) 30f5f5370dSKyle McMartin #define local_inc(l) atomic_long_inc(&(l)->a) 31f5f5370dSKyle McMartin #define local_dec(l) atomic_long_dec(&(l)->a) 32f5f5370dSKyle McMartin #define local_add(i,l) atomic_long_add((i),(&(l)->a)) 33f5f5370dSKyle McMartin #define local_sub(i,l) atomic_long_sub((i),(&(l)->a)) 341da177e4SLinus Torvalds 355e97b930SMathieu Desnoyers #define local_sub_and_test(i, l) atomic_long_sub_and_test((i), (&(l)->a)) 365e97b930SMathieu Desnoyers #define local_dec_and_test(l) atomic_long_dec_and_test(&(l)->a) 375e97b930SMathieu Desnoyers #define local_inc_and_test(l) atomic_long_inc_and_test(&(l)->a) 385e97b930SMathieu Desnoyers #define local_add_negative(i, l) atomic_long_add_negative((i), (&(l)->a)) 395e97b930SMathieu Desnoyers #define local_add_return(i, l) atomic_long_add_return((i), (&(l)->a)) 405e97b930SMathieu Desnoyers #define local_sub_return(i, l) atomic_long_sub_return((i), (&(l)->a)) 415e97b930SMathieu Desnoyers #define local_inc_return(l) atomic_long_inc_return(&(l)->a) 425e97b930SMathieu Desnoyers 435e97b930SMathieu Desnoyers #define local_cmpxchg(l, o, n) atomic_long_cmpxchg((&(l)->a), (o), (n)) 445e97b930SMathieu Desnoyers #define local_xchg(l, n) atomic_long_xchg((&(l)->a), (n)) 45bac9caf0SRoel Kluin #define local_add_unless(l, _a, u) atomic_long_add_unless((&(l)->a), (_a), (u)) 465e97b930SMathieu Desnoyers #define local_inc_not_zero(l) atomic_long_inc_not_zero(&(l)->a) 475e97b930SMathieu Desnoyers 481da177e4SLinus Torvalds /* Non-atomic variants, ie. preemption disabled and won't be touched 491da177e4SLinus Torvalds * in interrupt, etc. Some archs can optimize this case well. */ 501da177e4SLinus Torvalds #define __local_inc(l) local_set((l), local_read(l) + 1) 511da177e4SLinus Torvalds #define __local_dec(l) local_set((l), local_read(l) - 1) 521da177e4SLinus Torvalds #define __local_add(i,l) local_set((l), local_read(l) + (i)) 531da177e4SLinus Torvalds #define __local_sub(i,l) local_set((l), local_read(l) - (i)) 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #endif /* _ASM_GENERIC_LOCAL_H */ 56