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

[Xen-devel] [PATCH] RFC: Automatically adjust dom0 weight



At the moment, the scheduler treats dom0 the same as any other VM
for the purposes of accounting.  Since dom0 is really a critical
piece of infrastructure, and a part of the hypervisor system as a
whole, it would make more sense to try to give dom0 special rights
wrt CPU time.

This patch will cause the hypervisor to automatically adjust the
weight of dom0 such that it should be able to get either enough
cpu for each of its vcpus, or half of the cpus on the system,
whichever is less.

This patch has been in XenServer for several releases now.

I'm mostly posting to see what the interest in this kind of approach
is.  If there is interest, I'll do the work to make it more configurable.

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>

diff -r a91aa7a582fb -r 0aa2ccb56224 xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Tue Jan 31 16:34:39 2012 +0000
+++ b/xen/common/sched_credit.c Thu Feb 09 12:31:00 2012 +0000
@@ -175,6 +175,7 @@ struct csched_private {
     /* Period of master and tick in milliseconds */
     unsigned tslice_ms, tick_period_us, ticks_per_tslice;
     unsigned credits_per_tslice;
+    struct csched_dom * privdom;
 };
 
 static void csched_tick(void *_cpu);
@@ -551,6 +552,61 @@ csched_cpu_pick(const struct scheduler *
     return _csched_cpu_pick(ops, vc, 1);
 }
 
+/* Make sure that the privileged domain always has enough weight for its active
+ * vcpus to get one full pcpu each */
+static inline void __csched_adj_privdom_weight(struct csched_private *prv) {
+    struct csched_dom *sdom = prv->privdom;
+    int other_cpus, new_weight;
+#ifndef NDEBUG
+    int initial_weight;
+#endif
+
+    /* If privdom isn't being accounted for, or is the only active
+     * domain, we're done. */
+    if ( sdom == NULL
+         || list_empty(&sdom->active_sdom_elem)
+         || unlikely(prv->ncpus < 2) 
+         || prv->weight == sdom->weight * sdom->active_vcpu_count ) 
+        return;
+
+    BUG_ON(prv->weight < sdom->weight * sdom->active_vcpu_count);
+
+#ifndef NDEBUG
+    initial_weight = sdom->weight;
+#endif
+
+    /* First, subtract current privdom weight from system weight */
+    prv->weight -= sdom->weight * sdom->active_vcpu_count;
+
+    /* Calculate how many cores to leave to others. */
+    other_cpus = prv->ncpus - sdom->active_vcpu_count;
+
+    /* Don't let privdomain have more than half the available cores */
+    if ( sdom->active_vcpu_count > other_cpus )
+    {
+        /* Privdomain total weight will be equal to the weight of all others,
+         * giving it 50% of available processing power. */
+        new_weight = prv->weight / sdom->active_vcpu_count;
+    }
+    else
+    {
+        /* Calculate new privdomain weight: "other" weight / "other" pcpus */
+        new_weight = prv->weight / other_cpus;
+    }
+
+    if ( new_weight > 0 )
+        sdom->weight = new_weight;
+
+    /* Update system weight to reflect new dom0 weight */
+    prv->weight += sdom->weight * sdom->active_vcpu_count;
+
+#ifndef NDEBUG
+   if(0 && initial_weight != sdom->weight)
+        printk("%s: d%d weight %d -> %d\n",
+               __func__, sdom->dom->domain_id, initial_weight, sdom->weight);
+#endif
+}
+
 static inline void
 __csched_vcpu_acct_start(struct csched_private *prv, struct csched_vcpu *svc)
 {
@@ -572,6 +628,16 @@ __csched_vcpu_acct_start(struct csched_p
         {
             list_add(&sdom->active_sdom_elem, &prv->active_sdom);
         }
+
+        /* is_privileged isn't set when dom0 is created, so check it here. */
+        if ( unlikely(prv->privdom == NULL)
+             && IS_PRIV(sdom->dom) ) {
+            printk("%s: setting dom %d as the privileged domain\n",
+                   __func__, sdom->dom->domain_id);
+            prv->privdom = sdom;
+        }
+
+        __csched_adj_privdom_weight(prv);
     }
 
     spin_unlock_irqrestore(&prv->lock, flags);
@@ -591,11 +657,15 @@ __csched_vcpu_acct_stop_locked(struct cs
     BUG_ON( prv->weight < sdom->weight );
     sdom->active_vcpu_count--;
     list_del_init(&svc->active_vcpu_elem);
+
     prv->weight -= sdom->weight;
+
     if ( list_empty(&sdom->active_vcpu) )
     {
         list_del_init(&sdom->active_sdom_elem);
     }
+
+    __csched_adj_privdom_weight(prv);
 }
 
 static void
@@ -821,6 +891,8 @@ csched_dom_cntl(
                 prv->weight += op->u.credit.weight * sdom->active_vcpu_count;
             }
             sdom->weight = op->u.credit.weight;
+
+            __csched_adj_privdom_weight(prv);
         }
 
         if ( op->u.credit.cap != (uint16_t)~0U )
@@ -856,6 +928,7 @@ csched_alloc_domdata(const struct schedu
 static int
 csched_dom_init(const struct scheduler *ops, struct domain *dom)
 {
+    struct csched_private *prv = CSCHED_PRIV(ops);
     struct csched_dom *sdom;
 
     CSCHED_STAT_CRANK(dom_init);
@@ -869,6 +942,12 @@ csched_dom_init(const struct scheduler *
 
     dom->sched_priv = sdom;
 
+    if( IS_PRIV(dom) ) {
+        printk("%s: setting dom %d as the privileged domain\n",
+               __func__, dom->domain_id);
+        prv->privdom = sdom;
+    }
+
     return 0;
 }
 

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


 


Rackspace

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