diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 15:41:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 15:41:29 -0400 |
commit | c86ad14d305d2429c3da19462440bac50c183def (patch) | |
tree | bd794cd72476661faf82c440063c217bb978ce44 /lib | |
parent | a2303849a6b4b7ba59667091e00d6bb194071d9a (diff) | |
parent | f06628638cf6e75f179742b6c1b35076965b9fdd (diff) |
Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking updates from Ingo Molnar:
"The locking tree was busier in this cycle than the usual pattern - a
couple of major projects happened to coincide.
The main changes are:
- implement the atomic_fetch_{add,sub,and,or,xor}() API natively
across all SMP architectures (Peter Zijlstra)
- add atomic_fetch_{inc/dec}() as well, using the generic primitives
(Davidlohr Bueso)
- optimize various aspects of rwsems (Jason Low, Davidlohr Bueso,
Waiman Long)
- optimize smp_cond_load_acquire() on arm64 and implement LSE based
atomic{,64}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
on arm64 (Will Deacon)
- introduce smp_acquire__after_ctrl_dep() and fix various barrier
mis-uses and bugs (Peter Zijlstra)
- after discovering ancient spin_unlock_wait() barrier bugs in its
implementation and usage, strengthen its semantics and update/fix
usage sites (Peter Zijlstra)
- optimize mutex_trylock() fastpath (Peter Zijlstra)
- ... misc fixes and cleanups"
* 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (67 commits)
locking/atomic: Introduce inc/dec variants for the atomic_fetch_$op() API
locking/barriers, arch/arm64: Implement LDXR+WFE based smp_cond_load_acquire()
locking/static_keys: Fix non static symbol Sparse warning
locking/qspinlock: Use __this_cpu_dec() instead of full-blown this_cpu_dec()
locking/atomic, arch/tile: Fix tilepro build
locking/atomic, arch/m68k: Remove comment
locking/atomic, arch/arc: Fix build
locking/Documentation: Clarify limited control-dependency scope
locking/atomic, arch/rwsem: Employ atomic_long_fetch_add()
locking/atomic, arch/qrwlock: Employ atomic_fetch_add_acquire()
locking/atomic, arch/mips: Convert to _relaxed atomics
locking/atomic, arch/alpha: Convert to _relaxed atomics
locking/atomic: Remove the deprecated atomic_{set,clear}_mask() functions
locking/atomic: Remove linux/atomic.h:atomic_fetch_or()
locking/atomic: Implement atomic{,64,_long}_fetch_{add,sub,and,andnot,or,xor}{,_relaxed,_acquire,_release}()
locking/atomic: Fix atomic64_relaxed() bits
locking/atomic, arch/xtensa: Implement atomic_fetch_{add,sub,and,or,xor}()
locking/atomic, arch/x86: Implement atomic{,64}_fetch_{add,sub,and,or,xor}()
locking/atomic, arch/tile: Implement atomic{,64}_fetch_{add,sub,and,or,xor}()
locking/atomic, arch/sparc: Implement atomic{,64}_fetch_{add,sub,and,or,xor}()
...
Diffstat (limited to 'lib')
-rw-r--r-- | lib/atomic64.c | 32 | ||||
-rw-r--r-- | lib/atomic64_test.c | 34 |
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 | } \ |
97 | EXPORT_SYMBOL(atomic64_##op##_return); | 97 | EXPORT_SYMBOL(atomic64_##op##_return); |
98 | 98 | ||
99 | #define ATOMIC64_FETCH_OP(op, c_op) \ | ||
100 | long 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 | } \ | ||
112 | EXPORT_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 | ||
103 | ATOMIC64_OPS(add, +=) | 119 | ATOMIC64_OPS(add, +=) |
104 | ATOMIC64_OPS(sub, -=) | 120 | ATOMIC64_OPS(sub, -=) |
105 | ATOMIC64_OP(and, &=) | ||
106 | ATOMIC64_OP(or, |=) | ||
107 | ATOMIC64_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 | |||
128 | ATOMIC64_OPS(and, &=) | ||
129 | ATOMIC64_OPS(or, |=) | ||
130 | ATOMIC64_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) \ | ||
57 | do { \ | ||
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) \ |
57 | do { \ | 66 | do { \ |
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) \ | ||
71 | do { \ | ||
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...) \ |
62 | do { \ | 76 | do { \ |
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; |