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