aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/cmpxchg_32.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-x86/cmpxchg_32.h')
-rw-r--r--include/asm-x86/cmpxchg_32.h122
1 files changed, 79 insertions, 43 deletions
diff --git a/include/asm-x86/cmpxchg_32.h b/include/asm-x86/cmpxchg_32.h
index f86ede28f6dc..cea1dae288a7 100644
--- a/include/asm-x86/cmpxchg_32.h
+++ b/include/asm-x86/cmpxchg_32.h
@@ -105,15 +105,24 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
105 105
106#ifdef CONFIG_X86_CMPXCHG 106#ifdef CONFIG_X86_CMPXCHG
107#define __HAVE_ARCH_CMPXCHG 1 107#define __HAVE_ARCH_CMPXCHG 1
108#define cmpxchg(ptr,o,n)\ 108#define cmpxchg(ptr, o, n) \
109 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ 109 ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
110 (unsigned long)(n),sizeof(*(ptr)))) 110 (unsigned long)(n), sizeof(*(ptr))))
111#define sync_cmpxchg(ptr,o,n)\ 111#define sync_cmpxchg(ptr, o, n) \
112 ((__typeof__(*(ptr)))__sync_cmpxchg((ptr),(unsigned long)(o),\ 112 ((__typeof__(*(ptr)))__sync_cmpxchg((ptr), (unsigned long)(o), \
113 (unsigned long)(n),sizeof(*(ptr)))) 113 (unsigned long)(n), sizeof(*(ptr))))
114#define cmpxchg_local(ptr,o,n)\ 114#define cmpxchg_local(ptr, o, n) \
115 ((__typeof__(*(ptr)))__cmpxchg_local((ptr),(unsigned long)(o),\ 115 ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
116 (unsigned long)(n),sizeof(*(ptr)))) 116 (unsigned long)(n), sizeof(*(ptr))))
117#endif
118
119#ifdef CONFIG_X86_CMPXCHG64
120#define cmpxchg64(ptr, o, n) \
121 ((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
122 (unsigned long long)(n)))
123#define cmpxchg64_local(ptr, o, n) \
124 ((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o),\
125 (unsigned long long)(n)))
117#endif 126#endif
118 127
119static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, 128static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
@@ -203,6 +212,34 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
203 return old; 212 return old;
204} 213}
205 214
215static inline unsigned long long __cmpxchg64(volatile void *ptr,
216 unsigned long long old, unsigned long long new)
217{
218 unsigned long long prev;
219 __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
220 : "=A"(prev)
221 : "b"((unsigned long)new),
222 "c"((unsigned long)(new >> 32)),
223 "m"(*__xg(ptr)),
224 "0"(old)
225 : "memory");
226 return prev;
227}
228
229static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
230 unsigned long long old, unsigned long long new)
231{
232 unsigned long long prev;
233 __asm__ __volatile__("cmpxchg8b %3"
234 : "=A"(prev)
235 : "b"((unsigned long)new),
236 "c"((unsigned long)(new >> 32)),
237 "m"(*__xg(ptr)),
238 "0"(old)
239 : "memory");
240 return prev;
241}
242
206#ifndef CONFIG_X86_CMPXCHG 243#ifndef CONFIG_X86_CMPXCHG
207/* 244/*
208 * Building a kernel capable running on 80386. It may be necessary to 245 * Building a kernel capable running on 80386. It may be necessary to
@@ -228,7 +265,7 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
228 return old; 265 return old;
229} 266}
230 267
231#define cmpxchg(ptr,o,n) \ 268#define cmpxchg(ptr, o, n) \
232({ \ 269({ \
233 __typeof__(*(ptr)) __ret; \ 270 __typeof__(*(ptr)) __ret; \
234 if (likely(boot_cpu_data.x86 > 3)) \ 271 if (likely(boot_cpu_data.x86 > 3)) \
@@ -239,7 +276,7 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
239 (unsigned long)(n), sizeof(*(ptr))); \ 276 (unsigned long)(n), sizeof(*(ptr))); \
240 __ret; \ 277 __ret; \
241}) 278})
242#define cmpxchg_local(ptr,o,n) \ 279#define cmpxchg_local(ptr, o, n) \
243({ \ 280({ \
244 __typeof__(*(ptr)) __ret; \ 281 __typeof__(*(ptr)) __ret; \
245 if (likely(boot_cpu_data.x86 > 3)) \ 282 if (likely(boot_cpu_data.x86 > 3)) \
@@ -252,38 +289,37 @@ static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
252}) 289})
253#endif 290#endif
254 291
255static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old, 292#ifndef CONFIG_X86_CMPXCHG64
256 unsigned long long new) 293/*
257{ 294 * Building a kernel capable running on 80386 and 80486. It may be necessary
258 unsigned long long prev; 295 * to simulate the cmpxchg8b on the 80386 and 80486 CPU.
259 __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3" 296 */
260 : "=A"(prev)
261 : "b"((unsigned long)new),
262 "c"((unsigned long)(new >> 32)),
263 "m"(*__xg(ptr)),
264 "0"(old)
265 : "memory");
266 return prev;
267}
268 297
269static inline unsigned long long __cmpxchg64_local(volatile void *ptr, 298extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
270 unsigned long long old, unsigned long long new) 299
271{ 300#define cmpxchg64(ptr, o, n) \
272 unsigned long long prev; 301({ \
273 __asm__ __volatile__("cmpxchg8b %3" 302 __typeof__(*(ptr)) __ret; \
274 : "=A"(prev) 303 if (likely(boot_cpu_data.x86 > 4)) \
275 : "b"((unsigned long)new), 304 __ret = __cmpxchg64((ptr), (unsigned long long)(o), \
276 "c"((unsigned long)(new >> 32)), 305 (unsigned long long)(n)); \
277 "m"(*__xg(ptr)), 306 else \
278 "0"(old) 307 __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \
279 : "memory"); 308 (unsigned long long)(n)); \
280 return prev; 309 __ret; \
281} 310})
311#define cmpxchg64_local(ptr, o, n) \
312({ \
313 __typeof__(*(ptr)) __ret; \
314 if (likely(boot_cpu_data.x86 > 4)) \
315 __ret = __cmpxchg64_local((ptr), (unsigned long long)(o), \
316 (unsigned long long)(n)); \
317 else \
318 __ret = cmpxchg_486_u64((ptr), (unsigned long long)(o), \
319 (unsigned long long)(n)); \
320 __ret; \
321})
322
323#endif
282 324
283#define cmpxchg64(ptr,o,n)\
284 ((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
285 (unsigned long long)(n)))
286#define cmpxchg64_local(ptr,o,n)\
287 ((__typeof__(*(ptr)))__cmpxchg64_local((ptr),(unsigned long long)(o),\
288 (unsigned long long)(n)))
289#endif 325#endif