1*584afc90SJason Wang #ifndef __ATOMIC_H 2*584afc90SJason Wang #define __ATOMIC_H 3*584afc90SJason Wang 4*584afc90SJason Wang typedef struct { 5*584afc90SJason Wang volatile int counter; 6*584afc90SJason Wang } atomic_t; 7*584afc90SJason Wang 8*584afc90SJason Wang #ifdef __i386__ 9*584afc90SJason Wang 10*584afc90SJason Wang /** 11*584afc90SJason Wang * atomic_read - read atomic variable 12*584afc90SJason Wang * @v: pointer of type atomic_t 13*584afc90SJason Wang * 14*584afc90SJason Wang * Atomically reads the value of @v. 15*584afc90SJason Wang */ 16*584afc90SJason Wang static inline int atomic_read(const atomic_t *v) 17*584afc90SJason Wang { 18*584afc90SJason Wang return v->counter; 19*584afc90SJason Wang } 20*584afc90SJason Wang 21*584afc90SJason Wang /** 22*584afc90SJason Wang * atomic_set - set atomic variable 23*584afc90SJason Wang * @v: pointer of type atomic_t 24*584afc90SJason Wang * @i: required value 25*584afc90SJason Wang * 26*584afc90SJason Wang * Atomically sets the value of @v to @i. 27*584afc90SJason Wang */ 28*584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i) 29*584afc90SJason Wang { 30*584afc90SJason Wang v->counter = i; 31*584afc90SJason Wang } 32*584afc90SJason Wang 33*584afc90SJason Wang /** 34*584afc90SJason Wang * atomic_inc - increment atomic variable 35*584afc90SJason Wang * @v: pointer of type atomic_t 36*584afc90SJason Wang * 37*584afc90SJason Wang * Atomically increments @v by 1. 38*584afc90SJason Wang */ 39*584afc90SJason Wang static inline void atomic_inc(atomic_t *v) 40*584afc90SJason Wang { 41*584afc90SJason Wang asm volatile("lock incl %0" 42*584afc90SJason Wang : "+m" (v->counter)); 43*584afc90SJason Wang } 44*584afc90SJason Wang 45*584afc90SJason Wang /** 46*584afc90SJason Wang * atomic_dec - decrement atomic variable 47*584afc90SJason Wang * @v: pointer of type atomic_t 48*584afc90SJason Wang * 49*584afc90SJason Wang * Atomically decrements @v by 1. 50*584afc90SJason Wang */ 51*584afc90SJason Wang static inline void atomic_dec(atomic_t *v) 52*584afc90SJason Wang { 53*584afc90SJason Wang asm volatile("lock decl %0" 54*584afc90SJason Wang : "+m" (v->counter)); 55*584afc90SJason Wang } 56*584afc90SJason Wang 57*584afc90SJason Wang typedef struct { 58*584afc90SJason Wang u64 __attribute__((aligned(8))) counter; 59*584afc90SJason Wang } atomic64_t; 60*584afc90SJason Wang 61*584afc90SJason Wang #define ATOMIC64_INIT(val) { (val) } 62*584afc90SJason Wang 63*584afc90SJason Wang /** 64*584afc90SJason Wang * atomic64_read - read atomic64 variable 65*584afc90SJason Wang * @ptr: pointer to type atomic64_t 66*584afc90SJason Wang * 67*584afc90SJason Wang * Atomically reads the value of @ptr and returns it. 68*584afc90SJason Wang */ 69*584afc90SJason Wang static inline u64 atomic64_read(atomic64_t *ptr) 70*584afc90SJason Wang { 71*584afc90SJason Wang u64 res; 72*584afc90SJason Wang 73*584afc90SJason Wang /* 74*584afc90SJason Wang * Note, we inline this atomic64_t primitive because 75*584afc90SJason Wang * it only clobbers EAX/EDX and leaves the others 76*584afc90SJason Wang * untouched. We also (somewhat subtly) rely on the 77*584afc90SJason Wang * fact that cmpxchg8b returns the current 64-bit value 78*584afc90SJason Wang * of the memory location we are touching: 79*584afc90SJason Wang */ 80*584afc90SJason Wang asm volatile("mov %%ebx, %%eax\n\t" 81*584afc90SJason Wang "mov %%ecx, %%edx\n\t" 82*584afc90SJason Wang "lock cmpxchg8b %1\n" 83*584afc90SJason Wang : "=&A" (res) 84*584afc90SJason Wang : "m" (*ptr) 85*584afc90SJason Wang ); 86*584afc90SJason Wang return res; 87*584afc90SJason Wang } 88*584afc90SJason Wang 89*584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); 90*584afc90SJason Wang 91*584afc90SJason Wang #elif defined(__x86_64__) 92*584afc90SJason Wang 93*584afc90SJason Wang /** 94*584afc90SJason Wang * atomic_read - read atomic variable 95*584afc90SJason Wang * @v: pointer of type atomic_t 96*584afc90SJason Wang * 97*584afc90SJason Wang * Atomically reads the value of @v. 98*584afc90SJason Wang */ 99*584afc90SJason Wang static inline int atomic_read(const atomic_t *v) 100*584afc90SJason Wang { 101*584afc90SJason Wang return v->counter; 102*584afc90SJason Wang } 103*584afc90SJason Wang 104*584afc90SJason Wang /** 105*584afc90SJason Wang * atomic_set - set atomic variable 106*584afc90SJason Wang * @v: pointer of type atomic_t 107*584afc90SJason Wang * @i: required value 108*584afc90SJason Wang * 109*584afc90SJason Wang * Atomically sets the value of @v to @i. 110*584afc90SJason Wang */ 111*584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i) 112*584afc90SJason Wang { 113*584afc90SJason Wang v->counter = i; 114*584afc90SJason Wang } 115*584afc90SJason Wang 116*584afc90SJason Wang /** 117*584afc90SJason Wang * atomic_inc - increment atomic variable 118*584afc90SJason Wang * @v: pointer of type atomic_t 119*584afc90SJason Wang * 120*584afc90SJason Wang * Atomically increments @v by 1. 121*584afc90SJason Wang */ 122*584afc90SJason Wang static inline void atomic_inc(atomic_t *v) 123*584afc90SJason Wang { 124*584afc90SJason Wang asm volatile("lock incl %0" 125*584afc90SJason Wang : "=m" (v->counter) 126*584afc90SJason Wang : "m" (v->counter)); 127*584afc90SJason Wang } 128*584afc90SJason Wang 129*584afc90SJason Wang /** 130*584afc90SJason Wang * atomic_dec - decrement atomic variable 131*584afc90SJason Wang * @v: pointer of type atomic_t 132*584afc90SJason Wang * 133*584afc90SJason Wang * Atomically decrements @v by 1. 134*584afc90SJason Wang */ 135*584afc90SJason Wang static inline void atomic_dec(atomic_t *v) 136*584afc90SJason Wang { 137*584afc90SJason Wang asm volatile("lock decl %0" 138*584afc90SJason Wang : "=m" (v->counter) 139*584afc90SJason Wang : "m" (v->counter)); 140*584afc90SJason Wang } 141*584afc90SJason Wang 142*584afc90SJason Wang typedef struct { 143*584afc90SJason Wang long long counter; 144*584afc90SJason Wang } atomic64_t; 145*584afc90SJason Wang 146*584afc90SJason Wang #define ATOMIC64_INIT(i) { (i) } 147*584afc90SJason Wang 148*584afc90SJason Wang /** 149*584afc90SJason Wang * atomic64_read - read atomic64 variable 150*584afc90SJason Wang * @v: pointer of type atomic64_t 151*584afc90SJason Wang * 152*584afc90SJason Wang * Atomically reads the value of @v. 153*584afc90SJason Wang * Doesn't imply a read memory barrier. 154*584afc90SJason Wang */ 155*584afc90SJason Wang static inline long atomic64_read(const atomic64_t *v) 156*584afc90SJason Wang { 157*584afc90SJason Wang return v->counter; 158*584afc90SJason Wang } 159*584afc90SJason Wang 160*584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); 161*584afc90SJason Wang 162*584afc90SJason Wang #endif 163*584afc90SJason Wang 164*584afc90SJason Wang #endif 165