Changes in kernel/arch/amd64/include/atomic.h [9d58539:b17518e] in mainline
- File:
-
- 1 edited
-
kernel/arch/amd64/include/atomic.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/include/atomic.h
r9d58539 rb17518e 140 140 } 141 141 142 143 #define _atomic_cas_impl(pptr, exp_val, new_val, old_val, prefix) \ 144 asm volatile ( \ 145 prefix " cmpxchgq %[newval], %[ptr]\n" \ 146 : /* Output operands. */ \ 147 /* Old/current value is returned in eax. */ \ 148 [oldval] "=a" (old_val), \ 149 /* (*ptr) will be read and written to, hence "+" */ \ 150 [ptr] "+m" (*pptr) \ 151 : /* Input operands. */ \ 152 /* Expected value must be in eax. */ \ 153 [expval] "a" (exp_val), \ 154 /* The new value may be in any register. */ \ 155 [newval] "r" (new_val) \ 156 : "memory" \ 157 ) 158 159 /** Atomically compares and swaps the pointer at pptr. */ 160 NO_TRACE static inline void * atomic_cas_ptr(void **pptr, 161 void *exp_val, void *new_val) 162 { 163 void *old_val; 164 _atomic_cas_impl(pptr, exp_val, new_val, old_val, "lock\n"); 165 return old_val; 166 } 167 168 /** Compare-and-swap of a pointer that is atomic wrt to local cpu's interrupts. 169 * 170 * This function is NOT smp safe and is not atomic with respect to other cpus. 171 */ 172 NO_TRACE static inline void * atomic_cas_ptr_local(void **pptr, 173 void *exp_val, void *new_val) 174 { 175 void *old_val; 176 _atomic_cas_impl(pptr, exp_val, new_val, old_val, ""); 177 return old_val; 178 } 179 180 181 #define _atomic_swap_impl(pptr, new_val) \ 182 ({ \ 183 typeof(*(pptr)) new_in_old_out = new_val; \ 184 asm volatile ( \ 185 "xchgq %[val], %[p_ptr]\n" \ 186 : [val] "+r" (new_in_old_out), \ 187 [p_ptr] "+m" (*pptr) \ 188 ); \ 189 \ 190 new_in_old_out; \ 191 }) 192 193 /* 194 * Issuing a xchg instruction always implies lock prefix semantics. 195 * Therefore, it is cheaper to use a cmpxchg without a lock prefix 196 * in a loop. 197 */ 198 #define _atomic_swap_local_impl(pptr, new_val) \ 199 ({ \ 200 typeof(*(pptr)) exp_val; \ 201 typeof(*(pptr)) old_val; \ 202 \ 203 do { \ 204 exp_val = *pptr; \ 205 _atomic_cas_impl(pptr, exp_val, new_val, old_val, ""); \ 206 } while (old_val != exp_val); \ 207 \ 208 old_val; \ 209 }) 210 211 212 /** Atomicaly sets *ptr to val and returns the previous value. */ 213 NO_TRACE static inline void * atomic_set_return_ptr(void **pptr, void *val) 214 { 215 return _atomic_swap_impl(pptr, val); 216 } 217 218 /** Sets *ptr to new_val and returns the previous value. NOT smp safe. 219 * 220 * This function is only atomic wrt to local interrupts and it is 221 * NOT atomic wrt to other cpus. 222 */ 223 NO_TRACE static inline void * atomic_set_return_ptr_local( 224 void **pptr, void *new_val) 225 { 226 return _atomic_swap_local_impl(pptr, new_val); 227 } 228 229 /** Atomicaly sets *ptr to val and returns the previous value. */ 230 NO_TRACE static inline native_t atomic_set_return_native_t( 231 native_t *p, native_t val) 232 { 233 return _atomic_swap_impl(p, val); 234 } 235 236 /** Sets *ptr to new_val and returns the previous value. NOT smp safe. 237 * 238 * This function is only atomic wrt to local interrupts and it is 239 * NOT atomic wrt to other cpus. 240 */ 241 NO_TRACE static inline native_t atomic_set_return_native_t_local( 242 native_t *p, native_t new_val) 243 { 244 return _atomic_swap_local_impl(p, new_val); 245 } 246 247 248 #undef _atomic_cas_ptr_impl 249 #undef _atomic_swap_impl 250 #undef _atomic_swap_local_impl 251 142 252 #endif 143 253
Note:
See TracChangeset
for help on using the changeset viewer.
