aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2016-04-17 18:54:38 -0400
committerIngo Molnar <mingo@kernel.org>2016-06-16 04:48:32 -0400
commit28aa2bda2211f4327d83b44a4f917b4a061b1c56 (patch)
treee47ab8a7c49f19bd42722dcc2b8cf083e08cf270 /lib
parente12133324b7daaa176bb687c1eb59e1a6b203da4 (diff)
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/atomic64.c32
-rw-r--r--lib/atomic64_test.c34
2 files changed, 62 insertions, 4 deletions
diff --git a/lib/atomic64.c b/lib/atomic64.c
index 2886ebac6567..53c2d5edc826 100644
--- a/lib/atomic64.c
+++ b/lib/atomic64.c
@@ -96,17 +96,41 @@ long long atomic64_##op##_return(long long a, atomic64_t *v) \
96} \ 96} \
97EXPORT_SYMBOL(atomic64_##op##_return); 97EXPORT_SYMBOL(atomic64_##op##_return);
98 98
99#define ATOMIC64_FETCH_OP(op, c_op) \
100long long atomic64_fetch_##op(long long a, atomic64_t *v) \
101{ \
102 unsigned long flags; \
103 raw_spinlock_t *lock = lock_addr(v); \
104 long long val; \
105 \
106 raw_spin_lock_irqsave(lock, flags); \
107 val = v->counter; \
108 v->counter c_op a; \
109 raw_spin_unlock_irqrestore(lock, flags); \
110 return val; \
111} \
112EXPORT_SYMBOL(atomic64_fetch_##op);
113
99#define ATOMIC64_OPS(op, c_op) \ 114#define ATOMIC64_OPS(op, c_op) \
100 ATOMIC64_OP(op, c_op) \ 115 ATOMIC64_OP(op, c_op) \
101 ATOMIC64_OP_RETURN(op, c_op) 116 ATOMIC64_OP_RETURN(op, c_op) \
117 ATOMIC64_FETCH_OP(op, c_op)
102 118
103ATOMIC64_OPS(add, +=) 119ATOMIC64_OPS(add, +=)
104ATOMIC64_OPS(sub, -=) 120ATOMIC64_OPS(sub, -=)
105ATOMIC64_OP(and, &=)
106ATOMIC64_OP(or, |=)
107ATOMIC64_OP(xor, ^=)
108 121
109#undef ATOMIC64_OPS 122#undef ATOMIC64_OPS
123#define ATOMIC64_OPS(op, c_op) \
124 ATOMIC64_OP(op, c_op) \
125 ATOMIC64_OP_RETURN(op, c_op) \
126 ATOMIC64_FETCH_OP(op, c_op)
127
128ATOMIC64_OPS(and, &=)
129ATOMIC64_OPS(or, |=)
130ATOMIC64_OPS(xor, ^=)
131
132#undef ATOMIC64_OPS
133#undef ATOMIC64_FETCH_OP
110#undef ATOMIC64_OP_RETURN 134#undef ATOMIC64_OP_RETURN
111#undef ATOMIC64_OP 135#undef ATOMIC64_OP
112 136
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
index 123481814320..dbb369145dda 100644
--- a/lib/atomic64_test.c
+++ b/lib/atomic64_test.c
@@ -53,11 +53,25 @@ do { \
53 BUG_ON(atomic##bit##_read(&v) != r); \ 53 BUG_ON(atomic##bit##_read(&v) != r); \
54} while (0) 54} while (0)
55 55
56#define TEST_FETCH(bit, op, c_op, val) \
57do { \
58 atomic##bit##_set(&v, v0); \
59 r = v0; \
60 r c_op val; \
61 BUG_ON(atomic##bit##_##op(val, &v) != v0); \
62 BUG_ON(atomic##bit##_read(&v) != r); \
63} while (0)
64
56#define RETURN_FAMILY_TEST(bit, op, c_op, val) \ 65#define RETURN_FAMILY_TEST(bit, op, c_op, val) \
57do { \ 66do { \
58 FAMILY_TEST(TEST_RETURN, bit, op, c_op, val); \ 67 FAMILY_TEST(TEST_RETURN, bit, op, c_op, val); \
59} while (0) 68} while (0)
60 69
70#define FETCH_FAMILY_TEST(bit, op, c_op, val) \
71do { \
72 FAMILY_TEST(TEST_FETCH, bit, op, c_op, val); \
73} while (0)
74
61#define TEST_ARGS(bit, op, init, ret, expect, args...) \ 75#define TEST_ARGS(bit, op, init, ret, expect, args...) \
62do { \ 76do { \
63 atomic##bit##_set(&v, init); \ 77 atomic##bit##_set(&v, init); \
@@ -114,6 +128,16 @@ static __init void test_atomic(void)
114 RETURN_FAMILY_TEST(, sub_return, -=, onestwos); 128 RETURN_FAMILY_TEST(, sub_return, -=, onestwos);
115 RETURN_FAMILY_TEST(, sub_return, -=, -one); 129 RETURN_FAMILY_TEST(, sub_return, -=, -one);
116 130
131 FETCH_FAMILY_TEST(, fetch_add, +=, onestwos);
132 FETCH_FAMILY_TEST(, fetch_add, +=, -one);
133 FETCH_FAMILY_TEST(, fetch_sub, -=, onestwos);
134 FETCH_FAMILY_TEST(, fetch_sub, -=, -one);
135
136 FETCH_FAMILY_TEST(, fetch_or, |=, v1);
137 FETCH_FAMILY_TEST(, fetch_and, &=, v1);
138 FETCH_FAMILY_TEST(, fetch_andnot, &= ~, v1);
139 FETCH_FAMILY_TEST(, fetch_xor, ^=, v1);
140
117 INC_RETURN_FAMILY_TEST(, v0); 141 INC_RETURN_FAMILY_TEST(, v0);
118 DEC_RETURN_FAMILY_TEST(, v0); 142 DEC_RETURN_FAMILY_TEST(, v0);
119 143
@@ -154,6 +178,16 @@ static __init void test_atomic64(void)
154 RETURN_FAMILY_TEST(64, sub_return, -=, onestwos); 178 RETURN_FAMILY_TEST(64, sub_return, -=, onestwos);
155 RETURN_FAMILY_TEST(64, sub_return, -=, -one); 179 RETURN_FAMILY_TEST(64, sub_return, -=, -one);
156 180
181 FETCH_FAMILY_TEST(64, fetch_add, +=, onestwos);
182 FETCH_FAMILY_TEST(64, fetch_add, +=, -one);
183 FETCH_FAMILY_TEST(64, fetch_sub, -=, onestwos);
184 FETCH_FAMILY_TEST(64, fetch_sub, -=, -one);
185
186 FETCH_FAMILY_TEST(64, fetch_or, |=, v1);
187 FETCH_FAMILY_TEST(64, fetch_and, &=, v1);
188 FETCH_FAMILY_TEST(64, fetch_andnot, &= ~, v1);
189 FETCH_FAMILY_TEST(64, fetch_xor, ^=, v1);
190
157 INIT(v0); 191 INIT(v0);
158 atomic64_inc(&v); 192 atomic64_inc(&v);
159 r += one; 193 r += one;