Skip to content

Commit 28aa2bd

Browse files
Peter Zijlstraingomolnar
authored andcommitted
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
Now that all the architectures have implemented support for these new atomic primitives add on the generic infrastructure to expose and use it. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Borislav Petkov <bp@suse.de> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Will Deacon <will.deacon@arm.com> Cc: linux-arch@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent e121333 commit 28aa2bd

File tree

6 files changed

+493
-9
lines changed

6 files changed

+493
-9
lines changed

include/asm-generic/atomic-long.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,40 @@ static __always_inline void atomic_long_dec(atomic_long_t *l)
112112
ATOMIC_LONG_PFX(_dec)(v);
113113
}
114114

115+
#define ATOMIC_LONG_FETCH_OP(op, mo) \
116+
static inline long \
117+
atomic_long_fetch_##op##mo(long i, atomic_long_t *l) \
118+
{ \
119+
ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
120+
\
121+
return (long)ATOMIC_LONG_PFX(_fetch_##op##mo)(i, v); \
122+
}
123+
124+
ATOMIC_LONG_FETCH_OP(add, )
125+
ATOMIC_LONG_FETCH_OP(add, _relaxed)
126+
ATOMIC_LONG_FETCH_OP(add, _acquire)
127+
ATOMIC_LONG_FETCH_OP(add, _release)
128+
ATOMIC_LONG_FETCH_OP(sub, )
129+
ATOMIC_LONG_FETCH_OP(sub, _relaxed)
130+
ATOMIC_LONG_FETCH_OP(sub, _acquire)
131+
ATOMIC_LONG_FETCH_OP(sub, _release)
132+
ATOMIC_LONG_FETCH_OP(and, )
133+
ATOMIC_LONG_FETCH_OP(and, _relaxed)
134+
ATOMIC_LONG_FETCH_OP(and, _acquire)
135+
ATOMIC_LONG_FETCH_OP(and, _release)
136+
ATOMIC_LONG_FETCH_OP(andnot, )
137+
ATOMIC_LONG_FETCH_OP(andnot, _relaxed)
138+
ATOMIC_LONG_FETCH_OP(andnot, _acquire)
139+
ATOMIC_LONG_FETCH_OP(andnot, _release)
140+
ATOMIC_LONG_FETCH_OP(or, )
141+
ATOMIC_LONG_FETCH_OP(or, _relaxed)
142+
ATOMIC_LONG_FETCH_OP(or, _acquire)
143+
ATOMIC_LONG_FETCH_OP(or, _release)
144+
ATOMIC_LONG_FETCH_OP(xor, )
145+
ATOMIC_LONG_FETCH_OP(xor, _relaxed)
146+
ATOMIC_LONG_FETCH_OP(xor, _acquire)
147+
ATOMIC_LONG_FETCH_OP(xor, _release)
148+
115149
#define ATOMIC_LONG_OP(op) \
116150
static __always_inline void \
117151
atomic_long_##op(long i, atomic_long_t *l) \
@@ -124,9 +158,9 @@ atomic_long_##op(long i, atomic_long_t *l) \
124158
ATOMIC_LONG_OP(add)
125159
ATOMIC_LONG_OP(sub)
126160
ATOMIC_LONG_OP(and)
161+
ATOMIC_LONG_OP(andnot)
127162
ATOMIC_LONG_OP(or)
128163
ATOMIC_LONG_OP(xor)
129-
ATOMIC_LONG_OP(andnot)
130164

131165
#undef ATOMIC_LONG_OP
132166

include/asm-generic/atomic.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \
6161
return c c_op i; \
6262
}
6363

64+
#define ATOMIC_FETCH_OP(op, c_op) \
65+
static inline int atomic_fetch_##op(int i, atomic_t *v) \
66+
{ \
67+
int c, old; \
68+
\
69+
c = v->counter; \
70+
while ((old = cmpxchg(&v->counter, c, c c_op i)) != c) \
71+
c = old; \
72+
\
73+
return c; \
74+
}
75+
6476
#else
6577

6678
#include <linux/irqflags.h>
@@ -88,6 +100,20 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \
88100
return ret; \
89101
}
90102

103+
#define ATOMIC_FETCH_OP(op, c_op) \
104+
static inline int atomic_fetch_##op(int i, atomic_t *v) \
105+
{ \
106+
unsigned long flags; \
107+
int ret; \
108+
\
109+
raw_local_irq_save(flags); \
110+
ret = v->counter; \
111+
v->counter = v->counter c_op i; \
112+
raw_local_irq_restore(flags); \
113+
\
114+
return ret; \
115+
}
116+
91117
#endif /* CONFIG_SMP */
92118

93119
#ifndef atomic_add_return
@@ -98,6 +124,28 @@ ATOMIC_OP_RETURN(add, +)
98124
ATOMIC_OP_RETURN(sub, -)
99125
#endif
100126

127+
#ifndef atomic_fetch_add
128+
ATOMIC_FETCH_OP(add, +)
129+
#endif
130+
131+
#ifndef atomic_fetch_sub
132+
ATOMIC_FETCH_OP(sub, -)
133+
#endif
134+
135+
#ifndef atomic_fetch_and
136+
ATOMIC_FETCH_OP(and, &)
137+
#endif
138+
139+
#ifndef atomic_fetch_or
140+
#define atomic_fetch_or atomic_fetch_or
141+
142+
ATOMIC_FETCH_OP(or, |)
143+
#endif
144+
145+
#ifndef atomic_fetch_xor
146+
ATOMIC_FETCH_OP(xor, ^)
147+
#endif
148+
101149
#ifndef atomic_and
102150
ATOMIC_OP(and, &)
103151
#endif
@@ -110,6 +158,7 @@ ATOMIC_OP(or, |)
110158
ATOMIC_OP(xor, ^)
111159
#endif
112160

161+
#undef ATOMIC_FETCH_OP
113162
#undef ATOMIC_OP_RETURN
114163
#undef ATOMIC_OP
115164

include/asm-generic/atomic64.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,23 @@ extern void atomic64_##op(long long a, atomic64_t *v);
2727
#define ATOMIC64_OP_RETURN(op) \
2828
extern long long atomic64_##op##_return(long long a, atomic64_t *v);
2929

30-
#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op)
30+
#define ATOMIC64_FETCH_OP(op) \
31+
extern long long atomic64_fetch_##op(long long a, atomic64_t *v);
32+
33+
#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) ATOMIC64_FETCH_OP(op)
3134

3235
ATOMIC64_OPS(add)
3336
ATOMIC64_OPS(sub)
3437

35-
ATOMIC64_OP(and)
36-
ATOMIC64_OP(or)
37-
ATOMIC64_OP(xor)
38+
#undef ATOMIC64_OPS
39+
#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_FETCH_OP(op)
40+
41+
ATOMIC64_OPS(and)
42+
ATOMIC64_OPS(or)
43+
ATOMIC64_OPS(xor)
3844

3945
#undef ATOMIC64_OPS
46+
#undef ATOMIC64_FETCH_OP
4047
#undef ATOMIC64_OP_RETURN
4148
#undef ATOMIC64_OP
4249

0 commit comments

Comments
 (0)