]> git.karo-electronics.de Git - karo-tx-linux.git/blob - include/linux/atomic.h
Merge branch 'locking/arch-atomic' into locking/core, because it's ready for upstream
[karo-tx-linux.git] / include / linux / atomic.h
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  * atomic_add_unless - add unless the number is already a given value
8  * @v: pointer of type atomic_t
9  * @a: the amount to add to v...
10  * @u: ...unless v is equal to u.
11  *
12  * Atomically adds @a to @v, so long as @v was not already @u.
13  * Returns non-zero if @v was not @u, and zero otherwise.
14  */
15 static inline int atomic_add_unless(atomic_t *v, int a, int u)
16 {
17         return __atomic_add_unless(v, a, u) != u;
18 }
19
20 /**
21  * atomic_inc_not_zero - increment unless the number is zero
22  * @v: pointer of type atomic_t
23  *
24  * Atomically increments @v by 1, so long as @v is non-zero.
25  * Returns non-zero if @v was non-zero, and zero otherwise.
26  */
27 #ifndef atomic_inc_not_zero
28 #define atomic_inc_not_zero(v)          atomic_add_unless((v), 1, 0)
29 #endif
30
31 #ifndef atomic_andnot
32 static inline void atomic_andnot(int i, atomic_t *v)
33 {
34         atomic_and(~i, v);
35 }
36 #endif
37
38 static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
39 {
40         atomic_andnot(mask, v);
41 }
42
43 static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
44 {
45         atomic_or(mask, v);
46 }
47
48 /**
49  * atomic_inc_not_zero_hint - increment if not null
50  * @v: pointer of type atomic_t
51  * @hint: probable value of the atomic before the increment
52  *
53  * This version of atomic_inc_not_zero() gives a hint of probable
54  * value of the atomic. This helps processor to not read the memory
55  * before doing the atomic read/modify/write cycle, lowering
56  * number of bus transactions on some arches.
57  *
58  * Returns: 0 if increment was not done, 1 otherwise.
59  */
60 #ifndef atomic_inc_not_zero_hint
61 static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
62 {
63         int val, c = hint;
64
65         /* sanity test, should be removed by compiler if hint is a constant */
66         if (!hint)
67                 return atomic_inc_not_zero(v);
68
69         do {
70                 val = atomic_cmpxchg(v, c, c + 1);
71                 if (val == c)
72                         return 1;
73                 c = val;
74         } while (c);
75
76         return 0;
77 }
78 #endif
79
80 #ifndef atomic_inc_unless_negative
81 static inline int atomic_inc_unless_negative(atomic_t *p)
82 {
83         int v, v1;
84         for (v = 0; v >= 0; v = v1) {
85                 v1 = atomic_cmpxchg(p, v, v + 1);
86                 if (likely(v1 == v))
87                         return 1;
88         }
89         return 0;
90 }
91 #endif
92
93 #ifndef atomic_dec_unless_positive
94 static inline int atomic_dec_unless_positive(atomic_t *p)
95 {
96         int v, v1;
97         for (v = 0; v <= 0; v = v1) {
98                 v1 = atomic_cmpxchg(p, v, v - 1);
99                 if (likely(v1 == v))
100                         return 1;
101         }
102         return 0;
103 }
104 #endif
105
106 /*
107  * atomic_dec_if_positive - decrement by 1 if old value positive
108  * @v: pointer of type atomic_t
109  *
110  * The function returns the old value of *v minus 1, even if
111  * the atomic variable, v, was not decremented.
112  */
113 #ifndef atomic_dec_if_positive
114 static inline int atomic_dec_if_positive(atomic_t *v)
115 {
116         int c, old, dec;
117         c = atomic_read(v);
118         for (;;) {
119                 dec = c - 1;
120                 if (unlikely(dec < 0))
121                         break;
122                 old = atomic_cmpxchg((v), c, dec);
123                 if (likely(old == c))
124                         break;
125                 c = old;
126         }
127         return dec;
128 }
129 #endif
130
131 #include <asm-generic/atomic-long.h>
132 #ifdef CONFIG_GENERIC_ATOMIC64
133 #include <asm-generic/atomic64.h>
134 #endif
135
136 #ifndef atomic64_andnot
137 static inline void atomic64_andnot(long long i, atomic64_t *v)
138 {
139         atomic64_and(~i, v);
140 }
141 #endif
142
143 #endif /* _LINUX_ATOMIC_H */