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