diff options
author | Gunnar Larisch <gl@denx.de> | 2008-02-07 03:16:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 11:42:32 -0500 |
commit | 85fdbe1b4b33b797321bfadf706b355e7cca6165 (patch) | |
tree | bb24d49bb9cc2167742af843718587b408ad71e2 /include | |
parent | df80c8c5679c4e6c72e694525d76a9f26d5f33dc (diff) |
Add cmpxchg_local to ppc
Add a local processor version of cmpxchg for ppc.
Implements __cmpxchg_u32_local and uses it for 32 bits cmpxchg_local.
It uses the non NMI safe cmpxchg_local_generic for 1, 2 and 8 bytes
cmpxchg_local.
Signed-off-by: Gunnar Larisch <gl@denx.de>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Kumar Gala <galak@gate.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-ppc/system.h | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h index 51df94c73846..0593cb889d45 100644 --- a/include/asm-ppc/system.h +++ b/include/asm-ppc/system.h | |||
@@ -209,12 +209,34 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new) | |||
209 | return prev; | 209 | return prev; |
210 | } | 210 | } |
211 | 211 | ||
212 | static inline unsigned long | ||
213 | __cmpxchg_u32_local(volatile unsigned int *p, unsigned int old, | ||
214 | unsigned int new) | ||
215 | { | ||
216 | unsigned int prev; | ||
217 | |||
218 | __asm__ __volatile__ ("\n\ | ||
219 | 1: lwarx %0,0,%2 \n\ | ||
220 | cmpw 0,%0,%3 \n\ | ||
221 | bne 2f \n" | ||
222 | PPC405_ERR77(0,%2) | ||
223 | " stwcx. %4,0,%2 \n\ | ||
224 | bne- 1b\n" | ||
225 | "2:" | ||
226 | : "=&r" (prev), "=m" (*p) | ||
227 | : "r" (p), "r" (old), "r" (new), "m" (*p) | ||
228 | : "cc", "memory"); | ||
229 | |||
230 | return prev; | ||
231 | } | ||
232 | |||
212 | /* This function doesn't exist, so you'll get a linker error | 233 | /* This function doesn't exist, so you'll get a linker error |
213 | if something tries to do an invalid cmpxchg(). */ | 234 | if something tries to do an invalid cmpxchg(). */ |
214 | extern void __cmpxchg_called_with_bad_pointer(void); | 235 | extern void __cmpxchg_called_with_bad_pointer(void); |
215 | 236 | ||
216 | static __inline__ unsigned long | 237 | static __inline__ unsigned long |
217 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | 238 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, |
239 | unsigned int size) | ||
218 | { | 240 | { |
219 | switch (size) { | 241 | switch (size) { |
220 | case 4: | 242 | case 4: |
@@ -228,7 +250,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
228 | return old; | 250 | return old; |
229 | } | 251 | } |
230 | 252 | ||
231 | #define cmpxchg(ptr,o,n) \ | 253 | #define cmpxchg(ptr, o, n) \ |
232 | ({ \ | 254 | ({ \ |
233 | __typeof__(*(ptr)) _o_ = (o); \ | 255 | __typeof__(*(ptr)) _o_ = (o); \ |
234 | __typeof__(*(ptr)) _n_ = (n); \ | 256 | __typeof__(*(ptr)) _n_ = (n); \ |
@@ -236,6 +258,31 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
236 | (unsigned long)_n_, sizeof(*(ptr))); \ | 258 | (unsigned long)_n_, sizeof(*(ptr))); \ |
237 | }) | 259 | }) |
238 | 260 | ||
261 | #include <asm-generic/cmpxchg-local.h> | ||
262 | |||
263 | static inline unsigned long __cmpxchg_local(volatile void *ptr, | ||
264 | unsigned long old, | ||
265 | unsigned long new, int size) | ||
266 | { | ||
267 | switch (size) { | ||
268 | case 4: | ||
269 | return __cmpxchg_u32_local(ptr, old, new); | ||
270 | default: | ||
271 | return __cmpxchg_local_generic(ptr, old, new, size); | ||
272 | } | ||
273 | |||
274 | return old; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make | ||
279 | * them available. | ||
280 | */ | ||
281 | #define cmpxchg_local(ptr, o, n) \ | ||
282 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ | ||
283 | (unsigned long)(n), sizeof(*(ptr)))) | ||
284 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | ||
285 | |||
239 | #define arch_align_stack(x) (x) | 286 | #define arch_align_stack(x) (x) |
240 | 287 | ||
241 | #endif /* __KERNEL__ */ | 288 | #endif /* __KERNEL__ */ |