Skip to content

Commit c793a62

Browse files
sean-jcPeter Zijlstra
authored andcommitted
sched/core: Drop spinlocks on contention iff kernel is preemptible
Use preempt_model_preemptible() to detect a preemptible kernel when deciding whether or not to reschedule in order to drop a contended spinlock or rwlock. Because PREEMPT_DYNAMIC selects PREEMPTION, kernels built with PREEMPT_DYNAMIC=y will yield contended locks even if the live preemption model is "none" or "voluntary". In short, make kernels with dynamically selected models behave the same as kernels with statically selected models. Somewhat counter-intuitively, NOT yielding a lock can provide better latency for the relevant tasks/processes. E.g. KVM x86's mmu_lock, a rwlock, is often contended between an invalidation event (takes mmu_lock for write) and a vCPU servicing a guest page fault (takes mmu_lock for read). For _some_ setups, letting the invalidation task complete even if there is mmu_lock contention provides lower latency for *all* tasks, i.e. the invalidation completes sooner *and* the vCPU services the guest page fault sooner. But even KVM's mmu_lock behavior isn't uniform, e.g. the "best" behavior can vary depending on the host VMM, the guest workload, the number of vCPUs, the number of pCPUs in the host, why there is lock contention, etc. In other words, simply deleting the CONFIG_PREEMPTION guard (or doing the opposite and removing contention yielding entirely) needs to come with a big pile of data proving that changing the status quo is a net positive. Opportunistically document this side effect of preempt=full, as yielding contended spinlocks can have significant, user-visible impact. Fixes: c597bfd ("sched: Provide Kconfig support for default dynamic preempt mode") Signed-off-by: Sean Christopherson <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Ankur Arora <[email protected]> Reviewed-by: Chen Yu <[email protected]> Link: https://lore.kernel.org/kvm/[email protected]
1 parent f0dc887 commit c793a62

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4752,7 +4752,9 @@
47524752
none - Limited to cond_resched() calls
47534753
voluntary - Limited to cond_resched() and might_sleep() calls
47544754
full - Any section that isn't explicitly preempt disabled
4755-
can be preempted anytime.
4755+
can be preempted anytime. Tasks will also yield
4756+
contended spinlocks (if the critical section isn't
4757+
explicitly preempt disabled beyond the lock itself).
47564758

47574759
print-fatal-signals=
47584760
[KNL] debug: print fatal signals

include/linux/spinlock.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,10 @@ static __always_inline int spin_is_contended(spinlock_t *lock)
462462
*/
463463
static inline int spin_needbreak(spinlock_t *lock)
464464
{
465-
#ifdef CONFIG_PREEMPTION
465+
if (!preempt_model_preemptible())
466+
return 0;
467+
466468
return spin_is_contended(lock);
467-
#else
468-
return 0;
469-
#endif
470469
}
471470

472471
/*
@@ -479,11 +478,10 @@ static inline int spin_needbreak(spinlock_t *lock)
479478
*/
480479
static inline int rwlock_needbreak(rwlock_t *lock)
481480
{
482-
#ifdef CONFIG_PREEMPTION
481+
if (!preempt_model_preemptible())
482+
return 0;
483+
483484
return rwlock_is_contended(lock);
484-
#else
485-
return 0;
486-
#endif
487485
}
488486

489487
/*

0 commit comments

Comments
 (0)