diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-03-26 13:31:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-08-14 06:48:14 -0400 |
commit | d4608dd5b4ec13855680b89f719d8d4b2da92411 (patch) | |
tree | 7660d636c571ad0993f890085a88e829d7e0b9a0 /arch/xtensa | |
parent | 4f3316c2b5fe2062c26c9b66915b5a5c80c60a5c (diff) |
locking,arch,xtensa: Fold atomic_ops
Many of the atomic op implementations are the same except for one
instruction; fold the lot into a few CPP macros and reduce LoC.
This also prepares for easy addition of new ops.
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Cc: Chris Zankel <chris@zankel.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: linux-xtensa@linux-xtensa.org
Link: http://lkml.kernel.org/r/20140508135852.879575796@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/include/asm/atomic.h | 233 |
1 files changed, 82 insertions, 151 deletions
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index e5103b47a8ce..626676660b80 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h | |||
@@ -58,165 +58,96 @@ | |||
58 | */ | 58 | */ |
59 | #define atomic_set(v,i) ((v)->counter = (i)) | 59 | #define atomic_set(v,i) ((v)->counter = (i)) |
60 | 60 | ||
61 | /** | ||
62 | * atomic_add - add integer to atomic variable | ||
63 | * @i: integer value to add | ||
64 | * @v: pointer of type atomic_t | ||
65 | * | ||
66 | * Atomically adds @i to @v. | ||
67 | */ | ||
68 | static inline void atomic_add(int i, atomic_t * v) | ||
69 | { | ||
70 | #if XCHAL_HAVE_S32C1I | 61 | #if XCHAL_HAVE_S32C1I |
71 | unsigned long tmp; | 62 | #define ATOMIC_OP(op) \ |
72 | int result; | 63 | static inline void atomic_##op(int i, atomic_t * v) \ |
73 | 64 | { \ | |
74 | __asm__ __volatile__( | 65 | unsigned long tmp; \ |
75 | "1: l32i %1, %3, 0\n" | 66 | int result; \ |
76 | " wsr %1, scompare1\n" | 67 | \ |
77 | " add %0, %1, %2\n" | 68 | __asm__ __volatile__( \ |
78 | " s32c1i %0, %3, 0\n" | 69 | "1: l32i %1, %3, 0\n" \ |
79 | " bne %0, %1, 1b\n" | 70 | " wsr %1, scompare1\n" \ |
80 | : "=&a" (result), "=&a" (tmp) | 71 | " " #op " %0, %1, %2\n" \ |
81 | : "a" (i), "a" (v) | 72 | " s32c1i %0, %3, 0\n" \ |
82 | : "memory" | 73 | " bne %0, %1, 1b\n" \ |
83 | ); | 74 | : "=&a" (result), "=&a" (tmp) \ |
84 | #else | 75 | : "a" (i), "a" (v) \ |
85 | unsigned int vval; | 76 | : "memory" \ |
86 | 77 | ); \ | |
87 | __asm__ __volatile__( | 78 | } \ |
88 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | 79 | |
89 | " l32i %0, %2, 0\n" | 80 | #define ATOMIC_OP_RETURN(op) \ |
90 | " add %0, %0, %1\n" | 81 | static inline int atomic_##op##_return(int i, atomic_t * v) \ |
91 | " s32i %0, %2, 0\n" | 82 | { \ |
92 | " wsr a15, ps\n" | 83 | unsigned long tmp; \ |
93 | " rsync\n" | 84 | int result; \ |
94 | : "=&a" (vval) | 85 | \ |
95 | : "a" (i), "a" (v) | 86 | __asm__ __volatile__( \ |
96 | : "a15", "memory" | 87 | "1: l32i %1, %3, 0\n" \ |
97 | ); | 88 | " wsr %1, scompare1\n" \ |
98 | #endif | 89 | " " #op " %0, %1, %2\n" \ |
99 | } | 90 | " s32c1i %0, %3, 0\n" \ |
100 | 91 | " bne %0, %1, 1b\n" \ | |
101 | /** | 92 | " " #op " %0, %0, %2\n" \ |
102 | * atomic_sub - subtract the atomic variable | 93 | : "=&a" (result), "=&a" (tmp) \ |
103 | * @i: integer value to subtract | 94 | : "a" (i), "a" (v) \ |
104 | * @v: pointer of type atomic_t | 95 | : "memory" \ |
105 | * | 96 | ); \ |
106 | * Atomically subtracts @i from @v. | 97 | \ |
107 | */ | 98 | return result; \ |
108 | static inline void atomic_sub(int i, atomic_t *v) | ||
109 | { | ||
110 | #if XCHAL_HAVE_S32C1I | ||
111 | unsigned long tmp; | ||
112 | int result; | ||
113 | |||
114 | __asm__ __volatile__( | ||
115 | "1: l32i %1, %3, 0\n" | ||
116 | " wsr %1, scompare1\n" | ||
117 | " sub %0, %1, %2\n" | ||
118 | " s32c1i %0, %3, 0\n" | ||
119 | " bne %0, %1, 1b\n" | ||
120 | : "=&a" (result), "=&a" (tmp) | ||
121 | : "a" (i), "a" (v) | ||
122 | : "memory" | ||
123 | ); | ||
124 | #else | ||
125 | unsigned int vval; | ||
126 | |||
127 | __asm__ __volatile__( | ||
128 | " rsil a15, "__stringify(LOCKLEVEL)"\n" | ||
129 | " l32i %0, %2, 0\n" | ||
130 | " sub %0, %0, %1\n" | ||
131 | " s32i %0, %2, 0\n" | ||
132 | " wsr a15, ps\n" | ||
133 | " rsync\n" | ||
134 | : "=&a" (vval) | ||
135 | : "a" (i), "a" (v) | ||
136 | : "a15", "memory" | ||
137 | ); | ||
138 | #endif | ||
139 | } | 99 | } |
140 | 100 | ||
141 | /* | 101 | #else /* XCHAL_HAVE_S32C1I */ |
142 | * We use atomic_{add|sub}_return to define other functions. | 102 | |
143 | */ | 103 | #define ATOMIC_OP(op) \ |
144 | 104 | static inline void atomic_##op(int i, atomic_t * v) \ | |
145 | static inline int atomic_add_return(int i, atomic_t * v) | 105 | { \ |
146 | { | 106 | unsigned int vval; \ |
147 | #if XCHAL_HAVE_S32C1I | 107 | \ |
148 | unsigned long tmp; | 108 | __asm__ __volatile__( \ |
149 | int result; | 109 | " rsil a15, "__stringify(LOCKLEVEL)"\n"\ |
150 | 110 | " l32i %0, %2, 0\n" \ | |
151 | __asm__ __volatile__( | 111 | " " #op " %0, %0, %1\n" \ |
152 | "1: l32i %1, %3, 0\n" | 112 | " s32i %0, %2, 0\n" \ |
153 | " wsr %1, scompare1\n" | 113 | " wsr a15, ps\n" \ |
154 | " add %0, %1, %2\n" | 114 | " rsync\n" \ |
155 | " s32c1i %0, %3, 0\n" | 115 | : "=&a" (vval) \ |
156 | " bne %0, %1, 1b\n" | 116 | : "a" (i), "a" (v) \ |
157 | " add %0, %0, %2\n" | 117 | : "a15", "memory" \ |
158 | : "=&a" (result), "=&a" (tmp) | 118 | ); \ |
159 | : "a" (i), "a" (v) | 119 | } \ |
160 | : "memory" | 120 | |
161 | ); | 121 | #define ATOMIC_OP_RETURN(op) \ |
162 | 122 | static inline int atomic_##op##_return(int i, atomic_t * v) \ | |
163 | return result; | 123 | { \ |
164 | #else | 124 | unsigned int vval; \ |
165 | unsigned int vval; | 125 | \ |
166 | 126 | __asm__ __volatile__( \ | |
167 | __asm__ __volatile__( | 127 | " rsil a15,"__stringify(LOCKLEVEL)"\n" \ |
168 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | 128 | " l32i %0, %2, 0\n" \ |
169 | " l32i %0, %2, 0\n" | 129 | " " #op " %0, %0, %1\n" \ |
170 | " add %0, %0, %1\n" | 130 | " s32i %0, %2, 0\n" \ |
171 | " s32i %0, %2, 0\n" | 131 | " wsr a15, ps\n" \ |
172 | " wsr a15, ps\n" | 132 | " rsync\n" \ |
173 | " rsync\n" | 133 | : "=&a" (vval) \ |
174 | : "=&a" (vval) | 134 | : "a" (i), "a" (v) \ |
175 | : "a" (i), "a" (v) | 135 | : "a15", "memory" \ |
176 | : "a15", "memory" | 136 | ); \ |
177 | ); | 137 | \ |
178 | 138 | return vval; \ | |
179 | return vval; | ||
180 | #endif | ||
181 | } | 139 | } |
182 | 140 | ||
183 | static inline int atomic_sub_return(int i, atomic_t * v) | 141 | #endif /* XCHAL_HAVE_S32C1I */ |
184 | { | ||
185 | #if XCHAL_HAVE_S32C1I | ||
186 | unsigned long tmp; | ||
187 | int result; | ||
188 | 142 | ||
189 | __asm__ __volatile__( | 143 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) |
190 | "1: l32i %1, %3, 0\n" | ||
191 | " wsr %1, scompare1\n" | ||
192 | " sub %0, %1, %2\n" | ||
193 | " s32c1i %0, %3, 0\n" | ||
194 | " bne %0, %1, 1b\n" | ||
195 | " sub %0, %0, %2\n" | ||
196 | : "=&a" (result), "=&a" (tmp) | ||
197 | : "a" (i), "a" (v) | ||
198 | : "memory" | ||
199 | ); | ||
200 | 144 | ||
201 | return result; | 145 | ATOMIC_OPS(add) |
202 | #else | 146 | ATOMIC_OPS(sub) |
203 | unsigned int vval; | ||
204 | |||
205 | __asm__ __volatile__( | ||
206 | " rsil a15,"__stringify(LOCKLEVEL)"\n" | ||
207 | " l32i %0, %2, 0\n" | ||
208 | " sub %0, %0, %1\n" | ||
209 | " s32i %0, %2, 0\n" | ||
210 | " wsr a15, ps\n" | ||
211 | " rsync\n" | ||
212 | : "=&a" (vval) | ||
213 | : "a" (i), "a" (v) | ||
214 | : "a15", "memory" | ||
215 | ); | ||
216 | 147 | ||
217 | return vval; | 148 | #undef ATOMIC_OPS |
218 | #endif | 149 | #undef ATOMIC_OP_RETURN |
219 | } | 150 | #undef ATOMIC_OP |
220 | 151 | ||
221 | /** | 152 | /** |
222 | * atomic_sub_and_test - subtract value from variable and test result | 153 | * atomic_sub_and_test - subtract value from variable and test result |