VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / include / asm-m68k / atomic.h
1 #ifndef __ARCH_M68K_ATOMIC__
2 #define __ARCH_M68K_ATOMIC__
3
4 #include <asm/system.h> /* local_irq_XXX() */
5
6 /*
7  * Atomic operations that C can't guarantee us.  Useful for
8  * resource counting etc..
9  */
10
11 /*
12  * We do not have SMP m68k systems, so we don't have to deal with that.
13  */
14
15 typedef struct { int counter; } atomic_t;
16 #define ATOMIC_INIT(i)  { (i) }
17
18 #define atomic_read(v)          ((v)->counter)
19 #define atomic_set(v, i)        (((v)->counter) = i)
20
21 static inline void atomic_add(int i, atomic_t *v)
22 {
23         __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
24 }
25
26 static inline void atomic_sub(int i, atomic_t *v)
27 {
28         __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
29 }
30
31 static inline void atomic_inc(atomic_t *v)
32 {
33         __asm__ __volatile__("addql #1,%0" : "+m" (*v));
34 }
35
36 static inline void atomic_dec(atomic_t *v)
37 {
38         __asm__ __volatile__("subql #1,%0" : "+m" (*v));
39 }
40
41 static inline int atomic_dec_and_test(atomic_t *v)
42 {
43         char c;
44         __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
45         return c != 0;
46 }
47
48 static inline int atomic_inc_and_test(atomic_t *v)
49 {
50         char c;
51         __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
52         return c != 0;
53 }
54
55 #ifdef CONFIG_RMW_INSNS
56 static inline int atomic_add_return(int i, atomic_t *v)
57 {
58         int t, tmp;
59
60         __asm__ __volatile__(
61                         "1:     movel %2,%1\n"
62                         "       addl %3,%1\n"
63                         "       casl %2,%1,%0\n"
64                         "       jne 1b"
65                         : "+m" (*v), "=&d" (t), "=&d" (tmp)
66                         : "g" (i), "2" (atomic_read(v)));
67         return t;
68 }
69
70 static inline int atomic_sub_return(int i, atomic_t *v)
71 {
72         int t, tmp;
73
74         __asm__ __volatile__(
75                         "1:     movel %2,%1\n"
76                         "       subl %3,%1\n"
77                         "       casl %2,%1,%0\n"
78                         "       jne 1b"
79                         : "+m" (*v), "=&d" (t), "=&d" (tmp)
80                         : "g" (i), "2" (atomic_read(v)));
81         return t;
82 }
83 #else /* !CONFIG_RMW_INSNS */
84 static inline int atomic_add_return(int i, atomic_t * v)
85 {
86         unsigned long flags;
87         int t;
88
89         local_irq_save(flags);
90         t = atomic_read(v);
91         t += i;
92         atomic_set(v, t);
93         local_irq_restore(flags);
94
95         return t;
96 }
97
98 static inline int atomic_sub_return(int i, atomic_t * v)
99 {
100         unsigned long flags;
101         int t;
102
103         local_irq_save(flags);
104         t = atomic_read(v);
105         t -= i;
106         atomic_set(v, t);
107         local_irq_restore(flags);
108
109         return t;
110 }
111 #endif /* !CONFIG_RMW_INSNS */
112
113 #define atomic_dec_return(v)    atomic_sub_return(1, (v))
114 #define atomic_inc_return(v)    atomic_add_return(1, (v))
115
116 static inline int atomic_sub_and_test(int i, atomic_t *v)
117 {
118         char c;
119         __asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i));
120         return c != 0;
121 }
122
123 static inline int atomic_add_negative(int i, atomic_t *v)
124 {
125         char c;
126         __asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i));
127         return c != 0;
128 }
129
130 static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
131 {
132         __asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
133 }
134
135 static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
136 {
137         __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
138 }
139
140 /* Atomic operations are already serializing */
141 #define smp_mb__before_atomic_dec()     barrier()
142 #define smp_mb__after_atomic_dec()      barrier()
143 #define smp_mb__before_atomic_inc()     barrier()
144 #define smp_mb__after_atomic_inc()      barrier()
145
146 #endif /* __ARCH_M68K_ATOMIC __ */