Line data Source code
1 : /* Atomic operations usable in machine independent code */
2 : #ifndef _LINUX_ATOMIC_H
3 : #define _LINUX_ATOMIC_H
4 : #include <asm/atomic.h>
5 :
6 : /*
7 : * Provide __deprecated wrappers for the new interface, avoid flag day changes.
8 : * We need the ugly external functions to break header recursion hell.
9 : */
10 : #ifndef smp_mb__before_atomic_inc
11 : static inline void __deprecated smp_mb__before_atomic_inc(void)
12 : {
13 : extern void __smp_mb__before_atomic(void);
14 : __smp_mb__before_atomic();
15 : }
16 : #endif
17 :
18 : #ifndef smp_mb__after_atomic_inc
19 : static inline void __deprecated smp_mb__after_atomic_inc(void)
20 : {
21 : extern void __smp_mb__after_atomic(void);
22 : __smp_mb__after_atomic();
23 : }
24 : #endif
25 :
26 : #ifndef smp_mb__before_atomic_dec
27 : static inline void __deprecated smp_mb__before_atomic_dec(void)
28 : {
29 : extern void __smp_mb__before_atomic(void);
30 : __smp_mb__before_atomic();
31 : }
32 : #endif
33 :
34 : #ifndef smp_mb__after_atomic_dec
35 : static inline void __deprecated smp_mb__after_atomic_dec(void)
36 : {
37 : extern void __smp_mb__after_atomic(void);
38 : __smp_mb__after_atomic();
39 : }
40 : #endif
41 :
42 : /**
43 : * atomic_add_unless - add unless the number is already a given value
44 : * @v: pointer of type atomic_t
45 : * @a: the amount to add to v...
46 : * @u: ...unless v is equal to u.
47 : *
48 : * Atomically adds @a to @v, so long as @v was not already @u.
49 : * Returns non-zero if @v was not @u, and zero otherwise.
50 : */
51 : static inline int atomic_add_unless(atomic_t *v, int a, int u)
52 : {
53 57141 : return __atomic_add_unless(v, a, u) != u;
54 : }
55 :
56 : /**
57 : * atomic_inc_not_zero - increment unless the number is zero
58 : * @v: pointer of type atomic_t
59 : *
60 : * Atomically increments @v by 1, so long as @v is non-zero.
61 : * Returns non-zero if @v was non-zero, and zero otherwise.
62 : */
63 : #ifndef atomic_inc_not_zero
64 : #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
65 : #endif
66 :
67 : /**
68 : * atomic_inc_not_zero_hint - increment if not null
69 : * @v: pointer of type atomic_t
70 : * @hint: probable value of the atomic before the increment
71 : *
72 : * This version of atomic_inc_not_zero() gives a hint of probable
73 : * value of the atomic. This helps processor to not read the memory
74 : * before doing the atomic read/modify/write cycle, lowering
75 : * number of bus transactions on some arches.
76 : *
77 : * Returns: 0 if increment was not done, 1 otherwise.
78 : */
79 : #ifndef atomic_inc_not_zero_hint
80 : static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
81 : {
82 : int val, c = hint;
83 :
84 : /* sanity test, should be removed by compiler if hint is a constant */
85 : if (!hint)
86 : return atomic_inc_not_zero(v);
87 :
88 : do {
89 : val = atomic_cmpxchg(v, c, c + 1);
90 : if (val == c)
91 : return 1;
92 : c = val;
93 : } while (c);
94 :
95 : return 0;
96 : }
97 : #endif
98 :
99 : #ifndef atomic_inc_unless_negative
100 : static inline int atomic_inc_unless_negative(atomic_t *p)
101 : {
102 : int v, v1;
103 : for (v = 0; v >= 0; v = v1) {
104 : v1 = atomic_cmpxchg(p, v, v + 1);
105 : if (likely(v1 == v))
106 : return 1;
107 : }
108 : return 0;
109 : }
110 : #endif
111 :
112 : #ifndef atomic_dec_unless_positive
113 : static inline int atomic_dec_unless_positive(atomic_t *p)
114 : {
115 : int v, v1;
116 : for (v = 0; v <= 0; v = v1) {
117 : v1 = atomic_cmpxchg(p, v, v - 1);
118 : if (likely(v1 == v))
119 : return 1;
120 : }
121 : return 0;
122 : }
123 : #endif
124 :
125 : /*
126 : * atomic_dec_if_positive - decrement by 1 if old value positive
127 : * @v: pointer of type atomic_t
128 : *
129 : * The function returns the old value of *v minus 1, even if
130 : * the atomic variable, v, was not decremented.
131 : */
132 : #ifndef atomic_dec_if_positive
133 : static inline int atomic_dec_if_positive(atomic_t *v)
134 : {
135 : int c, old, dec;
136 : c = atomic_read(v);
137 : for (;;) {
138 : dec = c - 1;
139 : if (unlikely(dec < 0))
140 : break;
141 : old = atomic_cmpxchg((v), c, dec);
142 : if (likely(old == c))
143 : break;
144 : c = old;
145 : }
146 : return dec;
147 : }
148 : #endif
149 :
150 : #ifndef CONFIG_ARCH_HAS_ATOMIC_OR
151 : static inline void atomic_or(int i, atomic_t *v)
152 : {
153 : int old;
154 : int new;
155 :
156 : do {
157 : old = atomic_read(v);
158 : new = old | i;
159 : } while (atomic_cmpxchg(v, old, new) != old);
160 : }
161 : #endif /* #ifndef CONFIG_ARCH_HAS_ATOMIC_OR */
162 :
163 : #include <asm-generic/atomic-long.h>
164 : #ifdef CONFIG_GENERIC_ATOMIC64
165 : #include <asm-generic/atomic64.h>
166 : #endif
167 : #endif /* _LINUX_ATOMIC_H */
|