1 #ifndef _ASM_POWERPC_CMPXCHG_H_
2 #define _ASM_POWERPC_CMPXCHG_H_
5 #include <linux/compiler.h>
7 #include <asm/asm-compat.h>
12 * Changes the memory location '*ptr' to be val and returns
13 * the previous value stored there.
15 static __always_inline unsigned long
16 __xchg_u32(volatile void *p, unsigned long val)
21 PPC_ATOMIC_ENTRY_BARRIER
26 PPC_ATOMIC_EXIT_BARRIER
27 : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
37 * Changes the memory location '*ptr' to be val and returns
38 * the previous value stored there.
40 static __always_inline unsigned long
41 __xchg_u32_local(volatile void *p, unsigned long val)
50 : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
58 static __always_inline unsigned long
59 __xchg_u64(volatile void *p, unsigned long val)
64 PPC_ATOMIC_ENTRY_BARRIER
69 PPC_ATOMIC_EXIT_BARRIER
70 : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
77 static __always_inline unsigned long
78 __xchg_u64_local(volatile void *p, unsigned long val)
87 : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
96 * This function doesn't exist, so you'll get a linker error
97 * if something tries to do an invalid xchg().
99 extern void __xchg_called_with_bad_pointer(void);
101 static __always_inline unsigned long
102 __xchg(volatile void *ptr, unsigned long x, unsigned int size)
106 return __xchg_u32(ptr, x);
109 return __xchg_u64(ptr, x);
112 __xchg_called_with_bad_pointer();
116 static __always_inline unsigned long
117 __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
121 return __xchg_u32_local(ptr, x);
124 return __xchg_u64_local(ptr, x);
127 __xchg_called_with_bad_pointer();
130 #define xchg(ptr,x) \
132 __typeof__(*(ptr)) _x_ = (x); \
133 (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
136 #define xchg_local(ptr,x) \
138 __typeof__(*(ptr)) _x_ = (x); \
139 (__typeof__(*(ptr))) __xchg_local((ptr), \
140 (unsigned long)_x_, sizeof(*(ptr))); \
144 * Compare and exchange - if *p == old, set it to new,
145 * and return the old value of *p.
148 static __always_inline unsigned long
149 __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
153 __asm__ __volatile__ (
154 PPC_ATOMIC_ENTRY_BARRIER
155 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\
161 PPC_ATOMIC_EXIT_BARRIER
164 : "=&r" (prev), "+m" (*p)
165 : "r" (p), "r" (old), "r" (new)
171 static __always_inline unsigned long
172 __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
177 __asm__ __volatile__ (
178 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\
186 : "=&r" (prev), "+m" (*p)
187 : "r" (p), "r" (old), "r" (new)
194 static __always_inline unsigned long
195 __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
199 __asm__ __volatile__ (
200 PPC_ATOMIC_ENTRY_BARRIER
201 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\
206 PPC_ATOMIC_EXIT_BARRIER
209 : "=&r" (prev), "+m" (*p)
210 : "r" (p), "r" (old), "r" (new)
216 static __always_inline unsigned long
217 __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
222 __asm__ __volatile__ (
223 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\
230 : "=&r" (prev), "+m" (*p)
231 : "r" (p), "r" (old), "r" (new)
238 /* This function doesn't exist, so you'll get a linker error
239 if something tries to do an invalid cmpxchg(). */
240 extern void __cmpxchg_called_with_bad_pointer(void);
242 static __always_inline unsigned long
243 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
248 return __cmpxchg_u32(ptr, old, new);
251 return __cmpxchg_u64(ptr, old, new);
254 __cmpxchg_called_with_bad_pointer();
258 static __always_inline unsigned long
259 __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
264 return __cmpxchg_u32_local(ptr, old, new);
267 return __cmpxchg_u64_local(ptr, old, new);
270 __cmpxchg_called_with_bad_pointer();
274 #define cmpxchg(ptr, o, n) \
276 __typeof__(*(ptr)) _o_ = (o); \
277 __typeof__(*(ptr)) _n_ = (n); \
278 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
279 (unsigned long)_n_, sizeof(*(ptr))); \
283 #define cmpxchg_local(ptr, o, n) \
285 __typeof__(*(ptr)) _o_ = (o); \
286 __typeof__(*(ptr)) _n_ = (n); \
287 (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
288 (unsigned long)_n_, sizeof(*(ptr))); \
292 #define cmpxchg64(ptr, o, n) \
294 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
295 cmpxchg((ptr), (o), (n)); \
297 #define cmpxchg64_local(ptr, o, n) \
299 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
300 cmpxchg_local((ptr), (o), (n)); \
302 #define cmpxchg64_relaxed cmpxchg64_local
304 #include <asm-generic/cmpxchg-local.h>
305 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
308 #endif /* __KERNEL__ */
309 #endif /* _ASM_POWERPC_CMPXCHG_H_ */