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
)
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
)
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.
147 #define __HAVE_ARCH_CMPXCHG 1
149 static __always_inline
unsigned long
150 __cmpxchg_u32(volatile unsigned int *p
, unsigned long old
, unsigned long new)
154 __asm__
__volatile__ (
156 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\
165 : "=&r" (prev
), "+m" (*p
)
166 : "r" (p
), "r" (old
), "r" (new)
172 static __always_inline
unsigned long
173 __cmpxchg_u32_local(volatile unsigned int *p
, unsigned long old
,
178 __asm__
__volatile__ (
179 "1: lwarx %0,0,%2 # __cmpxchg_u32\n\
187 : "=&r" (prev
), "+m" (*p
)
188 : "r" (p
), "r" (old
), "r" (new)
195 static __always_inline
unsigned long
196 __cmpxchg_u64(volatile unsigned long *p
, unsigned long old
, unsigned long new)
200 __asm__
__volatile__ (
202 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\
210 : "=&r" (prev
), "+m" (*p
)
211 : "r" (p
), "r" (old
), "r" (new)
217 static __always_inline
unsigned long
218 __cmpxchg_u64_local(volatile unsigned long *p
, unsigned long old
,
223 __asm__
__volatile__ (
224 "1: ldarx %0,0,%2 # __cmpxchg_u64\n\
231 : "=&r" (prev
), "+m" (*p
)
232 : "r" (p
), "r" (old
), "r" (new)
239 /* This function doesn't exist, so you'll get a linker error
240 if something tries to do an invalid cmpxchg(). */
241 extern void __cmpxchg_called_with_bad_pointer(void);
243 static __always_inline
unsigned long
244 __cmpxchg(volatile void *ptr
, unsigned long old
, unsigned long new,
249 return __cmpxchg_u32(ptr
, old
, new);
252 return __cmpxchg_u64(ptr
, old
, new);
255 __cmpxchg_called_with_bad_pointer();
259 static __always_inline
unsigned long
260 __cmpxchg_local(volatile void *ptr
, unsigned long old
, unsigned long new,
265 return __cmpxchg_u32_local(ptr
, old
, new);
268 return __cmpxchg_u64_local(ptr
, old
, new);
271 __cmpxchg_called_with_bad_pointer();
275 #define cmpxchg(ptr, o, n) \
277 __typeof__(*(ptr)) _o_ = (o); \
278 __typeof__(*(ptr)) _n_ = (n); \
279 (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
280 (unsigned long)_n_, sizeof(*(ptr))); \
284 #define cmpxchg_local(ptr, o, n) \
286 __typeof__(*(ptr)) _o_ = (o); \
287 __typeof__(*(ptr)) _n_ = (n); \
288 (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
289 (unsigned long)_n_, sizeof(*(ptr))); \
293 #define cmpxchg64(ptr, o, n) \
295 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
296 cmpxchg((ptr), (o), (n)); \
298 #define cmpxchg64_local(ptr, o, n) \
300 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
301 cmpxchg_local((ptr), (o), (n)); \
303 #define cmpxchg64_relaxed cmpxchg64_local
305 #include <asm-generic/cmpxchg-local.h>
306 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
309 #endif /* __KERNEL__ */
310 #endif /* _ASM_POWERPC_CMPXCHG_H_ */