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

[Xen-changelog] [xen-unstable] [XEN] Improve scheduler cap mechanism



# HG changeset patch
# User Emmanuel Ackaouy <ack@xxxxxxxxxxxxx>
# Node ID 360eb996fa38319867a74bf581c734a80bf6839d
# Parent  c79f9d7882046074d30f58f769aadce5950357d9
[XEN] Improve scheduler cap mechanism
Somewhat unbastardize the scheduler cap mechanism. We now cleanly
pause and unpause running VCPUs of capped out domains instead of
using sub-idle priorities. This also improves the precision of
caps a bit.
Signed-off-by: Emmanuel Ackaouy <ack@xxxxxxxxxxxxx>
---
 xen/common/domain.c       |   19 +++++++++---
 xen/common/sched_credit.c |   71 +++++++++++++++++++++++++++++++++-------------
 xen/include/xen/sched.h   |    1 
 3 files changed, 67 insertions(+), 24 deletions(-)

diff -r c79f9d788204 -r 360eb996fa38 xen/common/domain.c
--- a/xen/common/domain.c       Wed Dec 13 10:20:20 2006 -0500
+++ b/xen/common/domain.c       Wed Dec 13 16:13:26 2006 +0000
@@ -350,16 +350,25 @@ void domain_destroy(struct domain *d)
     send_guest_global_virq(dom0, VIRQ_DOM_EXC);
 }
 
-void vcpu_pause(struct vcpu *v)
-{
-    ASSERT(v != current);
-
+static void vcpu_pause_setup(struct vcpu *v)
+{
     spin_lock(&v->pause_lock);
     if ( v->pause_count++ == 0 )
         set_bit(_VCPUF_paused, &v->vcpu_flags);
     spin_unlock(&v->pause_lock);
-
+}
+
+void vcpu_pause(struct vcpu *v)
+{
+    ASSERT(v != current);
+    vcpu_pause_setup(v);
     vcpu_sleep_sync(v);
+}
+
+void vcpu_pause_nosync(struct vcpu *v)
+{
+    vcpu_pause_setup(v);
+    vcpu_sleep_nosync(v);
 }
 
 void vcpu_unpause(struct vcpu *v)
diff -r c79f9d788204 -r 360eb996fa38 xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Wed Dec 13 10:20:20 2006 -0500
+++ b/xen/common/sched_credit.c Wed Dec 13 16:13:26 2006 +0000
@@ -56,7 +56,12 @@
 #define CSCHED_PRI_TS_UNDER     -1      /* time-share w/ credits */
 #define CSCHED_PRI_TS_OVER      -2      /* time-share w/o credits */
 #define CSCHED_PRI_IDLE         -64     /* idle */
-#define CSCHED_PRI_TS_PARKED    -65     /* time-share w/ capped credits */
+
+
+/*
+ * Flags
+ */
+#define CSCHED_FLAG_VCPU_PARKED 0x0001  /* VCPU over capped credits */
 
 
 /*
@@ -100,6 +105,8 @@
     _MACRO(vcpu_wake_onrunq)                \
     _MACRO(vcpu_wake_runnable)              \
     _MACRO(vcpu_wake_not_runnable)          \
+    _MACRO(vcpu_park)                       \
+    _MACRO(vcpu_unpark)                     \
     _MACRO(tickle_local_idler)              \
     _MACRO(tickle_local_over)               \
     _MACRO(tickle_local_under)              \
@@ -190,6 +197,7 @@ struct csched_vcpu {
     struct csched_dom *sdom;
     struct vcpu *vcpu;
     atomic_t credit;
+    uint16_t flags;
     int16_t pri;
 #ifdef CSCHED_STATS
     struct {
@@ -579,12 +587,11 @@ csched_vcpu_init(struct vcpu *vc)
     svc->sdom = sdom;
     svc->vcpu = vc;
     atomic_set(&svc->credit, 0);
+    svc->flags = 0U;
     svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
     CSCHED_VCPU_STATS_RESET(svc);
     vc->sched_priv = svc;
 
-    CSCHED_VCPU_CHECK(vc);
-
     /* Allocate per-PCPU info */
     if ( unlikely(!CSCHED_PCPU(vc->processor)) )
     {
@@ -593,7 +600,6 @@ csched_vcpu_init(struct vcpu *vc)
     }
 
     CSCHED_VCPU_CHECK(vc);
-
     return 0;
 }
 
@@ -673,9 +679,16 @@ csched_vcpu_wake(struct vcpu *vc)
      * This allows wake-to-run latency sensitive VCPUs to preempt
      * more CPU resource intensive VCPUs without impacting overall 
      * system fairness.
-     */
-    if ( svc->pri == CSCHED_PRI_TS_UNDER )
+     *
+     * The one exception is for VCPUs of capped domains unpausing
+     * after earning credits they had overspent. We don't boost
+     * those.
+     */
+    if ( svc->pri == CSCHED_PRI_TS_UNDER &&
+         !(svc->flags & CSCHED_FLAG_VCPU_PARKED) )
+    {
         svc->pri = CSCHED_PRI_TS_BOOST;
+    }
 
     /* Put the VCPU on the runq and tickle CPUs */
     __runq_insert(cpu, svc);
@@ -749,11 +762,8 @@ static void
 static void
 csched_dom_destroy(struct domain *dom)
 {
-    struct csched_dom * const sdom = CSCHED_DOM(dom);
-
     CSCHED_STAT_CRANK(dom_destroy);
-
-    xfree(sdom);
+    xfree(CSCHED_DOM(dom));
 }
 
 /*
@@ -942,11 +952,19 @@ csched_acct(void)
              */
             if ( credit < 0 )
             {
-                if ( sdom->cap != 0U && credit < -credit_cap )
-                    svc->pri = CSCHED_PRI_TS_PARKED;
-                else
-                    svc->pri = CSCHED_PRI_TS_OVER;
-
+                svc->pri = CSCHED_PRI_TS_OVER;
+
+                /* Park running VCPUs of capped-out domains */
+                if ( sdom->cap != 0U &&
+                     credit < -credit_cap &&
+                     !(svc->flags & CSCHED_FLAG_VCPU_PARKED) )
+                {
+                    CSCHED_STAT_CRANK(vcpu_park);
+                    vcpu_pause_nosync(svc->vcpu);
+                    svc->flags |= CSCHED_FLAG_VCPU_PARKED;
+                }
+
+                /* Lower bound on credits */
                 if ( credit < -CSCHED_CREDITS_PER_TSLICE )
                 {
                     CSCHED_STAT_CRANK(acct_min_credit);
@@ -958,6 +976,20 @@ csched_acct(void)
             {
                 svc->pri = CSCHED_PRI_TS_UNDER;
 
+                /* Unpark any capped domains whose credits go positive */
+                if ( svc->flags & CSCHED_FLAG_VCPU_PARKED)
+                {
+                    /*
+                     * It's important to unset the flag AFTER the unpause()
+                     * call to make sure the VCPU's priority is not boosted
+                     * if it is woken up here.
+                     */
+                    CSCHED_STAT_CRANK(vcpu_unpark);
+                    vcpu_unpause(svc->vcpu);
+                    svc->flags &= ~CSCHED_FLAG_VCPU_PARKED;
+                }
+
+                /* Upper bound on credits means VCPU stops earning */
                 if ( credit > CSCHED_CREDITS_PER_TSLICE )
                 {
                     __csched_vcpu_acct_stop_locked(svc);
@@ -1031,10 +1063,10 @@ csched_runq_steal(int peer_cpu, int cpu,
             speer = __runq_elem(iter);
 
             /*
-             * If next available VCPU here is not of higher priority
-             * than ours, this PCPU is useless to us.
+             * If next available VCPU here is not of strictly higher
+             * priority than ours, this PCPU is useless to us.
              */
-            if ( speer->pri <= CSCHED_PRI_IDLE || speer->pri <= pri )
+            if ( speer->pri <= pri )
                 break;
 
             /* Is this VCPU is runnable on our PCPU? */
@@ -1181,10 +1213,11 @@ csched_dump_vcpu(struct csched_vcpu *svc
 {
     struct csched_dom * const sdom = svc->sdom;
 
-    printk("[%i.%i] pri=%i cpu=%i",
+    printk("[%i.%i] pri=%i flags=%x cpu=%i",
             svc->vcpu->domain->domain_id,
             svc->vcpu->vcpu_id,
             svc->pri,
+            svc->flags,
             svc->vcpu->processor);
 
     if ( sdom )
diff -r c79f9d788204 -r 360eb996fa38 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Dec 13 10:20:20 2006 -0500
+++ b/xen/include/xen/sched.h   Wed Dec 13 16:13:26 2006 +0000
@@ -437,6 +437,7 @@ static inline int vcpu_runnable(struct v
 }
 
 void vcpu_pause(struct vcpu *v);
+void vcpu_pause_nosync(struct vcpu *v);
 void domain_pause(struct domain *d);
 void vcpu_unpause(struct vcpu *v);
 void domain_unpause(struct domain *d);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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