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