Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rqspinlock: Drop PV and virtualization support

Changes to rqspinlock in subsequent commits will be algorithmic
modifications, which won't remain in agreement with the implementations
of paravirt spin lock and virt_spin_lock support. These future changes
include measures for terminating waiting loops in slow path after a
certain point. While using a fair lock like qspinlock directly inside
virtual machines leads to suboptimal performance under certain
conditions, we cannot use the existing virtualization support before we
make it resilient as well. Therefore, drop it for now.

Note that we need to drop qspinlock_stat.h, as it's only relevant in
case of CONFIG_PARAVIRT_SPINLOCKS=y, but we need to keep lock_events.h
in the includes, which was indirectly pulled in before.

Reviewed-by: Barret Rhoden <brho@google.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20250316040541.108729-7-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Kumar Kartikeya Dwivedi and committed by
Alexei Starovoitov
a926d099 30ff1332

+1 -90
+1 -90
kernel/bpf/rqspinlock.c
··· 11 11 * Peter Zijlstra <peterz@infradead.org> 12 12 */ 13 13 14 - #ifndef _GEN_PV_LOCK_SLOWPATH 15 - 16 14 #include <linux/smp.h> 17 15 #include <linux/bug.h> 18 16 #include <linux/cpumask.h> ··· 27 29 * Include queued spinlock definitions and statistics code 28 30 */ 29 31 #include "../locking/qspinlock.h" 30 - #include "../locking/qspinlock_stat.h" 32 + #include "../locking/lock_events.h" 31 33 32 34 /* 33 35 * The basic principle of a queue-based spinlock can best be understood ··· 73 75 * contexts: task, softirq, hardirq, nmi. 74 76 * 75 77 * Exactly fits one 64-byte cacheline on a 64-bit architecture. 76 - * 77 - * PV doubles the storage and uses the second cacheline for PV state. 78 78 */ 79 79 static DEFINE_PER_CPU_ALIGNED(struct qnode, rqnodes[_Q_MAX_NODES]); 80 - 81 - /* 82 - * Generate the native code for resilient_queued_spin_unlock_slowpath(); provide NOPs 83 - * for all the PV callbacks. 84 - */ 85 - 86 - static __always_inline void __pv_init_node(struct mcs_spinlock *node) { } 87 - static __always_inline void __pv_wait_node(struct mcs_spinlock *node, 88 - struct mcs_spinlock *prev) { } 89 - static __always_inline void __pv_kick_node(struct qspinlock *lock, 90 - struct mcs_spinlock *node) { } 91 - static __always_inline u32 __pv_wait_head_or_lock(struct qspinlock *lock, 92 - struct mcs_spinlock *node) 93 - { return 0; } 94 - 95 - #define pv_enabled() false 96 - 97 - #define pv_init_node __pv_init_node 98 - #define pv_wait_node __pv_wait_node 99 - #define pv_kick_node __pv_kick_node 100 - #define pv_wait_head_or_lock __pv_wait_head_or_lock 101 - 102 - #ifdef CONFIG_PARAVIRT_SPINLOCKS 103 - #define resilient_queued_spin_lock_slowpath native_resilient_queued_spin_lock_slowpath 104 - #endif 105 - 106 - #endif /* _GEN_PV_LOCK_SLOWPATH */ 107 80 108 81 /** 109 82 * resilient_queued_spin_lock_slowpath - acquire the queued spinlock ··· 104 135 int idx; 105 136 106 137 BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS)); 107 - 108 - if (pv_enabled()) 109 - goto pv_queue; 110 - 111 - if (virt_spin_lock(lock)) 112 - return; 113 138 114 139 /* 115 140 * Wait for in-progress pending->locked hand-overs with a bounded ··· 175 212 */ 176 213 queue: 177 214 lockevent_inc(lock_slowpath); 178 - pv_queue: 179 215 node = this_cpu_ptr(&rqnodes[0].mcs); 180 216 idx = node->count++; 181 217 tail = encode_tail(smp_processor_id(), idx); ··· 213 251 214 252 node->locked = 0; 215 253 node->next = NULL; 216 - pv_init_node(node); 217 254 218 255 /* 219 256 * We touched a (possibly) cold cacheline in the per-cpu queue node; ··· 249 288 /* Link @node into the waitqueue. */ 250 289 WRITE_ONCE(prev->next, node); 251 290 252 - pv_wait_node(node, prev); 253 291 arch_mcs_spin_lock_contended(&node->locked); 254 292 255 293 /* ··· 272 312 * store-release that clears the locked bit and create lock 273 313 * sequentiality; this is because the set_locked() function below 274 314 * does not imply a full barrier. 275 - * 276 - * The PV pv_wait_head_or_lock function, if active, will acquire 277 - * the lock and return a non-zero value. So we have to skip the 278 - * atomic_cond_read_acquire() call. As the next PV queue head hasn't 279 - * been designated yet, there is no way for the locked value to become 280 - * _Q_SLOW_VAL. So both the set_locked() and the 281 - * atomic_cmpxchg_relaxed() calls will be safe. 282 - * 283 - * If PV isn't active, 0 will be returned instead. 284 - * 285 315 */ 286 - if ((val = pv_wait_head_or_lock(lock, node))) 287 - goto locked; 288 - 289 316 val = atomic_cond_read_acquire(&lock->val, !(VAL & _Q_LOCKED_PENDING_MASK)); 290 317 291 - locked: 292 318 /* 293 319 * claim the lock: 294 320 * ··· 287 341 */ 288 342 289 343 /* 290 - * In the PV case we might already have _Q_LOCKED_VAL set, because 291 - * of lock stealing; therefore we must also allow: 292 - * 293 - * n,0,1 -> 0,0,1 294 - * 295 344 * Note: at this point: (val & _Q_PENDING_MASK) == 0, because of the 296 345 * above wait condition, therefore any concurrent setting of 297 346 * PENDING will make the uncontended transition fail. ··· 310 369 next = smp_cond_load_relaxed(&node->next, (VAL)); 311 370 312 371 arch_mcs_spin_unlock_contended(&next->locked); 313 - pv_kick_node(lock, next); 314 372 315 373 release: 316 374 trace_contention_end(lock, 0); ··· 320 380 __this_cpu_dec(rqnodes[0].mcs.count); 321 381 } 322 382 EXPORT_SYMBOL_GPL(resilient_queued_spin_lock_slowpath); 323 - 324 - /* 325 - * Generate the paravirt code for resilient_queued_spin_unlock_slowpath(). 326 - */ 327 - #if !defined(_GEN_PV_LOCK_SLOWPATH) && defined(CONFIG_PARAVIRT_SPINLOCKS) 328 - #define _GEN_PV_LOCK_SLOWPATH 329 - 330 - #undef pv_enabled 331 - #define pv_enabled() true 332 - 333 - #undef pv_init_node 334 - #undef pv_wait_node 335 - #undef pv_kick_node 336 - #undef pv_wait_head_or_lock 337 - 338 - #undef resilient_queued_spin_lock_slowpath 339 - #define resilient_queued_spin_lock_slowpath __pv_resilient_queued_spin_lock_slowpath 340 - 341 - #include "../locking/qspinlock_paravirt.h" 342 - #include "rqspinlock.c" 343 - 344 - bool nopvspin; 345 - static __init int parse_nopvspin(char *arg) 346 - { 347 - nopvspin = true; 348 - return 0; 349 - } 350 - early_param("nopvspin", parse_nopvspin); 351 - #endif