Skip to content

Commit 2319be1

Browse files
committed
Merge tag 'locking-core-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking updates from Ingo Molnar: - rwsem cleanups & optimizations/fixes: - Conditionally wake waiters in reader/writer slowpaths - Always try to wake waiters in out_nolock path - Add try_cmpxchg64() implementation, with arch optimizations - and use it to micro-optimize sched_clock_{local,remote}() - Various force-inlining fixes to address objdump instrumentation-check warnings - Add lock contention tracepoints: lock:contention_begin lock:contention_end - Misc smaller fixes & cleanups * tag 'locking-core-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched/clock: Use try_cmpxchg64 in sched_clock_{local,remote} locking/atomic/x86: Introduce arch_try_cmpxchg64 locking/atomic: Add generic try_cmpxchg64 support futex: Remove a PREEMPT_RT_FULL reference. locking/qrwlock: Change "queue rwlock" to "queued rwlock" lockdep: Delete local_irq_enable_in_hardirq() locking/mutex: Make contention tracepoints more consistent wrt adaptive spinning locking: Apply contention tracepoints in the slow path locking: Add lock contention tracepoints locking/rwsem: Always try to wake waiters in out_nolock path locking/rwsem: Conditionally wake waiters in reader/writer slowpaths locking/rwsem: No need to check for handoff bit if wait queue empty lockdep: Fix -Wunused-parameter for _THIS_IP_ x86/mm: Force-inline __phys_addr_nodebug() x86/kvm/svm: Force-inline GHCB accessors task_stack, x86/cea: Force-inline stack helpers
2 parents 143a625 + 8491d1b commit 2319be1

31 files changed

+412
-148
lines changed

arch/arm64/kernel/entry-common.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static __always_inline void __exit_to_kernel_mode(struct pt_regs *regs)
7575
if (interrupts_enabled(regs)) {
7676
if (regs->exit_rcu) {
7777
trace_hardirqs_on_prepare();
78-
lockdep_hardirqs_on_prepare(CALLER_ADDR0);
78+
lockdep_hardirqs_on_prepare();
7979
rcu_irq_exit();
8080
lockdep_hardirqs_on(CALLER_ADDR0);
8181
return;
@@ -121,7 +121,7 @@ static __always_inline void enter_from_user_mode(struct pt_regs *regs)
121121
static __always_inline void __exit_to_user_mode(void)
122122
{
123123
trace_hardirqs_on_prepare();
124-
lockdep_hardirqs_on_prepare(CALLER_ADDR0);
124+
lockdep_hardirqs_on_prepare();
125125
user_enter_irqoff();
126126
lockdep_hardirqs_on(CALLER_ADDR0);
127127
}
@@ -179,7 +179,7 @@ static void noinstr arm64_exit_nmi(struct pt_regs *regs)
179179
ftrace_nmi_exit();
180180
if (restore) {
181181
trace_hardirqs_on_prepare();
182-
lockdep_hardirqs_on_prepare(CALLER_ADDR0);
182+
lockdep_hardirqs_on_prepare();
183183
}
184184

185185
rcu_nmi_exit();
@@ -215,7 +215,7 @@ static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
215215

216216
if (restore) {
217217
trace_hardirqs_on_prepare();
218-
lockdep_hardirqs_on_prepare(CALLER_ADDR0);
218+
lockdep_hardirqs_on_prepare();
219219
}
220220

221221
rcu_nmi_exit();

arch/x86/include/asm/cmpxchg_32.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ static inline void set_64bit(volatile u64 *ptr, u64 value)
4242
#define arch_cmpxchg64_local(ptr, o, n) \
4343
((__typeof__(*(ptr)))__cmpxchg64_local((ptr), (unsigned long long)(o), \
4444
(unsigned long long)(n)))
45+
#define arch_try_cmpxchg64(ptr, po, n) \
46+
__try_cmpxchg64((ptr), (unsigned long long *)(po), \
47+
(unsigned long long)(n))
4548
#endif
4649

4750
static inline u64 __cmpxchg64(volatile u64 *ptr, u64 old, u64 new)
@@ -70,6 +73,24 @@ static inline u64 __cmpxchg64_local(volatile u64 *ptr, u64 old, u64 new)
7073
return prev;
7174
}
7275

76+
static inline bool __try_cmpxchg64(volatile u64 *ptr, u64 *pold, u64 new)
77+
{
78+
bool success;
79+
u64 old = *pold;
80+
asm volatile(LOCK_PREFIX "cmpxchg8b %[ptr]"
81+
CC_SET(z)
82+
: CC_OUT(z) (success),
83+
[ptr] "+m" (*ptr),
84+
"+A" (old)
85+
: "b" ((u32)new),
86+
"c" ((u32)(new >> 32))
87+
: "memory");
88+
89+
if (unlikely(!success))
90+
*pold = old;
91+
return success;
92+
}
93+
7394
#ifndef CONFIG_X86_CMPXCHG64
7495
/*
7596
* Building a kernel capable running on 80386 and 80486. It may be necessary

arch/x86/include/asm/cmpxchg_64.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ static inline void set_64bit(volatile u64 *ptr, u64 val)
1919
arch_cmpxchg_local((ptr), (o), (n)); \
2020
})
2121

22+
#define arch_try_cmpxchg64(ptr, po, n) \
23+
({ \
24+
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
25+
arch_try_cmpxchg((ptr), (po), (n)); \
26+
})
27+
2228
#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX16)
2329

2430
#endif /* _ASM_X86_CMPXCHG_64_H */

arch/x86/include/asm/cpu_entry_area.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
143143

144144
extern struct cpu_entry_area *get_cpu_entry_area(int cpu);
145145

146-
static inline struct entry_stack *cpu_entry_stack(int cpu)
146+
static __always_inline struct entry_stack *cpu_entry_stack(int cpu)
147147
{
148148
return &get_cpu_entry_area(cpu)->entry_stack_page.stack;
149149
}

arch/x86/include/asm/page_64.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extern unsigned long page_offset_base;
1616
extern unsigned long vmalloc_base;
1717
extern unsigned long vmemmap_base;
1818

19-
static inline unsigned long __phys_addr_nodebug(unsigned long x)
19+
static __always_inline unsigned long __phys_addr_nodebug(unsigned long x)
2020
{
2121
unsigned long y = x - __START_KERNEL_map;
2222

arch/x86/include/asm/svm.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,23 +569,23 @@ struct vmcb {
569569
(offsetof(struct ghcb_save_area, field) / sizeof(u64))
570570

571571
#define DEFINE_GHCB_ACCESSORS(field) \
572-
static inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb) \
572+
static __always_inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb) \
573573
{ \
574574
return test_bit(GHCB_BITMAP_IDX(field), \
575575
(unsigned long *)&ghcb->save.valid_bitmap); \
576576
} \
577577
\
578-
static inline u64 ghcb_get_##field(struct ghcb *ghcb) \
578+
static __always_inline u64 ghcb_get_##field(struct ghcb *ghcb) \
579579
{ \
580580
return ghcb->save.field; \
581581
} \
582582
\
583-
static inline u64 ghcb_get_##field##_if_valid(struct ghcb *ghcb) \
583+
static __always_inline u64 ghcb_get_##field##_if_valid(struct ghcb *ghcb) \
584584
{ \
585585
return ghcb_##field##_is_valid(ghcb) ? ghcb->save.field : 0; \
586586
} \
587587
\
588-
static inline void ghcb_set_##field(struct ghcb *ghcb, u64 value) \
588+
static __always_inline void ghcb_set_##field(struct ghcb *ghcb, u64 value) \
589589
{ \
590590
__set_bit(GHCB_BITMAP_IDX(field), \
591591
(unsigned long *)&ghcb->save.valid_bitmap); \

include/asm-generic/qrwlock.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ extern void queued_read_lock_slowpath(struct qrwlock *lock);
3333
extern void queued_write_lock_slowpath(struct qrwlock *lock);
3434

3535
/**
36-
* queued_read_trylock - try to acquire read lock of a queue rwlock
37-
* @lock : Pointer to queue rwlock structure
36+
* queued_read_trylock - try to acquire read lock of a queued rwlock
37+
* @lock : Pointer to queued rwlock structure
3838
* Return: 1 if lock acquired, 0 if failed
3939
*/
4040
static inline int queued_read_trylock(struct qrwlock *lock)
@@ -52,8 +52,8 @@ static inline int queued_read_trylock(struct qrwlock *lock)
5252
}
5353

5454
/**
55-
* queued_write_trylock - try to acquire write lock of a queue rwlock
56-
* @lock : Pointer to queue rwlock structure
55+
* queued_write_trylock - try to acquire write lock of a queued rwlock
56+
* @lock : Pointer to queued rwlock structure
5757
* Return: 1 if lock acquired, 0 if failed
5858
*/
5959
static inline int queued_write_trylock(struct qrwlock *lock)
@@ -68,8 +68,8 @@ static inline int queued_write_trylock(struct qrwlock *lock)
6868
_QW_LOCKED));
6969
}
7070
/**
71-
* queued_read_lock - acquire read lock of a queue rwlock
72-
* @lock: Pointer to queue rwlock structure
71+
* queued_read_lock - acquire read lock of a queued rwlock
72+
* @lock: Pointer to queued rwlock structure
7373
*/
7474
static inline void queued_read_lock(struct qrwlock *lock)
7575
{
@@ -84,8 +84,8 @@ static inline void queued_read_lock(struct qrwlock *lock)
8484
}
8585

8686
/**
87-
* queued_write_lock - acquire write lock of a queue rwlock
88-
* @lock : Pointer to queue rwlock structure
87+
* queued_write_lock - acquire write lock of a queued rwlock
88+
* @lock : Pointer to queued rwlock structure
8989
*/
9090
static inline void queued_write_lock(struct qrwlock *lock)
9191
{
@@ -98,8 +98,8 @@ static inline void queued_write_lock(struct qrwlock *lock)
9898
}
9999

100100
/**
101-
* queued_read_unlock - release read lock of a queue rwlock
102-
* @lock : Pointer to queue rwlock structure
101+
* queued_read_unlock - release read lock of a queued rwlock
102+
* @lock : Pointer to queued rwlock structure
103103
*/
104104
static inline void queued_read_unlock(struct qrwlock *lock)
105105
{
@@ -110,8 +110,8 @@ static inline void queued_read_unlock(struct qrwlock *lock)
110110
}
111111

112112
/**
113-
* queued_write_unlock - release write lock of a queue rwlock
114-
* @lock : Pointer to queue rwlock structure
113+
* queued_write_unlock - release write lock of a queued rwlock
114+
* @lock : Pointer to queued rwlock structure
115115
*/
116116
static inline void queued_write_unlock(struct qrwlock *lock)
117117
{
@@ -120,7 +120,7 @@ static inline void queued_write_unlock(struct qrwlock *lock)
120120

121121
/**
122122
* queued_rwlock_is_contended - check if the lock is contended
123-
* @lock : Pointer to queue rwlock structure
123+
* @lock : Pointer to queued rwlock structure
124124
* Return: 1 if lock contended, 0 otherwise
125125
*/
126126
static inline int queued_rwlock_is_contended(struct qrwlock *lock)
@@ -130,7 +130,7 @@ static inline int queued_rwlock_is_contended(struct qrwlock *lock)
130130

131131
/*
132132
* Remapping rwlock architecture specific functions to the corresponding
133-
* queue rwlock functions.
133+
* queued rwlock functions.
134134
*/
135135
#define arch_read_lock(l) queued_read_lock(l)
136136
#define arch_write_lock(l) queued_write_lock(l)

include/asm-generic/qrwlock_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <asm/spinlock_types.h>
88

99
/*
10-
* The queue read/write lock data structure
10+
* The queued read/write lock data structure
1111
*/
1212

1313
typedef struct qrwlock {

include/linux/atomic/atomic-arch-fallback.h

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,76 @@
147147

148148
#endif /* arch_try_cmpxchg_relaxed */
149149

150+
#ifndef arch_try_cmpxchg64_relaxed
151+
#ifdef arch_try_cmpxchg64
152+
#define arch_try_cmpxchg64_acquire arch_try_cmpxchg64
153+
#define arch_try_cmpxchg64_release arch_try_cmpxchg64
154+
#define arch_try_cmpxchg64_relaxed arch_try_cmpxchg64
155+
#endif /* arch_try_cmpxchg64 */
156+
157+
#ifndef arch_try_cmpxchg64
158+
#define arch_try_cmpxchg64(_ptr, _oldp, _new) \
159+
({ \
160+
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
161+
___r = arch_cmpxchg64((_ptr), ___o, (_new)); \
162+
if (unlikely(___r != ___o)) \
163+
*___op = ___r; \
164+
likely(___r == ___o); \
165+
})
166+
#endif /* arch_try_cmpxchg64 */
167+
168+
#ifndef arch_try_cmpxchg64_acquire
169+
#define arch_try_cmpxchg64_acquire(_ptr, _oldp, _new) \
170+
({ \
171+
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
172+
___r = arch_cmpxchg64_acquire((_ptr), ___o, (_new)); \
173+
if (unlikely(___r != ___o)) \
174+
*___op = ___r; \
175+
likely(___r == ___o); \
176+
})
177+
#endif /* arch_try_cmpxchg64_acquire */
178+
179+
#ifndef arch_try_cmpxchg64_release
180+
#define arch_try_cmpxchg64_release(_ptr, _oldp, _new) \
181+
({ \
182+
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
183+
___r = arch_cmpxchg64_release((_ptr), ___o, (_new)); \
184+
if (unlikely(___r != ___o)) \
185+
*___op = ___r; \
186+
likely(___r == ___o); \
187+
})
188+
#endif /* arch_try_cmpxchg64_release */
189+
190+
#ifndef arch_try_cmpxchg64_relaxed
191+
#define arch_try_cmpxchg64_relaxed(_ptr, _oldp, _new) \
192+
({ \
193+
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
194+
___r = arch_cmpxchg64_relaxed((_ptr), ___o, (_new)); \
195+
if (unlikely(___r != ___o)) \
196+
*___op = ___r; \
197+
likely(___r == ___o); \
198+
})
199+
#endif /* arch_try_cmpxchg64_relaxed */
200+
201+
#else /* arch_try_cmpxchg64_relaxed */
202+
203+
#ifndef arch_try_cmpxchg64_acquire
204+
#define arch_try_cmpxchg64_acquire(...) \
205+
__atomic_op_acquire(arch_try_cmpxchg64, __VA_ARGS__)
206+
#endif
207+
208+
#ifndef arch_try_cmpxchg64_release
209+
#define arch_try_cmpxchg64_release(...) \
210+
__atomic_op_release(arch_try_cmpxchg64, __VA_ARGS__)
211+
#endif
212+
213+
#ifndef arch_try_cmpxchg64
214+
#define arch_try_cmpxchg64(...) \
215+
__atomic_op_fence(arch_try_cmpxchg64, __VA_ARGS__)
216+
#endif
217+
218+
#endif /* arch_try_cmpxchg64_relaxed */
219+
150220
#ifndef arch_atomic_read_acquire
151221
static __always_inline int
152222
arch_atomic_read_acquire(const atomic_t *v)
@@ -2386,4 +2456,4 @@ arch_atomic64_dec_if_positive(atomic64_t *v)
23862456
#endif
23872457

23882458
#endif /* _LINUX_ATOMIC_FALLBACK_H */
2389-
// 8e2cc06bc0d2c0967d2f8424762bd48555ee40ae
2459+
// b5e87bdd5ede61470c29f7a7e4de781af3770f09

include/linux/atomic/atomic-instrumented.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,44 @@ atomic_long_dec_if_positive(atomic_long_t *v)
20062006
arch_try_cmpxchg_relaxed(__ai_ptr, __ai_oldp, __VA_ARGS__); \
20072007
})
20082008

2009+
#define try_cmpxchg64(ptr, oldp, ...) \
2010+
({ \
2011+
typeof(ptr) __ai_ptr = (ptr); \
2012+
typeof(oldp) __ai_oldp = (oldp); \
2013+
kcsan_mb(); \
2014+
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
2015+
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
2016+
arch_try_cmpxchg64(__ai_ptr, __ai_oldp, __VA_ARGS__); \
2017+
})
2018+
2019+
#define try_cmpxchg64_acquire(ptr, oldp, ...) \
2020+
({ \
2021+
typeof(ptr) __ai_ptr = (ptr); \
2022+
typeof(oldp) __ai_oldp = (oldp); \
2023+
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
2024+
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
2025+
arch_try_cmpxchg64_acquire(__ai_ptr, __ai_oldp, __VA_ARGS__); \
2026+
})
2027+
2028+
#define try_cmpxchg64_release(ptr, oldp, ...) \
2029+
({ \
2030+
typeof(ptr) __ai_ptr = (ptr); \
2031+
typeof(oldp) __ai_oldp = (oldp); \
2032+
kcsan_release(); \
2033+
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
2034+
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
2035+
arch_try_cmpxchg64_release(__ai_ptr, __ai_oldp, __VA_ARGS__); \
2036+
})
2037+
2038+
#define try_cmpxchg64_relaxed(ptr, oldp, ...) \
2039+
({ \
2040+
typeof(ptr) __ai_ptr = (ptr); \
2041+
typeof(oldp) __ai_oldp = (oldp); \
2042+
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
2043+
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
2044+
arch_try_cmpxchg64_relaxed(__ai_ptr, __ai_oldp, __VA_ARGS__); \
2045+
})
2046+
20092047
#define cmpxchg_local(ptr, ...) \
20102048
({ \
20112049
typeof(ptr) __ai_ptr = (ptr); \
@@ -2045,4 +2083,4 @@ atomic_long_dec_if_positive(atomic_long_t *v)
20452083
})
20462084

20472085
#endif /* _LINUX_ATOMIC_INSTRUMENTED_H */
2048-
// 87c974b93032afd42143613434d1a7788fa598f9
2086+
// 764f741eb77a7ad565dc8d99ce2837d5542e8aee

0 commit comments

Comments
 (0)