From: Wanpeng Li <kernellwp@gmail.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Vincent Guittot <vincent.guittot@linaro.org>,
Juri Lelli <juri.lelli@redhat.com>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
Wanpeng Li <wanpengli@tencent.com>
Subject: [PATCH 04/10] sched/fair: Add penalty calculation and application logic
Date: Mon, 10 Nov 2025 11:32:25 +0800 [thread overview]
Message-ID: <20251110033232.12538-5-kernellwp@gmail.com> (raw)
In-Reply-To: <20251110033232.12538-1-kernellwp@gmail.com>
From: Wanpeng Li <wanpengli@tencent.com>
From: Wanpeng Li <wanpengli@tencent.com>
Implement core penalty calculation and application mechanisms for
yield deboost operations.
Add yield_deboost_apply_debounce() for reverse-pair debouncing to
prevent ping-pong behavior. When A→B then B→A occurs within ~600us,
downscale the penalty.
Add yield_deboost_calculate_penalty() to calculate vruntime penalty
based on the fairness gap (vruntime delta between yielding and target
tasks), scheduling granularity with safety floor for abnormal values,
and queue-size-based caps (2 tasks: 6.0×gran, 3: 4.0×, 4-6: 2.5×,
7-8: 2.0×, 9-12: 1.5×, >12: 1.0×). Apply special handling for zero
gap with refined multipliers and 10% boost weighting on positive gaps.
Add yield_deboost_apply_penalty() to apply the penalty with overflow
protection and update EEVDF fields (deadline, vlag) and min_vruntime.
The penalty is tuned to provide meaningful preference while avoiding
starvation, scales with queue depth, and prevents oscillation through
debouncing. These static functions will be integrated in the next
patch.
Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
---
kernel/sched/fair.c | 153 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 153 insertions(+)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 740c002b8f1c..4bad324f3662 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -9118,6 +9118,159 @@ static bool __maybe_unused yield_deboost_find_lca(struct sched_entity *se_y, str
return true;
}
+/*
+ * Apply debounce for reverse pair within ~600us to reduce ping-pong.
+ * Downscales penalty to max(need, gran) when the previous pair was target->source,
+ * and updates per-rq debounce tracking fields to avoid cross-CPU races.
+ */
+static u64 yield_deboost_apply_debounce(struct rq *rq, struct sched_entity *se_t,
+ u64 penalty, u64 need, u64 gran)
+{
+ u64 now_ns = rq->clock;
+ struct task_struct *p_yielding = rq->curr;
+ struct task_struct *p_target = task_of(se_t);
+
+ if (p_yielding && p_target) {
+ pid_t src_pid = p_yielding->pid;
+ pid_t dst_pid = p_target->pid;
+ pid_t last_src = rq->yield_deboost_last_src_pid;
+ pid_t last_dst = rq->yield_deboost_last_dst_pid;
+ u64 last_ns = rq->yield_deboost_last_pair_time_ns;
+
+ if (last_src == dst_pid && last_dst == src_pid &&
+ (now_ns - last_ns) <= (600ULL * NSEC_PER_USEC)) {
+ u64 alt = need;
+ if (alt < gran)
+ alt = gran;
+ if (penalty > alt)
+ penalty = alt;
+ }
+
+ /* Update per-rq tracking */
+ rq->yield_deboost_last_src_pid = src_pid;
+ rq->yield_deboost_last_dst_pid = dst_pid;
+ rq->yield_deboost_last_pair_time_ns = now_ns;
+ }
+
+ return penalty;
+}
+
+/*
+ * Calculate penalty with debounce logic for EEVDF yield deboost.
+ * Computes vruntime penalty based on fairness gap (need) plus granularity,
+ * applies queue-size-based caps to prevent excessive penalties in small queues,
+ * and implements reverse-pair debounce (~300us) to reduce ping-pong effects.
+ * Returns 0 if no penalty needed, otherwise returns clamped penalty value.
+ */
+static u64 __maybe_unused yield_deboost_calculate_penalty(struct rq *rq, struct sched_entity *se_y_lca,
+ struct sched_entity *se_t_lca, struct sched_entity *se_t,
+ int nr_queued)
+{
+ u64 gran, need, penalty, maxp;
+ u64 gran_floor;
+ u64 weighted_need, base;
+
+ gran = calc_delta_fair(sysctl_sched_base_slice, se_y_lca);
+ /* Low-bound safeguard for gran when slice is abnormally small */
+ gran_floor = calc_delta_fair(sysctl_sched_base_slice >> 1, se_y_lca);
+ if (gran < gran_floor)
+ gran = gran_floor;
+
+ need = 0;
+ if (se_t_lca->vruntime > se_y_lca->vruntime)
+ need = se_t_lca->vruntime - se_y_lca->vruntime;
+
+ /* Apply 10% boost to need when positive (weighted_need = need * 1.10) */
+ penalty = gran;
+ if (need) {
+ /* weighted_need = need + 10% */
+ weighted_need = need + need / 10;
+ /* clamp to avoid overflow when adding to gran (still capped later) */
+ if (weighted_need > U64_MAX - penalty)
+ weighted_need = U64_MAX - penalty;
+ penalty += weighted_need;
+ }
+
+ /* Apply debounce via helper to avoid ping-pong */
+ penalty = yield_deboost_apply_debounce(rq, se_t, penalty, need, gran);
+
+ /* Upper bound (cap): slightly more aggressive for mid-size queues */
+ if (nr_queued == 2)
+ maxp = gran * 6; /* Strongest push for 2-task ping-pong */
+ else if (nr_queued == 3)
+ maxp = gran * 4; /* 4.0 * gran */
+ else if (nr_queued <= 6)
+ maxp = (gran * 5) / 2; /* 2.5 * gran */
+ else if (nr_queued <= 8)
+ maxp = gran * 2; /* 2.0 * gran */
+ else if (nr_queued <= 12)
+ maxp = (gran * 3) / 2; /* 1.5 * gran */
+ else
+ maxp = gran; /* 1.0 * gran */
+
+ if (penalty < gran)
+ penalty = gran;
+ if (penalty > maxp)
+ penalty = maxp;
+
+ /* If no need, apply refined baseline push (low risk + mid risk combined). */
+ if (need == 0) {
+ /*
+ * Baseline multiplier for need==0:
+ * 2 -> 1.00 * gran
+ * 3 -> 0.9375 * gran
+ * 4–6 -> 0.625 * gran
+ * 7–8 -> 0.50 * gran
+ * 9–12 -> 0.375 * gran
+ * >12 -> 0.25 * gran
+ */
+ base = gran;
+ if (nr_queued == 3)
+ base = (gran * 15) / 16; /* 0.9375 */
+ else if (nr_queued >= 4 && nr_queued <= 6)
+ base = (gran * 5) / 8; /* 0.625 */
+ else if (nr_queued >= 7 && nr_queued <= 8)
+ base = gran / 2; /* 0.5 */
+ else if (nr_queued >= 9 && nr_queued <= 12)
+ base = (gran * 3) / 8; /* 0.375 */
+ else if (nr_queued > 12)
+ base = gran / 4; /* 0.25 */
+
+ if (penalty < base)
+ penalty = base;
+ }
+
+ return penalty;
+}
+
+/*
+ * Apply penalty and update EEVDF fields for scheduler consistency.
+ * Safely applies vruntime penalty with overflow protection, then updates
+ * EEVDF-specific fields (deadline, vlag) and cfs_rq min_vruntime to maintain
+ * scheduler state consistency. Returns true on successful application,
+ * false if penalty cannot be safely applied.
+ */
+static void __maybe_unused yield_deboost_apply_penalty(struct rq *rq, struct sched_entity *se_y_lca,
+ struct cfs_rq *cfs_rq_common, u64 penalty)
+{
+ u64 new_vruntime;
+
+ /* Overflow protection */
+ if (se_y_lca->vruntime > (U64_MAX - penalty))
+ return;
+
+ new_vruntime = se_y_lca->vruntime + penalty;
+
+ /* Validity check */
+ if (new_vruntime <= se_y_lca->vruntime)
+ return;
+
+ se_y_lca->vruntime = new_vruntime;
+ se_y_lca->deadline = se_y_lca->vruntime + calc_delta_fair(se_y_lca->slice, se_y_lca);
+ se_y_lca->vlag = avg_vruntime(cfs_rq_common) - se_y_lca->vruntime;
+ update_min_vruntime(cfs_rq_common);
+}
+
/*
* sched_yield() is very simple
*/
--
2.43.0
next prev parent reply other threads:[~2025-11-10 3:32 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-10 3:32 [PATCH 00/10] sched/kvm: Semantics-aware vCPU scheduling for oversubscribed KVM Wanpeng Li
2025-11-10 3:32 ` [PATCH 01/10] sched: Add vCPU debooster infrastructure Wanpeng Li
2025-11-10 3:32 ` [PATCH 02/10] sched/fair: Add rate-limiting and validation helpers Wanpeng Li
2025-11-12 6:40 ` K Prateek Nayak
2025-11-12 6:44 ` K Prateek Nayak
2025-11-13 13:36 ` Wanpeng Li
2025-11-13 12:00 ` Wanpeng Li
2025-11-10 3:32 ` [PATCH 03/10] sched/fair: Add cgroup LCA finder for hierarchical yield Wanpeng Li
2025-11-12 6:50 ` K Prateek Nayak
2025-11-13 8:59 ` Wanpeng Li
2025-11-10 3:32 ` Wanpeng Li [this message]
2025-11-12 7:25 ` [PATCH 04/10] sched/fair: Add penalty calculation and application logic K Prateek Nayak
2025-11-13 13:25 ` Wanpeng Li
2025-11-10 3:32 ` [PATCH 05/10] sched/fair: Wire up yield deboost in yield_to_task_fair() Wanpeng Li
2025-11-10 5:16 ` kernel test robot
2025-11-10 5:16 ` kernel test robot
2025-11-10 3:32 ` [PATCH 06/10] KVM: Fix last_boosted_vcpu index assignment bug Wanpeng Li
2025-11-21 0:35 ` Sean Christopherson
2025-11-21 0:38 ` Sean Christopherson
2025-11-21 11:46 ` Wanpeng Li
2025-11-10 3:32 ` [PATCH 07/10] KVM: x86: Add IPI tracking infrastructure Wanpeng Li
2025-11-10 3:32 ` [PATCH 08/10] KVM: x86/lapic: Integrate IPI tracking with interrupt delivery Wanpeng Li
2025-11-10 3:32 ` [PATCH 09/10] KVM: Implement IPI-aware directed yield candidate selection Wanpeng Li
2025-11-10 3:39 ` [PATCH 10/10] KVM: Relaxed boost as safety net Wanpeng Li
2025-11-10 12:02 ` [PATCH 00/10] sched/kvm: Semantics-aware vCPU scheduling for oversubscribed KVM Christian Borntraeger
2025-11-12 5:01 ` Wanpeng Li
2025-11-18 8:11 ` Christian Borntraeger
2025-11-18 14:19 ` Wanpeng Li
2025-11-11 6:28 ` K Prateek Nayak
2025-11-12 4:54 ` Wanpeng Li
2025-11-12 6:07 ` K Prateek Nayak
2025-11-13 5:37 ` Wanpeng Li
2025-11-13 4:42 ` K Prateek Nayak
2025-11-13 8:33 ` Wanpeng Li
2025-11-13 9:48 ` K Prateek Nayak
2025-11-13 13:56 ` Wanpeng Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251110033232.12538-5-kernellwp@gmail.com \
--to=kernellwp@gmail.com \
--cc=juri.lelli@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=vincent.guittot@linaro.org \
--cc=wanpengli@tencent.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox