diff options
Diffstat (limited to 'arch/arm/include/asm/cmpxchg.h')
-rw-r--r-- | arch/arm/include/asm/cmpxchg.h | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h index 4f009c10540d..df2fbba7efc8 100644 --- a/arch/arm/include/asm/cmpxchg.h +++ b/arch/arm/include/asm/cmpxchg.h | |||
@@ -223,6 +223,42 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
223 | return ret; | 223 | return ret; |
224 | } | 224 | } |
225 | 225 | ||
226 | static inline unsigned long long __cmpxchg64(unsigned long long *ptr, | ||
227 | unsigned long long old, | ||
228 | unsigned long long new) | ||
229 | { | ||
230 | unsigned long long oldval; | ||
231 | unsigned long res; | ||
232 | |||
233 | __asm__ __volatile__( | ||
234 | "1: ldrexd %1, %H1, [%3]\n" | ||
235 | " teq %1, %4\n" | ||
236 | " teqeq %H1, %H4\n" | ||
237 | " bne 2f\n" | ||
238 | " strexd %0, %5, %H5, [%3]\n" | ||
239 | " teq %0, #0\n" | ||
240 | " bne 1b\n" | ||
241 | "2:" | ||
242 | : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr) | ||
243 | : "r" (ptr), "r" (old), "r" (new) | ||
244 | : "cc"); | ||
245 | |||
246 | return oldval; | ||
247 | } | ||
248 | |||
249 | static inline unsigned long long __cmpxchg64_mb(unsigned long long *ptr, | ||
250 | unsigned long long old, | ||
251 | unsigned long long new) | ||
252 | { | ||
253 | unsigned long long ret; | ||
254 | |||
255 | smp_mb(); | ||
256 | ret = __cmpxchg64(ptr, old, new); | ||
257 | smp_mb(); | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
226 | #define cmpxchg_local(ptr,o,n) \ | 262 | #define cmpxchg_local(ptr,o,n) \ |
227 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ | 263 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ |
228 | (unsigned long)(o), \ | 264 | (unsigned long)(o), \ |
@@ -230,18 +266,16 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
230 | sizeof(*(ptr)))) | 266 | sizeof(*(ptr)))) |
231 | 267 | ||
232 | #define cmpxchg64(ptr, o, n) \ | 268 | #define cmpxchg64(ptr, o, n) \ |
233 | ((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr), \ | 269 | ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr), \ |
234 | atomic64_t, \ | 270 | (unsigned long long)(o), \ |
235 | counter), \ | 271 | (unsigned long long)(n))) |
236 | (unsigned long long)(o), \ | 272 | |
237 | (unsigned long long)(n))) | 273 | #define cmpxchg64_relaxed(ptr, o, n) \ |
238 | 274 | ((__typeof__(*(ptr)))__cmpxchg64((ptr), \ | |
239 | #define cmpxchg64_local(ptr, o, n) \ | 275 | (unsigned long long)(o), \ |
240 | ((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr), \ | 276 | (unsigned long long)(n))) |
241 | local64_t, \ | 277 | |
242 | a), \ | 278 | #define cmpxchg64_local(ptr, o, n) cmpxchg64_relaxed((ptr), (o), (n)) |
243 | (unsigned long long)(o), \ | ||
244 | (unsigned long long)(n))) | ||
245 | 279 | ||
246 | #endif /* __LINUX_ARM_ARCH__ >= 6 */ | 280 | #endif /* __LINUX_ARM_ARCH__ >= 6 */ |
247 | 281 | ||