Skip to content

Commit fcfdfe3

Browse files
wildea01Ingo Molnar
authored andcommitted
locking/barriers: Introduce smp_cond_load_relaxed() and atomic_cond_read_relaxed()
Whilst we currently provide smp_cond_load_acquire() and atomic_cond_read_acquire(), there are cases where the ACQUIRE semantics are not required because of a subsequent fence or release operation once the conditional loop has exited. This patch adds relaxed versions of the conditional spinning primitives to avoid unnecessary barrier overhead on architectures such as arm64. Signed-off-by: Will Deacon <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Waiman Long <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 0644f18 commit fcfdfe3

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

include/asm-generic/atomic-long.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
244244
#define atomic_long_inc_not_zero(l) \
245245
ATOMIC_LONG_PFX(_inc_not_zero)((ATOMIC_LONG_PFX(_t) *)(l))
246246

247+
#define atomic_long_cond_read_relaxed(v, c) \
248+
ATOMIC_LONG_PFX(_cond_read_relaxed)((ATOMIC_LONG_PFX(_t) *)(v), (c))
247249
#define atomic_long_cond_read_acquire(v, c) \
248250
ATOMIC_LONG_PFX(_cond_read_acquire)((ATOMIC_LONG_PFX(_t) *)(v), (c))
249251

include/asm-generic/barrier.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,18 +221,17 @@ do { \
221221
#endif
222222

223223
/**
224-
* smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering
224+
* smp_cond_load_relaxed() - (Spin) wait for cond with no ordering guarantees
225225
* @ptr: pointer to the variable to wait on
226226
* @cond: boolean expression to wait for
227227
*
228-
* Equivalent to using smp_load_acquire() on the condition variable but employs
229-
* the control dependency of the wait to reduce the barrier on many platforms.
228+
* Equivalent to using READ_ONCE() on the condition variable.
230229
*
231230
* Due to C lacking lambda expressions we load the value of *ptr into a
232231
* pre-named variable @VAL to be used in @cond.
233232
*/
234-
#ifndef smp_cond_load_acquire
235-
#define smp_cond_load_acquire(ptr, cond_expr) ({ \
233+
#ifndef smp_cond_load_relaxed
234+
#define smp_cond_load_relaxed(ptr, cond_expr) ({ \
236235
typeof(ptr) __PTR = (ptr); \
237236
typeof(*ptr) VAL; \
238237
for (;;) { \
@@ -241,10 +240,26 @@ do { \
241240
break; \
242241
cpu_relax(); \
243242
} \
244-
smp_acquire__after_ctrl_dep(); \
245243
VAL; \
246244
})
247245
#endif
248246

247+
/**
248+
* smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering
249+
* @ptr: pointer to the variable to wait on
250+
* @cond: boolean expression to wait for
251+
*
252+
* Equivalent to using smp_load_acquire() on the condition variable but employs
253+
* the control dependency of the wait to reduce the barrier on many platforms.
254+
*/
255+
#ifndef smp_cond_load_acquire
256+
#define smp_cond_load_acquire(ptr, cond_expr) ({ \
257+
typeof(*ptr) _val; \
258+
_val = smp_cond_load_relaxed(ptr, cond_expr); \
259+
smp_acquire__after_ctrl_dep(); \
260+
_val; \
261+
})
262+
#endif
263+
249264
#endif /* !__ASSEMBLY__ */
250265
#endif /* __ASM_GENERIC_BARRIER_H */

include/linux/atomic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ static inline int atomic_dec_if_positive(atomic_t *v)
654654
}
655655
#endif
656656

657+
#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
657658
#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
658659

659660
#ifdef CONFIG_GENERIC_ATOMIC64
@@ -1075,6 +1076,7 @@ static inline long long atomic64_fetch_andnot_release(long long i, atomic64_t *v
10751076
}
10761077
#endif
10771078

1079+
#define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c))
10781080
#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
10791081

10801082
#include <asm-generic/atomic-long.h>

0 commit comments

Comments
 (0)