diff options
Diffstat (limited to 'arch/avr32/include/asm/cmpxchg.h')
-rw-r--r-- | arch/avr32/include/asm/cmpxchg.h | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/arch/avr32/include/asm/cmpxchg.h b/arch/avr32/include/asm/cmpxchg.h new file mode 100644 index 000000000000..962a6aeab787 --- /dev/null +++ b/arch/avr32/include/asm/cmpxchg.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Atomic operations that C can't guarantee us. Useful for | ||
3 | * resource counting etc. | ||
4 | * | ||
5 | * But use these as seldom as possible since they are slower than | ||
6 | * regular operations. | ||
7 | * | ||
8 | * Copyright (C) 2004-2006 Atmel Corporation | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | #ifndef __ASM_AVR32_CMPXCHG_H | ||
15 | #define __ASM_AVR32_CMPXCHG_H | ||
16 | |||
17 | #define xchg(ptr,x) \ | ||
18 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
19 | |||
20 | extern void __xchg_called_with_bad_pointer(void); | ||
21 | |||
22 | static inline unsigned long xchg_u32(u32 val, volatile u32 *m) | ||
23 | { | ||
24 | u32 ret; | ||
25 | |||
26 | asm volatile("xchg %[ret], %[m], %[val]" | ||
27 | : [ret] "=&r"(ret), "=m"(*m) | ||
28 | : "m"(*m), [m] "r"(m), [val] "r"(val) | ||
29 | : "memory"); | ||
30 | return ret; | ||
31 | } | ||
32 | |||
33 | static inline unsigned long __xchg(unsigned long x, | ||
34 | volatile void *ptr, | ||
35 | int size) | ||
36 | { | ||
37 | switch(size) { | ||
38 | case 4: | ||
39 | return xchg_u32(x, ptr); | ||
40 | default: | ||
41 | __xchg_called_with_bad_pointer(); | ||
42 | return x; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, | ||
47 | unsigned long new) | ||
48 | { | ||
49 | __u32 ret; | ||
50 | |||
51 | asm volatile( | ||
52 | "1: ssrf 5\n" | ||
53 | " ld.w %[ret], %[m]\n" | ||
54 | " cp.w %[ret], %[old]\n" | ||
55 | " brne 2f\n" | ||
56 | " stcond %[m], %[new]\n" | ||
57 | " brne 1b\n" | ||
58 | "2:\n" | ||
59 | : [ret] "=&r"(ret), [m] "=m"(*m) | ||
60 | : "m"(m), [old] "ir"(old), [new] "r"(new) | ||
61 | : "memory", "cc"); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels( | ||
66 | volatile int * m, unsigned long old, unsigned long new); | ||
67 | #define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels | ||
68 | |||
69 | /* This function doesn't exist, so you'll get a linker error | ||
70 | if something tries to do an invalid cmpxchg(). */ | ||
71 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
72 | |||
73 | #define __HAVE_ARCH_CMPXCHG 1 | ||
74 | |||
75 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | ||
76 | unsigned long new, int size) | ||
77 | { | ||
78 | switch (size) { | ||
79 | case 4: | ||
80 | return __cmpxchg_u32(ptr, old, new); | ||
81 | case 8: | ||
82 | return __cmpxchg_u64(ptr, old, new); | ||
83 | } | ||
84 | |||
85 | __cmpxchg_called_with_bad_pointer(); | ||
86 | return old; | ||
87 | } | ||
88 | |||
89 | #define cmpxchg(ptr, old, new) \ | ||
90 | ((typeof(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), \ | ||
91 | (unsigned long)(new), \ | ||
92 | sizeof(*(ptr)))) | ||
93 | |||
94 | #include <asm-generic/cmpxchg-local.h> | ||
95 | |||
96 | static inline unsigned long __cmpxchg_local(volatile void *ptr, | ||
97 | unsigned long old, | ||
98 | unsigned long new, int size) | ||
99 | { | ||
100 | switch (size) { | ||
101 | case 4: | ||
102 | return __cmpxchg_u32(ptr, old, new); | ||
103 | default: | ||
104 | return __cmpxchg_local_generic(ptr, old, new, size); | ||
105 | } | ||
106 | |||
107 | return old; | ||
108 | } | ||
109 | |||
110 | #define cmpxchg_local(ptr, old, new) \ | ||
111 | ((typeof(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(old), \ | ||
112 | (unsigned long)(new), \ | ||
113 | sizeof(*(ptr)))) | ||
114 | |||
115 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | ||
116 | |||
117 | #endif /* __ASM_AVR32_CMPXCHG_H */ | ||