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