[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xen/credit2: factor in previous active unit's credit in csched2_runtime()


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Sat, 21 Jun 2025 23:14:11 +0900
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=J9+f5/bj/zZHwsLt9rViwjBEk07emcS5iCST2DIr8n0=; b=yDJinfrrSkY0YHPlY3cQznJW4uhTNJZ8h4q/MQ7zuQ3BnqaqP9YanpyjGqljDleCB7I0jYs68vQQyMJC8mkpdE1ZxQio5+9COUyY4P+R79wFF+Wx7PbpuMVzOKdiZlc8PxVVAUEs/TvBpmSOuiYyy0K5ADY3I5bk8Zo4iQtlx3yPiBwKWPFp3nAz1ko+gKhR9yjOUDj8M4rQnadUnbkWxTLNDhHtKdcsjSMEcYUY2Y0ybdUNprRKY9Y+W+tBbUSeYBdwhLFaY6Yw2lpiJkFxR+4htd3Xgs+6cQsD+c0YvikS40Xs545WUeHb3l16eMEEQPWXpIjy2qWOaNk25RsPEA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=COW1xDwgiRrATilH8LwSqebecGB3N6IJk8Z/9KTBDV3l1tI+l7nq2s7WEkD2ESzqyQf5DlzmOgf8HO+6+ARGQyla+bAZFdzRi9Md3bT/CSJPc3GuioX4eLOGrdC4bU5XKkFyJfK1iHfaKaCAWhRIvZUgSo/B4obkqx3rj4ADcO3R9jcyj3l2t7x/fxI4TxN5sEtC9KJhUjbIgMVPzclphoWyPRxsZ+qCF3ssm7TVXw2g0YWLXDQDDNa1DBySCwBbZcD49zgyz8plSnjOcc57weU+IHk4b8TlFgSm4lTEeN1mxZc5tqAlcj5xiOwJE8FKBGmxtECw0nYn3k3OHoJmag==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp;
  • Cc: dfaggioli@xxxxxxxx, jgross@xxxxxxxx, gwd@xxxxxxxxxxxxxx
  • Delivery-date: Sat, 21 Jun 2025 14:30:27 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

When a running unit is about to be scheduled out due to a competing unit
with the highest remaining credit, the residual credit of the previous
unit is currently ignored in csched2_runtime() because it hasn't yet
been reinserted into the runqueue.

As a result, two equally weighted, busy units can often each be granted
almost the maximum possible runtime (i.e. consuming CSCHED2_CREDIT_INIT
in one shot) when only those two are active. In broad strokes two units
switch back and forth every 10ms (CSCHED2_MAX_TIMER). In contrast, when
more than two busy units are competing, such coarse runtime allocations
are rarely seen, since at least one active unit remains in the runqueue.

To ensure consistent behavior, have csched2_runtime() take into account
the previous unit's latest credit when it still can/wants to run.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/common/sched/credit2.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/xen/common/sched/credit2.c b/xen/common/sched/credit2.c
index 0a83f237259f..0b74fa3c5d0b 100644
--- a/xen/common/sched/credit2.c
+++ b/xen/common/sched/credit2.c
@@ -3278,13 +3278,14 @@ csched2_unit_remove(const struct scheduler *ops, struct 
sched_unit *unit)
 /* How long should we let this unit run for? */
 static s_time_t
 csched2_runtime(const struct scheduler *ops, int cpu,
-                struct csched2_unit *snext, s_time_t now)
+                struct csched2_unit *snext, s_time_t now, int inflight_credit)
 {
     s_time_t time, min_time;
     int rt_credit; /* Proposed runtime measured in credits */
     struct csched2_runqueue_data *rqd = c2rqd(cpu);
     struct list_head *runq = &rqd->runq;
     const struct csched2_private *prv = csched2_priv(ops);
+    int swait_credit = 0;
 
     /*
      * If we're idle, just stay so. Others (or external events)
@@ -3320,17 +3321,21 @@ csched2_runtime(const struct scheduler *ops, int cpu,
     /*
      * 2) If there's someone waiting whose credit is positive,
      *    run until your credit ~= his.
+     *    Note that this someone might be the one who was just
+     *    running and is about to be placed back on the runqueue.
      */
     if ( ! list_empty(runq) )
     {
         struct csched2_unit *swait = runq_elem(runq->next);
 
-        if ( ! is_idle_unit(swait->unit)
-             && swait->credit > 0 )
-        {
-            rt_credit = snext->credit - swait->credit;
-        }
+        if ( !is_idle_unit(swait->unit) && swait->credit > 0 )
+            swait_credit = swait->credit;
     }
+    if ( swait_credit < inflight_credit )
+        swait_credit = inflight_credit;
+
+    if ( swait_credit > 0 )
+        rt_credit = snext->credit - swait_credit;
 
     /*
      * The next guy on the runqueue may actually have a higher credit,
@@ -3582,6 +3587,7 @@ static void cf_check csched2_schedule(
     struct csched2_runqueue_data *rqd;
     struct csched2_unit * const scurr = csched2_unit(currunit);
     struct csched2_unit *snext = NULL;
+    int inflight_credit = 0;
     bool tickled;
     bool migrated = false;
 
@@ -3716,6 +3722,13 @@ static void cf_check csched2_schedule(
             balance_load(ops, sched_cpu, now);
         }
 
+        /*
+         * This must occur after the potential credit reset above,
+         * otherwise it would capture a negative credit.
+         */
+        if ( test_bit(__CSFLAG_delayed_runq_add, &scurr->flags) )
+            inflight_credit = scurr->credit;
+
         snext->start_time = now;
         snext->tickled_cpu = -1;
 
@@ -3756,7 +3769,8 @@ static void cf_check csched2_schedule(
     /*
      * Return task to run next...
      */
-    currunit->next_time = csched2_runtime(ops, sched_cpu, snext, now);
+    currunit->next_time = csched2_runtime(ops, sched_cpu, snext, now,
+                                          inflight_credit);
     currunit->next_task = snext->unit;
     snext->unit->migrated = migrated;
 
-- 
2.48.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.