blob: 8b98b423388fad55263cbab6683217bb7914d851 [file] [log] [blame]
Arun Sharmaacac43e2011-07-26 16:09:08 -07001/* Atomic operations usable in machine independent code */
Eric Dumazet3f9d35b2010-11-11 14:05:08 -08002#ifndef _LINUX_ATOMIC_H
3#define _LINUX_ATOMIC_H
4#include <asm/atomic.h>
5
6/**
Arun Sharmaf24219b2011-07-26 16:09:07 -07007 * 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 */
15static 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/**
Arun Sharma600634972011-07-26 16:09:06 -070021 * 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 */
Anton Blanchardb1ada602012-02-29 21:09:53 +000027#ifndef atomic_inc_not_zero
Arun Sharma600634972011-07-26 16:09:06 -070028#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
Anton Blanchardb1ada602012-02-29 21:09:53 +000029#endif
Arun Sharma600634972011-07-26 16:09:06 -070030
Peter Zijlstrade9e4322015-04-24 01:12:32 +020031#ifndef atomic_andnot
32static inline void atomic_andnot(int i, atomic_t *v)
33{
34 atomic_and(~i, v);
35}
36#endif
37
38static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
39{
40 atomic_andnot(mask, v);
41}
42
43static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
44{
45 atomic_or(mask, v);
46}
47
Arun Sharma600634972011-07-26 16:09:06 -070048/**
Eric Dumazet3f9d35b2010-11-11 14:05:08 -080049 * 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
61static 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
Al Viro07b8ce12011-06-20 10:52:57 -040080#ifndef atomic_inc_unless_negative
81static 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
94static 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
Shaohua Lie79bee22012-10-08 16:32:18 -0700106/*
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
114static 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
Arun Sharma78477772011-07-26 16:09:08 -0700131#include <asm-generic/atomic-long.h>
132#ifdef CONFIG_GENERIC_ATOMIC64
133#include <asm-generic/atomic64.h>
134#endif
Peter Zijlstrade9e4322015-04-24 01:12:32 +0200135
136#ifndef atomic64_andnot
137static inline void atomic64_andnot(long long i, atomic64_t *v)
138{
139 atomic64_and(~i, v);
140}
141#endif
142
Eric Dumazet3f9d35b2010-11-11 14:05:08 -0800143#endif /* _LINUX_ATOMIC_H */