1
2
3
4
5
6
7
8
9
10
11#ifndef _ASM_ATOMIC_H
12#define _ASM_ATOMIC_H
13
14#include <asm/irqflags.h>
15#include <asm/cmpxchg.h>
16#include <asm/barrier.h>
17
18#ifndef CONFIG_SMP
19#include <asm-generic/atomic.h>
20#else
21
22
23
24
25
26
27#define ATOMIC_INIT(i) { (i) }
28
29#ifdef __KERNEL__
30
31
32
33
34
35
36
37#define atomic_read(v) (ACCESS_ONCE((v)->counter))
38
39
40
41
42
43
44
45
46#define atomic_set(v, i) (((v)->counter) = (i))
47
48#define ATOMIC_OP(op) \
49static inline void atomic_##op(int i, atomic_t *v) \
50{ \
51 int retval, status; \
52 \
53 asm volatile( \
54 "1: mov %4,(_AAR,%3) \n" \
55 " mov (_ADR,%3),%1 \n" \
56 " " #op " %5,%1 \n" \
57 " mov %1,(_ADR,%3) \n" \
58 " mov (_ADR,%3),%0 \n" \
59 " mov (_ASR,%3),%0 \n" \
60 " or %0,%0 \n" \
61 " bne 1b \n" \
62 : "=&r"(status), "=&r"(retval), "=m"(v->counter) \
63 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i) \
64 : "memory", "cc"); \
65}
66
67#define ATOMIC_OP_RETURN(op) \
68static inline int atomic_##op##_return(int i, atomic_t *v) \
69{ \
70 int retval, status; \
71 \
72 asm volatile( \
73 "1: mov %4,(_AAR,%3) \n" \
74 " mov (_ADR,%3),%1 \n" \
75 " " #op " %5,%1 \n" \
76 " mov %1,(_ADR,%3) \n" \
77 " mov (_ADR,%3),%0 \n" \
78 " mov (_ASR,%3),%0 \n" \
79 " or %0,%0 \n" \
80 " bne 1b \n" \
81 : "=&r"(status), "=&r"(retval), "=m"(v->counter) \
82 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(&v->counter), "r"(i) \
83 : "memory", "cc"); \
84 return retval; \
85}
86
87#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op)
88
89ATOMIC_OPS(add)
90ATOMIC_OPS(sub)
91
92#undef ATOMIC_OPS
93#undef ATOMIC_OP_RETURN
94#undef ATOMIC_OP
95
96static inline int atomic_add_negative(int i, atomic_t *v)
97{
98 return atomic_add_return(i, v) < 0;
99}
100
101static inline void atomic_inc(atomic_t *v)
102{
103 atomic_add_return(1, v);
104}
105
106static inline void atomic_dec(atomic_t *v)
107{
108 atomic_sub_return(1, v);
109}
110
111#define atomic_dec_return(v) atomic_sub_return(1, (v))
112#define atomic_inc_return(v) atomic_add_return(1, (v))
113
114#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
115#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
116#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
117
118#define __atomic_add_unless(v, a, u) \
119({ \
120 int c, old; \
121 c = atomic_read(v); \
122 while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
123 c = old; \
124 c; \
125})
126
127#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
128#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
129
130
131
132
133
134
135
136
137static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
138{
139#ifdef CONFIG_SMP
140 int status;
141
142 asm volatile(
143 "1: mov %3,(_AAR,%2) \n"
144 " mov (_ADR,%2),%0 \n"
145 " and %4,%0 \n"
146 " mov %0,(_ADR,%2) \n"
147 " mov (_ADR,%2),%0 \n"
148 " mov (_ASR,%2),%0 \n"
149 " or %0,%0 \n"
150 " bne 1b \n"
151 : "=&r"(status), "=m"(*addr)
152 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(~mask)
153 : "memory", "cc");
154#else
155 unsigned long flags;
156
157 mask = ~mask;
158 flags = arch_local_cli_save();
159 *addr &= mask;
160 arch_local_irq_restore(flags);
161#endif
162}
163
164
165
166
167
168
169
170
171static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
172{
173#ifdef CONFIG_SMP
174 int status;
175
176 asm volatile(
177 "1: mov %3,(_AAR,%2) \n"
178 " mov (_ADR,%2),%0 \n"
179 " or %4,%0 \n"
180 " mov %0,(_ADR,%2) \n"
181 " mov (_ADR,%2),%0 \n"
182 " mov (_ASR,%2),%0 \n"
183 " or %0,%0 \n"
184 " bne 1b \n"
185 : "=&r"(status), "=m"(*addr)
186 : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(mask)
187 : "memory", "cc");
188#else
189 unsigned long flags;
190
191 flags = arch_local_cli_save();
192 *addr |= mask;
193 arch_local_irq_restore(flags);
194#endif
195}
196
197#endif
198#endif
199#endif
200