]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* $Id: atomic.h,v 1.3 2001/07/25 16:15:19 bjornw Exp $ */ |
2 | ||
3 | #ifndef __ASM_CRIS_ATOMIC__ | |
4 | #define __ASM_CRIS_ATOMIC__ | |
5 | ||
9587997a | 6 | #include <linux/compiler.h> |
ea435467 | 7 | #include <linux/types.h> |
b1a154db | 8 | #include <asm/cmpxchg.h> |
556dcee7 | 9 | #include <arch/atomic.h> |
17b40213 PZ |
10 | #include <arch/system.h> |
11 | #include <asm/barrier.h> | |
1da177e4 LT |
12 | |
13 | /* | |
14 | * Atomic operations that C can't guarantee us. Useful for | |
15 | * resource counting etc.. | |
16 | */ | |
17 | ||
1da177e4 LT |
18 | #define ATOMIC_INIT(i) { (i) } |
19 | ||
2291059c | 20 | #define atomic_read(v) ACCESS_ONCE((v)->counter) |
1da177e4 LT |
21 | #define atomic_set(v,i) (((v)->counter) = (i)) |
22 | ||
23 | /* These should be written in asm but we do it in C for now. */ | |
24 | ||
7179e30e PZ |
25 | #define ATOMIC_OP(op, c_op) \ |
26 | static inline void atomic_##op(int i, volatile atomic_t *v) \ | |
27 | { \ | |
28 | unsigned long flags; \ | |
29 | cris_atomic_save(v, flags); \ | |
30 | v->counter c_op i; \ | |
31 | cris_atomic_restore(v, flags); \ | |
32 | } \ | |
33 | ||
34 | #define ATOMIC_OP_RETURN(op, c_op) \ | |
35 | static inline int atomic_##op##_return(int i, volatile atomic_t *v) \ | |
36 | { \ | |
37 | unsigned long flags; \ | |
38 | int retval; \ | |
39 | cris_atomic_save(v, flags); \ | |
40 | retval = (v->counter c_op i); \ | |
41 | cris_atomic_restore(v, flags); \ | |
42 | return retval; \ | |
1da177e4 LT |
43 | } |
44 | ||
7179e30e | 45 | #define ATOMIC_OPS(op, c_op) ATOMIC_OP(op, c_op) ATOMIC_OP_RETURN(op, c_op) |
1da177e4 | 46 | |
7179e30e PZ |
47 | ATOMIC_OPS(add, +=) |
48 | ATOMIC_OPS(sub, -=) | |
1da177e4 | 49 | |
7179e30e PZ |
50 | #undef ATOMIC_OPS |
51 | #undef ATOMIC_OP_RETURN | |
52 | #undef ATOMIC_OP | |
1da177e4 | 53 | |
7179e30e | 54 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) |
1da177e4 | 55 | |
d9b5444e | 56 | static inline int atomic_sub_and_test(int i, volatile atomic_t *v) |
1da177e4 LT |
57 | { |
58 | int retval; | |
59 | unsigned long flags; | |
8d20a541 | 60 | cris_atomic_save(v, flags); |
1da177e4 | 61 | retval = (v->counter -= i) == 0; |
8d20a541 | 62 | cris_atomic_restore(v, flags); |
1da177e4 LT |
63 | return retval; |
64 | } | |
65 | ||
d9b5444e | 66 | static inline void atomic_inc(volatile atomic_t *v) |
1da177e4 LT |
67 | { |
68 | unsigned long flags; | |
8d20a541 | 69 | cris_atomic_save(v, flags); |
1da177e4 | 70 | (v->counter)++; |
8d20a541 | 71 | cris_atomic_restore(v, flags); |
1da177e4 LT |
72 | } |
73 | ||
d9b5444e | 74 | static inline void atomic_dec(volatile atomic_t *v) |
1da177e4 LT |
75 | { |
76 | unsigned long flags; | |
8d20a541 | 77 | cris_atomic_save(v, flags); |
1da177e4 | 78 | (v->counter)--; |
8d20a541 | 79 | cris_atomic_restore(v, flags); |
1da177e4 LT |
80 | } |
81 | ||
d9b5444e | 82 | static inline int atomic_inc_return(volatile atomic_t *v) |
1da177e4 LT |
83 | { |
84 | unsigned long flags; | |
85 | int retval; | |
8d20a541 | 86 | cris_atomic_save(v, flags); |
3c1d9303 | 87 | retval = ++(v->counter); |
8d20a541 | 88 | cris_atomic_restore(v, flags); |
1da177e4 LT |
89 | return retval; |
90 | } | |
91 | ||
d9b5444e | 92 | static inline int atomic_dec_return(volatile atomic_t *v) |
1da177e4 LT |
93 | { |
94 | unsigned long flags; | |
95 | int retval; | |
8d20a541 | 96 | cris_atomic_save(v, flags); |
3c1d9303 | 97 | retval = --(v->counter); |
8d20a541 | 98 | cris_atomic_restore(v, flags); |
1da177e4 LT |
99 | return retval; |
100 | } | |
d9b5444e | 101 | static inline int atomic_dec_and_test(volatile atomic_t *v) |
1da177e4 LT |
102 | { |
103 | int retval; | |
104 | unsigned long flags; | |
8d20a541 | 105 | cris_atomic_save(v, flags); |
1da177e4 | 106 | retval = --(v->counter) == 0; |
8d20a541 | 107 | cris_atomic_restore(v, flags); |
1da177e4 LT |
108 | return retval; |
109 | } | |
110 | ||
d9b5444e | 111 | static inline int atomic_inc_and_test(volatile atomic_t *v) |
1da177e4 LT |
112 | { |
113 | int retval; | |
114 | unsigned long flags; | |
8d20a541 | 115 | cris_atomic_save(v, flags); |
1da177e4 | 116 | retval = ++(v->counter) == 0; |
8d20a541 | 117 | cris_atomic_restore(v, flags); |
1da177e4 LT |
118 | return retval; |
119 | } | |
120 | ||
4a6dae6d NP |
121 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) |
122 | { | |
123 | int ret; | |
124 | unsigned long flags; | |
125 | ||
126 | cris_atomic_save(v, flags); | |
127 | ret = v->counter; | |
128 | if (likely(ret == old)) | |
129 | v->counter = new; | |
130 | cris_atomic_restore(v, flags); | |
131 | return ret; | |
132 | } | |
133 | ||
ffbf670f IM |
134 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) |
135 | ||
f24219b4 | 136 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) |
8426e1f6 NP |
137 | { |
138 | int ret; | |
139 | unsigned long flags; | |
140 | ||
141 | cris_atomic_save(v, flags); | |
142 | ret = v->counter; | |
143 | if (ret != u) | |
144 | v->counter += a; | |
145 | cris_atomic_restore(v, flags); | |
f24219b4 | 146 | return ret; |
8426e1f6 | 147 | } |
8426e1f6 | 148 | |
1da177e4 | 149 | #endif |