Merge remote branch 'repo/master' into stats
[openvswitch] / datapath / linux-2.4 / compat-2.4 / include-arm / asm / atomic.h
1 #ifndef __ASM_ARM_ATOMIC_H_WRAPPER
2 #define __ASM_ARM_ATOMIC_H_WRAPPER 1
3
4 #include_next <asm/atomic.h>
5
6 #ifdef __KERNEL__
7
8 #if __LINUX_ARM_ARCH__ >= 6
9
10 static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
11 {
12         unsigned long oldval, res;
13
14         do {
15                 __asm__ __volatile__("@ atomic_cmpxchg\n"
16                 "ldrex  %1, [%2]\n"
17                 "mov    %0, #0\n"
18                 "teq    %1, %3\n"
19                 "strexeq %0, %4, [%2]\n"
20                     : "=&r" (res), "=&r" (oldval)
21                     : "r" (&ptr->counter), "Ir" (old), "r" (new)
22                     : "cc");
23         } while (res);
24
25         return oldval;
26 }
27
28 #else /* ARM_ARCH_6 */
29
30 #include <asm/system.h>
31
32 #ifdef CONFIG_SMP
33 #error SMP not supported on pre-ARMv6 CPUs
34 #endif
35
36 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
37 {
38         int ret;
39         unsigned long flags;
40
41         local_irq_save(flags);
42         ret = v->counter;
43         if (likely(ret == old))
44                 v->counter = new;
45         local_irq_restore(flags);
46
47         return ret;
48 }
49
50 #endif /* __LINUX_ARM_ARCH__ */
51
52 #endif /* __KERNEL__ */
53
54 #endif /* asm/atomic.h */