1584afc90SJason Wang #ifndef __ATOMIC_H 2584afc90SJason Wang #define __ATOMIC_H 3584afc90SJason Wang 4*ae21b795SPeter Xu #include "asm-generic/atomic.h" 5*ae21b795SPeter Xu 6584afc90SJason Wang typedef struct { 7584afc90SJason Wang volatile int counter; 8584afc90SJason Wang } atomic_t; 9584afc90SJason Wang 10584afc90SJason Wang #ifdef __i386__ 11584afc90SJason Wang 12584afc90SJason Wang /** 13584afc90SJason Wang * atomic_read - read atomic variable 14584afc90SJason Wang * @v: pointer of type atomic_t 15584afc90SJason Wang * 16584afc90SJason Wang * Atomically reads the value of @v. 17584afc90SJason Wang */ 18584afc90SJason Wang static inline int atomic_read(const atomic_t *v) 19584afc90SJason Wang { 20584afc90SJason Wang return v->counter; 21584afc90SJason Wang } 22584afc90SJason Wang 23584afc90SJason Wang /** 24584afc90SJason Wang * atomic_set - set atomic variable 25584afc90SJason Wang * @v: pointer of type atomic_t 26584afc90SJason Wang * @i: required value 27584afc90SJason Wang * 28584afc90SJason Wang * Atomically sets the value of @v to @i. 29584afc90SJason Wang */ 30584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i) 31584afc90SJason Wang { 32584afc90SJason Wang v->counter = i; 33584afc90SJason Wang } 34584afc90SJason Wang 35584afc90SJason Wang /** 36584afc90SJason Wang * atomic_inc - increment atomic variable 37584afc90SJason Wang * @v: pointer of type atomic_t 38584afc90SJason Wang * 39584afc90SJason Wang * Atomically increments @v by 1. 40584afc90SJason Wang */ 41584afc90SJason Wang static inline void atomic_inc(atomic_t *v) 42584afc90SJason Wang { 43584afc90SJason Wang asm volatile("lock incl %0" 44584afc90SJason Wang : "+m" (v->counter)); 45584afc90SJason Wang } 46584afc90SJason Wang 47584afc90SJason Wang /** 48584afc90SJason Wang * atomic_dec - decrement atomic variable 49584afc90SJason Wang * @v: pointer of type atomic_t 50584afc90SJason Wang * 51584afc90SJason Wang * Atomically decrements @v by 1. 52584afc90SJason Wang */ 53584afc90SJason Wang static inline void atomic_dec(atomic_t *v) 54584afc90SJason Wang { 55584afc90SJason Wang asm volatile("lock decl %0" 56584afc90SJason Wang : "+m" (v->counter)); 57584afc90SJason Wang } 58584afc90SJason Wang 59584afc90SJason Wang typedef struct { 60584afc90SJason Wang u64 __attribute__((aligned(8))) counter; 61584afc90SJason Wang } atomic64_t; 62584afc90SJason Wang 63584afc90SJason Wang #define ATOMIC64_INIT(val) { (val) } 64584afc90SJason Wang 65584afc90SJason Wang /** 66584afc90SJason Wang * atomic64_read - read atomic64 variable 67584afc90SJason Wang * @ptr: pointer to type atomic64_t 68584afc90SJason Wang * 69584afc90SJason Wang * Atomically reads the value of @ptr and returns it. 70584afc90SJason Wang */ 71584afc90SJason Wang static inline u64 atomic64_read(atomic64_t *ptr) 72584afc90SJason Wang { 73584afc90SJason Wang u64 res; 74584afc90SJason Wang 75584afc90SJason Wang /* 76584afc90SJason Wang * Note, we inline this atomic64_t primitive because 77584afc90SJason Wang * it only clobbers EAX/EDX and leaves the others 78584afc90SJason Wang * untouched. We also (somewhat subtly) rely on the 79584afc90SJason Wang * fact that cmpxchg8b returns the current 64-bit value 80584afc90SJason Wang * of the memory location we are touching: 81584afc90SJason Wang */ 82584afc90SJason Wang asm volatile("mov %%ebx, %%eax\n\t" 83584afc90SJason Wang "mov %%ecx, %%edx\n\t" 84584afc90SJason Wang "lock cmpxchg8b %1\n" 85584afc90SJason Wang : "=&A" (res) 86584afc90SJason Wang : "m" (*ptr) 87584afc90SJason Wang ); 88584afc90SJason Wang return res; 89584afc90SJason Wang } 90584afc90SJason Wang 91584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); 92584afc90SJason Wang 93584afc90SJason Wang #elif defined(__x86_64__) 94584afc90SJason Wang 95584afc90SJason Wang /** 96584afc90SJason Wang * atomic_read - read atomic variable 97584afc90SJason Wang * @v: pointer of type atomic_t 98584afc90SJason Wang * 99584afc90SJason Wang * Atomically reads the value of @v. 100584afc90SJason Wang */ 101584afc90SJason Wang static inline int atomic_read(const atomic_t *v) 102584afc90SJason Wang { 103584afc90SJason Wang return v->counter; 104584afc90SJason Wang } 105584afc90SJason Wang 106584afc90SJason Wang /** 107584afc90SJason Wang * atomic_set - set atomic variable 108584afc90SJason Wang * @v: pointer of type atomic_t 109584afc90SJason Wang * @i: required value 110584afc90SJason Wang * 111584afc90SJason Wang * Atomically sets the value of @v to @i. 112584afc90SJason Wang */ 113584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i) 114584afc90SJason Wang { 115584afc90SJason Wang v->counter = i; 116584afc90SJason Wang } 117584afc90SJason Wang 118584afc90SJason Wang /** 119584afc90SJason Wang * atomic_inc - increment atomic variable 120584afc90SJason Wang * @v: pointer of type atomic_t 121584afc90SJason Wang * 122584afc90SJason Wang * Atomically increments @v by 1. 123584afc90SJason Wang */ 124584afc90SJason Wang static inline void atomic_inc(atomic_t *v) 125584afc90SJason Wang { 126584afc90SJason Wang asm volatile("lock incl %0" 127584afc90SJason Wang : "=m" (v->counter) 128584afc90SJason Wang : "m" (v->counter)); 129584afc90SJason Wang } 130584afc90SJason Wang 131584afc90SJason Wang /** 132584afc90SJason Wang * atomic_dec - decrement atomic variable 133584afc90SJason Wang * @v: pointer of type atomic_t 134584afc90SJason Wang * 135584afc90SJason Wang * Atomically decrements @v by 1. 136584afc90SJason Wang */ 137584afc90SJason Wang static inline void atomic_dec(atomic_t *v) 138584afc90SJason Wang { 139584afc90SJason Wang asm volatile("lock decl %0" 140584afc90SJason Wang : "=m" (v->counter) 141584afc90SJason Wang : "m" (v->counter)); 142584afc90SJason Wang } 143584afc90SJason Wang 144584afc90SJason Wang typedef struct { 145584afc90SJason Wang long long counter; 146584afc90SJason Wang } atomic64_t; 147584afc90SJason Wang 148584afc90SJason Wang #define ATOMIC64_INIT(i) { (i) } 149584afc90SJason Wang 150584afc90SJason Wang /** 151584afc90SJason Wang * atomic64_read - read atomic64 variable 152584afc90SJason Wang * @v: pointer of type atomic64_t 153584afc90SJason Wang * 154584afc90SJason Wang * Atomically reads the value of @v. 155584afc90SJason Wang * Doesn't imply a read memory barrier. 156584afc90SJason Wang */ 157584afc90SJason Wang static inline long atomic64_read(const atomic64_t *v) 158584afc90SJason Wang { 159584afc90SJason Wang return v->counter; 160584afc90SJason Wang } 161584afc90SJason Wang 162584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); 163584afc90SJason Wang 164584afc90SJason Wang #endif 165584afc90SJason Wang 166584afc90SJason Wang #endif 167