Skip to content

Commit 48fc82c

Browse files
committed
Merge tag 'locking-core-2024-05-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking updates from Ingo Molnar: - Over a dozen code generation micro-optimizations for the atomic and spinlock code - Add more __ro_after_init attributes - Robustify the lockdevent_*() macros * tag 'locking-core-2024-05-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking/pvqspinlock/x86: Use _Q_LOCKED_VAL in PV_UNLOCK_ASM macro locking/qspinlock/x86: Micro-optimize virt_spin_lock() locking/atomic/x86: Merge __arch{,_try}_cmpxchg64_emu_local() with __arch{,_try}_cmpxchg64_emu() locking/atomic/x86: Introduce arch_try_cmpxchg64_local() locking/pvqspinlock/x86: Remove redundant CMP after CMPXCHG in __raw_callee_save___pv_queued_spin_unlock() locking/pvqspinlock: Use try_cmpxchg() in qspinlock_paravirt.h locking/pvqspinlock: Use try_cmpxchg_acquire() in trylock_clear_pending() locking/qspinlock: Use atomic_try_cmpxchg_relaxed() in xchg_tail() locking/atomic/x86: Define arch_atomic_sub() family using arch_atomic_add() functions locking/atomic/x86: Rewrite x86_32 arch_atomic64_{,fetch}_{and,or,xor}() functions locking/atomic/x86: Introduce arch_atomic64_read_nonatomic() to x86_32 locking/atomic/x86: Introduce arch_atomic64_try_cmpxchg() to x86_32 locking/atomic/x86: Introduce arch_try_cmpxchg64() for !CONFIG_X86_CMPXCHG64 locking/atomic/x86: Modernize x86_32 arch_{,try_}_cmpxchg64{,_local}() locking/atomic/x86: Correct the definition of __arch_try_cmpxchg128() x86/tsc: Make __use_tsc __ro_after_init x86/kvm: Make kvm_async_pf_enabled __ro_after_init context_tracking: Make context_tracking_key __ro_after_init jump_label,module: Don't alloc static_key_mod for __ro_after_init keys locking/qspinlock: Always evaluate lockevent* non-event parameter once
2 parents a7c840b + 532453e commit 48fc82c

File tree

17 files changed

+295
-175
lines changed

17 files changed

+295
-175
lines changed

arch/x86/include/asm/atomic.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,15 @@ static __always_inline int arch_atomic_add_return(int i, atomic_t *v)
8686
}
8787
#define arch_atomic_add_return arch_atomic_add_return
8888

89-
static __always_inline int arch_atomic_sub_return(int i, atomic_t *v)
90-
{
91-
return arch_atomic_add_return(-i, v);
92-
}
93-
#define arch_atomic_sub_return arch_atomic_sub_return
89+
#define arch_atomic_sub_return(i, v) arch_atomic_add_return(-(i), v)
9490

9591
static __always_inline int arch_atomic_fetch_add(int i, atomic_t *v)
9692
{
9793
return xadd(&v->counter, i);
9894
}
9995
#define arch_atomic_fetch_add arch_atomic_fetch_add
10096

101-
static __always_inline int arch_atomic_fetch_sub(int i, atomic_t *v)
102-
{
103-
return xadd(&v->counter, -i);
104-
}
105-
#define arch_atomic_fetch_sub arch_atomic_fetch_sub
97+
#define arch_atomic_fetch_sub(i, v) arch_atomic_fetch_add(-(i), v)
10698

10799
static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new)
108100
{

arch/x86/include/asm/atomic64_32.h

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,32 @@ typedef struct {
1414

1515
#define ATOMIC64_INIT(val) { (val) }
1616

17+
/*
18+
* Read an atomic64_t non-atomically.
19+
*
20+
* This is intended to be used in cases where a subsequent atomic operation
21+
* will handle the torn value, and can be used to prime the first iteration
22+
* of unconditional try_cmpxchg() loops, e.g.:
23+
*
24+
* s64 val = arch_atomic64_read_nonatomic(v);
25+
* do { } while (!arch_atomic64_try_cmpxchg(v, &val, val OP i);
26+
*
27+
* This is NOT safe to use where the value is not always checked by a
28+
* subsequent atomic operation, such as in conditional try_cmpxchg() loops
29+
* that can break before the atomic operation, e.g.:
30+
*
31+
* s64 val = arch_atomic64_read_nonatomic(v);
32+
* do {
33+
* if (condition(val))
34+
* break;
35+
* } while (!arch_atomic64_try_cmpxchg(v, &val, val OP i);
36+
*/
37+
static __always_inline s64 arch_atomic64_read_nonatomic(const atomic64_t *v)
38+
{
39+
/* See comment in arch_atomic_read(). */
40+
return __READ_ONCE(v->counter);
41+
}
42+
1743
#define __ATOMIC64_DECL(sym) void atomic64_##sym(atomic64_t *, ...)
1844
#ifndef ATOMIC64_EXPORT
1945
#define ATOMIC64_DECL_ONE __ATOMIC64_DECL
@@ -61,12 +87,18 @@ ATOMIC64_DECL(add_unless);
6187
#undef __ATOMIC64_DECL
6288
#undef ATOMIC64_EXPORT
6389

64-
static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 o, s64 n)
90+
static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)
6591
{
66-
return arch_cmpxchg64(&v->counter, o, n);
92+
return arch_cmpxchg64(&v->counter, old, new);
6793
}
6894
#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg
6995

96+
static __always_inline bool arch_atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)
97+
{
98+
return arch_try_cmpxchg64(&v->counter, old, new);
99+
}
100+
#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchg
101+
70102
static __always_inline s64 arch_atomic64_xchg(atomic64_t *v, s64 n)
71103
{
72104
s64 o;
@@ -195,69 +227,62 @@ static __always_inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
195227

196228
static __always_inline void arch_atomic64_and(s64 i, atomic64_t *v)
197229
{
198-
s64 old, c = 0;
230+
s64 val = arch_atomic64_read_nonatomic(v);
199231

200-
while ((old = arch_atomic64_cmpxchg(v, c, c & i)) != c)
201-
c = old;
232+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val & i));
202233
}
203234

204235
static __always_inline s64 arch_atomic64_fetch_and(s64 i, atomic64_t *v)
205236
{
206-
s64 old, c = 0;
237+
s64 val = arch_atomic64_read_nonatomic(v);
207238

208-
while ((old = arch_atomic64_cmpxchg(v, c, c & i)) != c)
209-
c = old;
239+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val & i));
210240

211-
return old;
241+
return val;
212242
}
213243
#define arch_atomic64_fetch_and arch_atomic64_fetch_and
214244

215245
static __always_inline void arch_atomic64_or(s64 i, atomic64_t *v)
216246
{
217-
s64 old, c = 0;
247+
s64 val = arch_atomic64_read_nonatomic(v);
218248

219-
while ((old = arch_atomic64_cmpxchg(v, c, c | i)) != c)
220-
c = old;
249+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val | i));
221250
}
222251

223252
static __always_inline s64 arch_atomic64_fetch_or(s64 i, atomic64_t *v)
224253
{
225-
s64 old, c = 0;
254+
s64 val = arch_atomic64_read_nonatomic(v);
226255

227-
while ((old = arch_atomic64_cmpxchg(v, c, c | i)) != c)
228-
c = old;
256+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val | i));
229257

230-
return old;
258+
return val;
231259
}
232260
#define arch_atomic64_fetch_or arch_atomic64_fetch_or
233261

234262
static __always_inline void arch_atomic64_xor(s64 i, atomic64_t *v)
235263
{
236-
s64 old, c = 0;
264+
s64 val = arch_atomic64_read_nonatomic(v);
237265

238-
while ((old = arch_atomic64_cmpxchg(v, c, c ^ i)) != c)
239-
c = old;
266+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val ^ i));
240267
}
241268

242269
static __always_inline s64 arch_atomic64_fetch_xor(s64 i, atomic64_t *v)
243270
{
244-
s64 old, c = 0;
271+
s64 val = arch_atomic64_read_nonatomic(v);
245272

246-
while ((old = arch_atomic64_cmpxchg(v, c, c ^ i)) != c)
247-
c = old;
273+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val ^ i));
248274

249-
return old;
275+
return val;
250276
}
251277
#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor
252278

253279
static __always_inline s64 arch_atomic64_fetch_add(s64 i, atomic64_t *v)
254280
{
255-
s64 old, c = 0;
281+
s64 val = arch_atomic64_read_nonatomic(v);
256282

257-
while ((old = arch_atomic64_cmpxchg(v, c, c + i)) != c)
258-
c = old;
283+
do { } while (!arch_atomic64_try_cmpxchg(v, &val, val + i));
259284

260-
return old;
285+
return val;
261286
}
262287
#define arch_atomic64_fetch_add arch_atomic64_fetch_add
263288

arch/x86/include/asm/atomic64_64.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,15 @@ static __always_inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v)
8080
}
8181
#define arch_atomic64_add_return arch_atomic64_add_return
8282

83-
static __always_inline s64 arch_atomic64_sub_return(s64 i, atomic64_t *v)
84-
{
85-
return arch_atomic64_add_return(-i, v);
86-
}
87-
#define arch_atomic64_sub_return arch_atomic64_sub_return
83+
#define arch_atomic64_sub_return(i, v) arch_atomic64_add_return(-(i), v)
8884

8985
static __always_inline s64 arch_atomic64_fetch_add(s64 i, atomic64_t *v)
9086
{
9187
return xadd(&v->counter, i);
9288
}
9389
#define arch_atomic64_fetch_add arch_atomic64_fetch_add
9490

95-
static __always_inline s64 arch_atomic64_fetch_sub(s64 i, atomic64_t *v)
96-
{
97-
return xadd(&v->counter, -i);
98-
}
99-
#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub
91+
#define arch_atomic64_fetch_sub(i, v) arch_atomic64_fetch_add(-(i), v)
10092

10193
static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)
10294
{

0 commit comments

Comments
 (0)