1*1da177e4SLinus Torvalds #ifndef _ASM_GENERIC_LOCAL_H 2*1da177e4SLinus Torvalds #define _ASM_GENERIC_LOCAL_H 3*1da177e4SLinus Torvalds 4*1da177e4SLinus Torvalds #include <linux/config.h> 5*1da177e4SLinus Torvalds #include <linux/percpu.h> 6*1da177e4SLinus Torvalds #include <linux/hardirq.h> 7*1da177e4SLinus Torvalds #include <asm/types.h> 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds /* An unsigned long type for operations which are atomic for a single 10*1da177e4SLinus Torvalds * CPU. Usually used in combination with per-cpu variables. */ 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #if BITS_PER_LONG == 32 13*1da177e4SLinus Torvalds /* Implement in terms of atomics. */ 14*1da177e4SLinus Torvalds 15*1da177e4SLinus Torvalds /* Don't use typedef: don't want them to be mixed with atomic_t's. */ 16*1da177e4SLinus Torvalds typedef struct 17*1da177e4SLinus Torvalds { 18*1da177e4SLinus Torvalds atomic_t a; 19*1da177e4SLinus Torvalds } local_t; 20*1da177e4SLinus Torvalds 21*1da177e4SLinus Torvalds #define LOCAL_INIT(i) { ATOMIC_INIT(i) } 22*1da177e4SLinus Torvalds 23*1da177e4SLinus Torvalds #define local_read(l) ((unsigned long)atomic_read(&(l)->a)) 24*1da177e4SLinus Torvalds #define local_set(l,i) atomic_set((&(l)->a),(i)) 25*1da177e4SLinus Torvalds #define local_inc(l) atomic_inc(&(l)->a) 26*1da177e4SLinus Torvalds #define local_dec(l) atomic_dec(&(l)->a) 27*1da177e4SLinus Torvalds #define local_add(i,l) atomic_add((i),(&(l)->a)) 28*1da177e4SLinus Torvalds #define local_sub(i,l) atomic_sub((i),(&(l)->a)) 29*1da177e4SLinus Torvalds 30*1da177e4SLinus Torvalds /* Non-atomic variants, ie. preemption disabled and won't be touched 31*1da177e4SLinus Torvalds * in interrupt, etc. Some archs can optimize this case well. */ 32*1da177e4SLinus Torvalds #define __local_inc(l) local_set((l), local_read(l) + 1) 33*1da177e4SLinus Torvalds #define __local_dec(l) local_set((l), local_read(l) - 1) 34*1da177e4SLinus Torvalds #define __local_add(i,l) local_set((l), local_read(l) + (i)) 35*1da177e4SLinus Torvalds #define __local_sub(i,l) local_set((l), local_read(l) - (i)) 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds #else /* ... can't use atomics. */ 38*1da177e4SLinus Torvalds /* Implement in terms of three variables. 39*1da177e4SLinus Torvalds Another option would be to use local_irq_save/restore. */ 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds typedef struct 42*1da177e4SLinus Torvalds { 43*1da177e4SLinus Torvalds /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */ 44*1da177e4SLinus Torvalds unsigned long v[3]; 45*1da177e4SLinus Torvalds } local_t; 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds #define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()]) 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds #define LOCAL_INIT(i) { { (i), 0, 0 } } 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds static inline unsigned long local_read(local_t *l) 52*1da177e4SLinus Torvalds { 53*1da177e4SLinus Torvalds return l->v[0] + l->v[1] + l->v[2]; 54*1da177e4SLinus Torvalds } 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds static inline void local_set(local_t *l, unsigned long v) 57*1da177e4SLinus Torvalds { 58*1da177e4SLinus Torvalds l->v[0] = v; 59*1da177e4SLinus Torvalds l->v[1] = l->v[2] = 0; 60*1da177e4SLinus Torvalds } 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds static inline void local_inc(local_t *l) 63*1da177e4SLinus Torvalds { 64*1da177e4SLinus Torvalds preempt_disable(); 65*1da177e4SLinus Torvalds _LOCAL_VAR(l)++; 66*1da177e4SLinus Torvalds preempt_enable(); 67*1da177e4SLinus Torvalds } 68*1da177e4SLinus Torvalds 69*1da177e4SLinus Torvalds static inline void local_dec(local_t *l) 70*1da177e4SLinus Torvalds { 71*1da177e4SLinus Torvalds preempt_disable(); 72*1da177e4SLinus Torvalds _LOCAL_VAR(l)--; 73*1da177e4SLinus Torvalds preempt_enable(); 74*1da177e4SLinus Torvalds } 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds static inline void local_add(unsigned long v, local_t *l) 77*1da177e4SLinus Torvalds { 78*1da177e4SLinus Torvalds preempt_disable(); 79*1da177e4SLinus Torvalds _LOCAL_VAR(l) += v; 80*1da177e4SLinus Torvalds preempt_enable(); 81*1da177e4SLinus Torvalds } 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds static inline void local_sub(unsigned long v, local_t *l) 84*1da177e4SLinus Torvalds { 85*1da177e4SLinus Torvalds preempt_disable(); 86*1da177e4SLinus Torvalds _LOCAL_VAR(l) -= v; 87*1da177e4SLinus Torvalds preempt_enable(); 88*1da177e4SLinus Torvalds } 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds /* Non-atomic variants, ie. preemption disabled and won't be touched 91*1da177e4SLinus Torvalds * in interrupt, etc. Some archs can optimize this case well. */ 92*1da177e4SLinus Torvalds #define __local_inc(l) ((l)->v[0]++) 93*1da177e4SLinus Torvalds #define __local_dec(l) ((l)->v[0]--) 94*1da177e4SLinus Torvalds #define __local_add(i,l) ((l)->v[0] += (i)) 95*1da177e4SLinus Torvalds #define __local_sub(i,l) ((l)->v[0] -= (i)) 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds #endif /* Non-atomic implementation */ 98*1da177e4SLinus Torvalds 99*1da177e4SLinus Torvalds /* Use these for per-cpu local_t variables: on some archs they are 100*1da177e4SLinus Torvalds * much more efficient than these naive implementations. Note they take 101*1da177e4SLinus Torvalds * a variable (eg. mystruct.foo), not an address. 102*1da177e4SLinus Torvalds */ 103*1da177e4SLinus Torvalds #define cpu_local_read(v) local_read(&__get_cpu_var(v)) 104*1da177e4SLinus Torvalds #define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) 105*1da177e4SLinus Torvalds #define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) 106*1da177e4SLinus Torvalds #define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) 107*1da177e4SLinus Torvalds #define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) 108*1da177e4SLinus Torvalds #define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds /* Non-atomic increments, ie. preemption disabled and won't be touched 111*1da177e4SLinus Torvalds * in interrupt, etc. Some archs can optimize this case well. 112*1da177e4SLinus Torvalds */ 113*1da177e4SLinus Torvalds #define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v)) 114*1da177e4SLinus Torvalds #define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v)) 115*1da177e4SLinus Torvalds #define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v)) 116*1da177e4SLinus Torvalds #define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v)) 117*1da177e4SLinus Torvalds 118*1da177e4SLinus Torvalds #endif /* _ASM_GENERIC_LOCAL_H */ 119