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