Skip to contentSkip to conversation

scheduler: credit scheduler for client virtualization

RFC PATCH In review NISHIGUCHI Naoki 4 participants 15 messages Dec 3, 2008 – Jan 22, 2009 3 messages not in the archive Arm/actions semi architecture

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 scheduler: credit scheduler for client virtualization

Hi all,

This patch is what I spoke about improvement of credit scheduler in XenSummit Tokyo.
My presentation is now available at
http://www.xen.org/xensummit/xensummit_fall_2008.html.

In case of using Xen hypervisor on the client virtualization environment, especially enabling vtd and passing through some devices to a domain, I think that it is neccessary to reduce time for the vcpu in the domain to wait its turn on a run queue.

My approach is to keep the vcpu's priority in BOOST and to switch the vcpu to another vcpu at short intervals when there are some vcpus in BOOST priority .

Changes to credit scheduler are the following:

- Improve the precision of credit
There are three changes. First change is to subtract credit for
consumed cpu time accurately. Second change is to preserve the value of credit when credit of the vcpu is over upper bound value(currently 300). Third change is to shorten cpu time per one credit(experimentally 30000 credits to 30ms).

- Shorten allocated time to a vcpu in BOOST priority Allocated time is experimentally changed to 2ms from 30ms.

- Balance credits of each vcpu of a domain

- Introduce boost credit
Boost credit is new credit to keep a vcpu's priority in BOOST. When a
value of boost credit is 1 or more, priority of the vcpu is set to BOOST. Moreover, to avoid the fall of priority for abrupt cpu consumption of the vcpu, upper bound value of boost credit can be set.

How to use:

On this patch, I added bcredit scheduler(named boost credit scheduler) as third scheduler. In order to use bcredit scheduler, add "sched=bcredit" option to xen.gz in grub.conf.

Then in order to boost a domain, you should enable boost credit of the domain. There is two method.

1. Using xm command, set upper bound value of boost credit of the domain. It is specified by not the value of credit but the millisecond. It is named max boost period.
e.g. domain:0, max boost period:100ms
xm sched-bcredit -d 0 -m 100

2. Using xm command, set upper bound value of boost credit of the domain and set boost ratio. Boost ratio is ratio to one CPU that is used for distributing boost credit. Boost credit corresponding to boost ratio is distributed in place of credit. An influence of other domains is not received because of ratio to one CPU.
e.g. domain:0, max boost period:500ms, boost ratio:80(80% to one CPU)

    xm sched-bcredit -d 0 -m 500 -r 80

Please review this patch.
Any comments are appreciated.

Best regards,
Naoki Nishiguchi

tools/libxc/xc_csched.c +38 -0
diff -r a00eb6595d3c tools/libxc/xc_csched.c
@@ -48,3 +48,41 @@ xc_sched_credit_domain_get(
 
     return err;
 }
+
+int
+xc_sched_bcredit_domain_set(
+    int xc_handle,
+    uint32_t domid,
+    struct xen_domctl_sched_bcredit *sdom)
+{
+    DECLARE_DOMCTL;
+
+    domctl.cmd = XEN_DOMCTL_scheduler_op;
+    domctl.domain = (domid_t) domid;
+    domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_BCREDIT;
+    domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_putinfo;
+    domctl.u.scheduler_op.u.bcredit = *sdom;
+
+    return do_domctl(xc_handle, &domctl);
+}
+
+int
+xc_sched_bcredit_domain_get(
+    int xc_handle,
+    uint32_t domid,
+    struct xen_domctl_sched_bcredit *sdom)
+{
+    DECLARE_DOMCTL;
+    int err;
+
+    domctl.cmd = XEN_DOMCTL_scheduler_op;
+    domctl.domain = (domid_t) domid;
+    domctl.u.scheduler_op.sched_id = XEN_SCHEDULER_BCREDIT;
+    domctl.u.scheduler_op.cmd = XEN_DOMCTL_SCHEDOP_getinfo;
+
+    err = do_domctl(xc_handle, &domctl);
+    if ( err == 0 )
+        *sdom = domctl.u.scheduler_op.u.bcredit;
+
+    return err;
+}
tools/libxc/xenctrl.h +8 -0
diff -r a00eb6595d3c tools/libxc/xenctrl.h
@@ -448,6 +448,14 @@ int xc_sched_credit_domain_get(int xc_ha
                                uint32_t domid,
                                struct xen_domctl_sched_credit *sdom);
 
+int xc_sched_bcredit_domain_set(int xc_handle,
+                                uint32_t domind,
+                                struct xen_domctl_sched_bcredit *sdom);
+
+int xc_sched_bcredit_domain_get(int xc_handle,
+                                uint32_t domid,
+                                struct xen_domctl_sched_bcredit *sdom);
+
 /**
  * This function sends a trigger to a domain.
  *
tools/python/xen/lowlevel/xc/xc.c +78 -0

96 lines not on this page · raw message

tools/python/xen/xend/XendAPI.py +10 -0
diff -r a00eb6595d3c tools/python/xen/xend/XendAPI.py
@@ -1509,6 +1509,16 @@ class XendAPI(object):
             weight = xeninfo.info['vcpus_params']['weight']
             cap = xeninfo.info['vcpus_params']['cap']
             xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
+
+        if 'bc_weight' in xeninfo.info['vcpus_params'] \
+           and 'bc_cap' in xeninfo.info['vcpus_params'] \
+           and 'bc_max_boost_period' in xeninfo.info['vcpus_params'] \
+           and 'bc_ratio' in xeninfo.info['vcpus_params']:
+            bc_weight = xeninfo.info['vcpus_params']['bc_weight']
+            bc_cap = xeninfo.info['vcpus_params']['bc_cap']
+            bc_max_boost_period = xeninfo.info['vcpus_params']['bc_max_boost_period']
+            bc_ratio = xeninfo.info['vcpus_params']['bc_ratio']
+            xendom.domain_sched_bcredit_set(xeninfo.getDomid(), bc_weight, bc_cap, bc_max_boost_period, bc_ratio)
 
     def VM_set_VCPUs_number_live(self, _, vm_ref, num):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
tools/python/xen/xend/XendConfig.py +9 -0
diff -r a00eb6595d3c tools/python/xen/xend/XendConfig.py
@@ -585,6 +585,15 @@ class XendConfig(dict):
             int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
         cfg["vcpus_params"]["cap"] = \
             int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
+        # For boost credit scheduler
+        cfg["vcpus_params"]["bc_weight"] = \
+            int(sxp.child_value(sxp_cfg, "cpu_bc_weight", 256))
+        cfg["vcpus_params"]["bc_cap"] = \
+            int(sxp.child_value(sxp_cfg, "cpu_bc_cap", 0))
+        cfg["vcpus_params"]["bc_max_boost_period"] = \
+            int(sxp.child_value(sxp_cfg, "cpu_bc_max_boost_period", 0))
+        cfg["vcpus_params"]["bc_ratio"] = \
+            int(sxp.child_value(sxp_cfg, "cpu_bc_ratio", 0))
 
         # Only extract options we know about.
         extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \
tools/python/xen/xend/XendDomain.py +93 -0

99 lines not on this page · raw message

tools/python/xen/xend/XendDomainInfo.py +32 -0
diff -r a00eb6595d3c tools/python/xen/xend/XendDomainInfo.py
@@ -466,6 +466,14 @@ class XendDomainInfo:
                     xendomains.domain_sched_credit_set(self.getDomid(),
                                                        self.getWeight(),
                                                        self.getCap())
+
+                if xennode.xenschedinfo() == 'bcredit':
+                    xendomains.domain_sched_bcredit_set(self.getDomid(),
+                                                        self.getBCWeight(),
+                                                        self.getBCCap(),
+                                                        self.getBCMaxBoostPeriod(),
+                                                        self.getBCRatio())
+
             except:
                 log.exception('VM start failed')
                 self.destroy()
@@ -1606,6 +1614,30 @@ class XendDomainInfo:
     def setWeight(self, cpu_weight):
         self.info['vcpus_params']['weight'] = cpu_weight
 
+    def getBCCap(self):
+        return self.info['vcpus_params']['bc_cap']
+
+    def setBCCap(self, cpu_bc_cap):
+        self.info['vcpus_params']['bc_cap'] = cpu_bc_cap
+
+    def getBCWeight(self):
+        return self.info['vcpus_params']['bc_weight']
+
+    def setBCWeight(self, cpu_bc_weight):
+        self.info['vcpus_params']['bc_weight'] = cpu_bc_weight
+
+    def getBCMaxBoostPeriod(self):
+        return self.info['vcpus_params']['bc_max_boost_period']
+
+    def setBCMaxBoostPeriod(self, cpu_bc_max_boost_period):
+        self.info['vcpus_params']['bc_max_boost_period'] = cpu_bc_max_boost_period
+
+    def getBCRatio(self):
+        return self.info['vcpus_params']['bc_ratio']
+
+    def setBCRatio(self, cpu_bc_ratio):
+        self.info['vcpus_params']['bc_ratio'] = cpu_bc_ratio
+
     def getRestartCount(self):
         return self._readVm('xend/restart_count')
 
tools/python/xen/xend/XendNode.py +4 -0
diff -r a00eb6595d3c tools/python/xen/xend/XendNode.py
@@ -555,6 +555,8 @@ class XendNode:
             return 'sedf'
         elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
             return 'credit'
+        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_BCREDIT:
+            return 'bcredit'
         else:
             return 'unknown'
 
@@ -714,6 +716,8 @@ class XendNode:
             return 'sedf'
         elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
             return 'credit'
+        elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_BCREDIT:
+            return 'bcredit'
         else:
             return 'unknown'
 
tools/python/xen/xm/main.py +120 -0

144 lines not on this page · raw message

xen/common/sched_credit.c +1000 -0

1,003 lines not on this page · raw message

xen/common/schedule.c +2 -0
diff -r a00eb6595d3c xen/common/schedule.c
@@ -51,9 +51,11 @@ DEFINE_PER_CPU(struct schedule_data, sch
 
 extern struct scheduler sched_sedf_def;
 extern struct scheduler sched_credit_def;
+extern struct scheduler sched_bcredit_def;
 static struct scheduler *schedulers[] = { 
     &sched_sedf_def,
     &sched_credit_def,
+    &sched_bcredit_def,
     NULL
 };
 
xen/include/public/domctl.h +7 -0
diff -r a00eb6595d3c xen/include/public/domctl.h
@@ -294,6 +294,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_v
 /* Scheduler types. */
 #define XEN_SCHEDULER_SEDF     4
 #define XEN_SCHEDULER_CREDIT   5
+#define XEN_SCHEDULER_BCREDIT  6
 /* Set or get info? */
 #define XEN_DOMCTL_SCHEDOP_putinfo 0
 #define XEN_DOMCTL_SCHEDOP_getinfo 1
@@ -312,6 +313,12 @@ struct xen_domctl_scheduler_op {
             uint16_t weight;
             uint16_t cap;
         } credit;
+        struct xen_domctl_sched_bcredit {
+            uint16_t weight;
+            uint16_t cap;
+            uint16_t max_boost_period;
+            uint16_t boost_ratio;
+        } bcredit;
     } u;
 };
 typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw
Quoted 2 lines · NISHIGUCHI Naoki

Please review this patch.
Any comments are appreciated.

Don't hack it into the existing sched_credit.c unless you are really sharing significant amounts of stuff (which it looks like you aren't?). sched_bcredit.c would be a cleaner name if there's no sharing. Is a new scheduler necessary -- could the existing credit scheduler be generalised with your boost mechanism to be suitable for both client and server?

The issue with multiple schedulers is that it's most likely the non-default will not be tested, used or maintained. The default credit scheduler gets little enough love as it is, and it's really the only sensible scheduler to choose now (SEDF is not great -- good example of a rotten non-default scheduler).

-- Keir

#2 lore raw
Quoted 5 lines · Keir Fraser

Don't hack it into the existing sched_credit.c unless you are really sharing significant amounts of stuff (which it looks like you aren't?). sched_bcredit.c would be a cleaner name if there's no sharing. Is a new scheduler necessary -- could the existing credit scheduler be generalised with your boost mechanism to be suitable for both client and server?

I think we ought to be able to work this out; the functionality doesn't sound that different, and as you say, keeping two schedulers around is only an invitation to bitrot.

The more accurate credit scheduling and vcpu credit "balancing" seem like good ideas. For the other changes, it's probably worth measuring on a battery of tests to see what kinds of effects we get, especially on network throughput.

Nishiguchi-san, (I hope that's right!) as I understood from your presentation, you haven't tested this on a server workload, but you predict that the "boost" scheduling of 2ms will cause unnecessary overhead for server workloads. Is that correct?

Couldn't we avoid the overhead this way: If a vcpu has 5 or more "boost" credits, we simply set the next-timer to 10ms. If the vcpu yields before then, we subtract the amount of "boost" credits actually used. If not, we subtract 5. That way we're not interrupting any more frequently than we were before.

Come to think of it: won't the effect of setting the 'boost' time to 2ms be basically counteracted by giving domains boost credits? I thought the purpose reducing the boost time was to allow other domains to run more quickly? But if a domain has more than 5 'boost' credits, it will run for a full 10 ms anyway. Is that not so?

Could you test your video latency measurement with all the other optimizations, but with the "boost" time set to 10ms instead of 2? If it works well, it's probably worth simply merging the bulk of your changes in and testing with server workloads.

-George

#3 lore raw

Thank you for your suggestions.

Quoted 10 lines · George Dunlap
Quoted 5 lines · Keir Fraser

Don't hack it into the existing sched_credit.c unless you are really sharing significant amounts of stuff (which it looks like you aren't?). sched_bcredit.c would be a cleaner name if there's no sharing. Is a new scheduler necessary -- could the existing credit scheduler be generalised with your boost mechanism to be suitable for both client and server?

I think we ought to be able to work this out; the functionality doesn't sound that different, and as you say, keeping two schedulers around is only an invitation to bitrot.

I had thought that the scheduler for client would be needed separately because this modification would influence a server workload. In order to minimize modifications, the bcredit scheduler was implemented by wrapping the current credit scheduler. I added the differences between original and bcredit. But as a result, almost functions were created newly.

Now, I agree that one scheduler is best.

Quoted 4 lines

The more accurate credit scheduling and vcpu credit "balancing" seem like good ideas. For the other changes, it's probably worth measuring on a battery of tests to see what kinds of effects we get, especially on network throughput.

I didn’t think about the battery and the performance.

Quoted 4 lines

Nishiguchi-san, (I hope that's right!) as I understood from your presentation, you haven't tested this on a server workload, but you predict that the "boost" scheduling of 2ms will cause unnecessary overhead for server workloads. Is that correct?

Yes, you are correct. I answered that in Q/A.

Quoted 5 lines

Couldn't we avoid the overhead this way: If a vcpu has 5 or more "boost" credits, we simply set the next-timer to 10ms. If the vcpu yields before then, we subtract the amount of "boost" credits actually used. If not, we subtract 5. That way we're not interrupting any more frequently than we were before.

I set the next-timer to 2ms in any vcpu having “boost” credits since every vcpu having “boost” credits need to be run equally at short intervals. If there are vcpus having “boost” credits and the next-timer of a vcpu is set to 10ms, the other vcpus will be waited during 10ms.

At present, I am thinking that if the other vcpus don’t have “boost” credits then we may set the next-timer to 30ms.

Quoted 5 lines

Come to think of it: won't the effect of setting the 'boost' time to 2ms be basically counteracted by giving domains boost credits? I thought the purpose reducing the boost time was to allow other domains to run more quickly? But if a domain has more than 5 'boost' credits, it will run for a full 10 ms anyway. Is that not so?

I suppose that there are two domains given “boost” credits. One domain runs for 2ms, then the other domain runs for 2ms, then one domain runs for 2ms, then the other domain runs for 2ms, … Because I think to need that waited time of both is same.

Quoted 4 lines

Could you test your video latency measurement with all the other optimizations, but with the "boost" time set to 10ms instead of 2? If it works well, it's probably worth simply merging the bulk of your changes in and testing with server workloads.

I tested the video latency measurement with the “boost” time set to 10ms. But it regretted not to work well. As I was mentioned above, the vcpu was occasionally waited during 10ms.

On my patch, “boost” time is tuneable. How about the default “boost” time is 30ms and if necessary, “boost” time is set? Is it acceptable?

In order to lengthen the “boost” time as much as possible, I will think about computing the length of the next-timer of the vcpu having “boost” credits. I’ll try to revise the patch.

And thanks again.

Best regards,
Naoki Nishiguchi

#4 lore raw
Quoted 6 lines · NISHIGUCHI Naoki
Quoted 4 lines

The more accurate credit scheduling and vcpu credit "balancing" seem like good ideas. For the other changes, it's probably worth measuring on a battery of tests to see what kinds of effects we get, especially on network throughput.

I didn't think about the battery and the performance.

I'm sorry, I used an uncommon definition of the word "battery"; I should have been more careful. :-)

In this context, "a battery of tests" means "a combination of several different kinds of tests." I meant some disk-intensive tests, some network-intensive tests, some cpu-intensive tests, and some combination of all three. I can run some of these, and you can make sure that the "client" tests still work well. It would probably be helpful to have other people volunteer to do some testing as well, just to make sure we have our bases covered.

Quoted 7 lines

I set the next-timer to 2ms in any vcpu having "boost" credits since every vcpu having "boost" credits need to be run equally at short intervals. If there are vcpus having "boost" credits and the next-timer of a vcpu is set to 10ms, the other vcpus will be waited during 10ms.

At present, I am thinking that if the other vcpus don't have "boost" credits then we may set the next-timer to 30ms.

I see -- the current setup is good if there's only one "boosted" VM (per cpu) at a time; but if there are two "boosted" VMs, they're back to taking turns at 30 ms. Your 2ms patch allows several latency-sensitive VMs to share the "low latency" boost. That makes sense. I agree with your suggestion: we can set the timer to 2ms only if the next waiting vcpu on the queue is also BOOST.

Quoted 3 lines

I tested the video latency measurement with the "boost" time set to 10ms. But it regretted not to work well. As I was mentioned above, the vcpu was occasionally waited during 10ms.

OK, good to know.

Quoted 2 lines

On my patch, "boost" time is tuneable. How about the default "boost" time is 30ms and if necessary, "boost" time is set? Is it acceptable?

I suspect that latency-sensitive workloads such as network, especially network servers that do very little computation, may also benefit from short boost times.

Quoted 3 lines

In order to lengthen the "boost" time as much as possible, I will think about computing the length of the next-timer of the vcpu having "boost" credits.

If it makes things simpler, we could just stick with 10ms timeslices when there are no waiting vcpus with BOOST priority, and 2ms if there is BOOST priority. I don't think there's a particular need to give a VM only (say) 8 ms instead of 10, if there are no latency-sensitive VMs waiting.

Quoted 1 line

I'll try to revise the patch.

I suggest:
* Modify the credit scheduler directly, rather than having an extra scheduler
* Break down your changes into patches that make individual changes, i.e (from your first post):
+ A patch to subtract credit consumed accurately
+ A patch to preserve the value of cpu credit when the vcpu is over upper bound
+ A patch to shorten cpu time per one credit
+ A patch to balance credits of each vcpu of a domain
+ A patch to introduce BOOST credit (both Xen and tool components)
+ A patch to shorten allocated time in BOOST priority if the next
vcpu on the runqueue is also at BOOST

Then we can evaluate each change individually.

Thanks for your work!

-George

#5 lore raw
Quoted 6 lines · George Dunlap

I see -- the current setup is good if there's only one "boosted" VM (per cpu) at a time; but if there are two "boosted" VMs, they're back to taking turns at 30 ms. Your 2ms patch allows several latency-sensitive VMs to share the "low latency" boost. That makes sense. I agree with your suggestion: we can set the timer to 2ms only if the next waiting vcpu on the queue is also BOOST.

There was a paper earlier this year about scheduling and I/O performance:
http://www.cs.rice.edu/CS/Architecture/docs/ongaro-vee08.pdf

One of the things he noted was that if a driver domain is accepting network packets for multiple VMs, we sometimes get the following pattern:
* driver domain wakes up, starts processing packets. Because it's in "over", it doesn't get boosted.
* Passes a packet to VM 1, waking it up. It runs in "boost", preempting the (now lower-priority) driver domain.
* Other packets (possibly even for VM 1) sit in the driver domain's queue, waiting for it to get cpu time.

Their tests, for 3 networking guests and 3 cpu-intensive guests, showed a 40% degradation in performance due to this problem. While we're thinking about the scheduler, it might be worth seeing if we can solve this.

-George

#6 lore raw

Thanks for your information.

Quoted 12 lines · George Dunlap

There was a paper earlier this year about scheduling and I/O performance:
http://www.cs.rice.edu/CS/Architecture/docs/ongaro-vee08.pdf

One of the things he noted was that if a driver domain is accepting network packets for multiple VMs, we sometimes get the following pattern:
* driver domain wakes up, starts processing packets. Because it's in "over", it doesn't get boosted.
* Passes a packet to VM 1, waking it up. It runs in "boost", preempting the (now lower-priority) driver domain.
* Other packets (possibly even for VM 1) sit in the driver domain's queue, waiting for it to get cpu time.

I don't read the paper yet, but I think our approach is effective in this problem.
However, if driver domain consumes cpu time too much, we couldn't prevent it from becoming "over" priority. Otherwise, we could keep it with "under" or "boost" priority.

Quoted 4 lines

Their tests, for 3 networking guests and 3 cpu-intensive guests, showed a 40% degradation in performance due to this problem. While we're thinking about the scheduler, it might be worth seeing if we can solve this.

Firstly, I'd like to read the paper.

Regards,
Naoki Nishiguchi

#7 lore raw

Hi all,

In almost the same environment as the paper, I experimented with credit scheduler(original and modified version). I describe the results below.

Unfortunately the good result was not obtained by my previous patches.

I found that there were some problems on my previous patches.
So, I had revised the patches and experimented with revised version again. Using revised patches, the good result was obtained. Especially, please look at the result of ex7. In revised version, I/O bandwidth per guest is growing correctly according to dom0's weight.

I'll post the revised patches later.

Thanks,
Naoki Nishiguchi

---------- results ----------
experimental environment:
HP dc7800 US/CT(Core2 Duo E6550 2.33GHz)
Multi-processor: disable
Xen: xen 3.3.0 release
dom0: CentOS 5.2

I used the following experiments from among the paper's experiments.
ex3: burn x7, ping x1
ex5: stream x7, ping x1
ex7: stream x3, burn x3, ping x1
ex8: stream x3, ping+burn x1, burn x3

original credit scheduler
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 19.7(average) 0.1 - 359
ex5
stream(Mbps): 144.05 141.19 137.81 137.01 137.30 138.76 142.21
ping(ms) : 8.2(average) 7.84 - 8.63
ex7
stream(Mbps): 33.74 27.74 34.70
burn(%): 28 28 28 (by guess)
ping(ms): 238(average) 1.78 - 485
ex7(xm sched-credit -d 0 -w 512)
There was no change in the result.
ex8
stream(Mbps): 9.98 11.32 10.61
ping+burn: 264.9ms(average) 20.3 - 547

                24%

burn(%): 24 24 24

modified version(previous patches)
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 0.17(average) 0.136 - 0.202
ex5
stream(Mbps): 143.90 141.79 137.15 138.43 138.37 130.33 143.36
ping(ms): 7.2(average) 4.85 - 8.95
ex7
stream(Mbps): 2.33 2.18 1.87
burn(%): 32 32 32 (by guess)
ping(ms): 373.7(average) 68.0 - 589
ex7(xm sched-credit -d 0 -w 512)
There was no change in the result.
ex7(xm sched-credit -d 0 -m 100 -r 20)
stream(Mbps): 114.49 117.59 115.76
burn(%): 24 24 24
ping(ms): 1.2(average) 0.158 - 65.1
ex8
stream(Mbps): 1.31 1.09 1.92
ping+burn: 387.7ms(average) 92.6 - 676

                24% (by guess)

burn(%): 24 24 24 (by guess)

revised version
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 0.18(average) 0.140 - 0.238
ex5
stream(Mbps): 142.57 139.03 137.50 136.77 137.61 138.95 142.63
ping(ms): 8.2(average) 7.86 - 8.71
ex7
stream(Mbps): 143.63 132.13 131.77
burn(%): 24 24 24
ping(ms): 32.2(average) 1.73 - 173
ex7(xm sched-credit -d 0 -w 512)
stream(Mbps): 240.06 204.85 229.23
burn(%): 18 18 18
ping(ms): 7.0(average) 0.412 - 73.9
ex7(xm sched-credit -d 0 -m 100 -r 20)
stream(Mbps): 139.74 134.95 135.18
burn(%): 23 23 23
ping(ms): 15.1(average) 1.87 - 95.4
ex8
stream(Mbps): 118.15 106.71 116.37
ping+burn: 68.8ms(average) 1.86 - 319

                19%

burn(%): 19 19 19
----------

Quoted 34 lines · NISHIGUCHI Naoki

Thanks for your information.

Quoted 12 lines · George Dunlap

There was a paper earlier this year about scheduling and I/O performance:
http://www.cs.rice.edu/CS/Architecture/docs/ongaro-vee08.pdf

One of the things he noted was that if a driver domain is accepting network packets for multiple VMs, we sometimes get the following pattern:
* driver domain wakes up, starts processing packets. Because it's in "over", it doesn't get boosted.
* Passes a packet to VM 1, waking it up. It runs in "boost", preempting the (now lower-priority) driver domain.
* Other packets (possibly even for VM 1) sit in the driver domain's queue, waiting for it to get cpu time.

I don't read the paper yet, but I think our approach is effective in this problem.
However, if driver domain consumes cpu time too much, we couldn't prevent it from becoming "over" priority. Otherwise, we could keep it with "under" or "boost" priority.

Quoted 4 lines

Their tests, for 3 networking guests and 3 cpu-intensive guests, showed a 40% degradation in performance due to this problem. While we're thinking about the scheduler, it might be worth seeing if we can solve this.

Firstly, I'd like to read the paper.

Regards,
Naoki Nishiguchi

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#8 lore raw

Naoki,

Thank you for your work! The results look really good.

Overall, I think the scheduler as a whole needs some design work before these can go in. No one at this point fully understands the principles on which it's supposed to run. I've been taking a close look at the unmodified scheduler (notably trying to understand the anomalies pointed out by Atsushi), and I think it's clear that there are some flaws in the logic.

Before making a large change like this, I think we should do several things:
* Try to describe exactly what the scheduler is currently doing, and why
* If there are some inconsistencies, change them
* Modify the description to include your proposed changes to the boost scheduler

Your changes, although proven effective, make the scheduler much more complicated. If no one understands it now, it will be even harder to understand with your changes, unless we set down some very clear documentation of how the algorithm is supposed to work. Namely, we need to document:

* What factors different workloads need; i.e.:
+ Long enough time for cpu-bound workloads to warm up the cache effectively
+ Fast responsiveness for "latency-sensitive" workloads, esp. in the
face of multiple latency-sensitive workloads
+ Fairness wrt weight
* At a high level, what we'd like to see happen
* How individual mechanisms work:
+ Credits: when they are added / subtracted
+ Priorities: when they are changed and why
+ Preemption: when a cpu-bound process gets preempted
+ Active / passive status: when and why switched from one to the other

I've been intending to do this for a couple of weeks now, but I've got some other patches I need to get cleaned up and submitted first. Hopefully those will be finished by the end of the week. This is my very next priority.

Once I have the "design" document, I can describe your changes in reference to them, and we can discuss them at a design level.

I have a couple of specific comments on your patches that I'll put inline in other e-mails.

Thank you for your work, and your patience.

-George

Quoted 150 lines · NISHIGUCHI Naoki

Hi all,

In almost the same environment as the paper, I experimented with credit scheduler(original and modified version).
I describe the results below.

Unfortunately the good result was not obtained by my previous patches.

I found that there were some problems on my previous patches. So, I had revised the patches and experimented with revised version again. Using revised patches, the good result was obtained. Especially, please look at the result of ex7. In revised version, I/O bandwidth per guest is growing correctly according to dom0's weight.

I'll post the revised patches later.

Thanks,
Naoki Nishiguchi

---------- results ----------
experimental environment:
HP dc7800 US/CT(Core2 Duo E6550 2.33GHz)
Multi-processor: disable
Xen: xen 3.3.0 release
dom0: CentOS 5.2

I used the following experiments from among the paper's experiments.
ex3: burn x7, ping x1
ex5: stream x7, ping x1
ex7: stream x3, burn x3, ping x1
ex8: stream x3, ping+burn x1, burn x3

original credit scheduler
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 19.7(average) 0.1 - 359
ex5
stream(Mbps): 144.05 141.19 137.81 137.01 137.30 138.76 142.21
ping(ms) : 8.2(average) 7.84 - 8.63
ex7
stream(Mbps): 33.74 27.74 34.70
burn(%): 28 28 28 (by guess)
ping(ms): 238(average) 1.78 - 485
ex7(xm sched-credit -d 0 -w 512)
There was no change in the result.
ex8
stream(Mbps): 9.98 11.32 10.61
ping+burn: 264.9ms(average) 20.3 - 547

               24%

burn(%): 24 24 24

modified version(previous patches)
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 0.17(average) 0.136 - 0.202
ex5
stream(Mbps): 143.90 141.79 137.15 138.43 138.37 130.33 143.36
ping(ms): 7.2(average) 4.85 - 8.95
ex7
stream(Mbps): 2.33 2.18 1.87
burn(%): 32 32 32 (by guess)
ping(ms): 373.7(average) 68.0 - 589
ex7(xm sched-credit -d 0 -w 512)
There was no change in the result.
ex7(xm sched-credit -d 0 -m 100 -r 20)
stream(Mbps): 114.49 117.59 115.76
burn(%): 24 24 24
ping(ms): 1.2(average) 0.158 - 65.1
ex8
stream(Mbps): 1.31 1.09 1.92
ping+burn: 387.7ms(average) 92.6 - 676

               24% (by guess)

burn(%): 24 24 24 (by guess)

revised version
ex3
burn(%): 14 14 14 14 14 14 14
ping(ms): 0.18(average) 0.140 - 0.238
ex5
stream(Mbps): 142.57 139.03 137.50 136.77 137.61 138.95 142.63
ping(ms): 8.2(average) 7.86 - 8.71
ex7
stream(Mbps): 143.63 132.13 131.77
burn(%): 24 24 24
ping(ms): 32.2(average) 1.73 - 173
ex7(xm sched-credit -d 0 -w 512)
stream(Mbps): 240.06 204.85 229.23
burn(%): 18 18 18
ping(ms): 7.0(average) 0.412 - 73.9
ex7(xm sched-credit -d 0 -m 100 -r 20)
stream(Mbps): 139.74 134.95 135.18
burn(%): 23 23 23
ping(ms): 15.1(average) 1.87 - 95.4
ex8
stream(Mbps): 118.15 106.71 116.37
ping+burn: 68.8ms(average) 1.86 - 319

               19%

burn(%): 19 19 19
----------

Quoted 31 lines · NISHIGUCHI Naoki

Thanks for your information.

Quoted 4 lines · George Dunlap

There was a paper earlier this year about scheduling and I/O performance:
http://www.cs.rice.edu/CS/Architecture/docs/ongaro-vee08.pdf

Quoted 9 lines

One of the things he noted was that if a driver domain is accepting network packets for multiple VMs, we sometimes get the following pattern:
* driver domain wakes up, starts processing packets. Because it's in "over", it doesn't get boosted.
* Passes a packet to VM 1, waking it up. It runs in "boost", preempting the (now lower-priority) driver domain.
* Other packets (possibly even for VM 1) sit in the driver domain's queue, waiting for it to get cpu time.

I don't read the paper yet, but I think our approach is effective in this problem.
However, if driver domain consumes cpu time too much, we couldn't prevent it from becoming "over" priority. Otherwise, we could keep it with "under" or "boost" priority.

Quoted 4 lines

Their tests, for 3 networking guests and 3 cpu-intensive guests, showed a 40% degradation in performance due to this problem. While we're thinking about the scheduler, it might be worth seeing if we can solve this.

Firstly, I'd like to read the paper.

Quoted 8 lines

Regards,
Naoki Nishiguchi

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#9 lore raw
In reply to George Dunlap

Hi,

Thank you for your comments and suggestions.

Quoted 5 lines · George Dunlap
Quoted 1 line

I didn't think about the battery and the performance.

I'm sorry, I used an uncommon definition of the word "battery"; I should have been more careful. :-)

Quoted 7 lines

In this context, "a battery of tests" means "a combination of several different kinds of tests." I meant some disk-intensive tests, some network-intensive tests, some cpu-intensive tests, and some combination of all three. I can run some of these, and you can make sure that the "client" tests still work well. It would probably be helpful to have other people volunteer to do some testing as well, just to make sure we have our bases covered.

Oh, I misread the word “battery”. I understand what “a battery of tests” means. By the way, what tests do you concretely do? I have no idea on these tests.

Quoted 8 lines
Quoted 7 lines

I set the next-timer to 2ms in any vcpu having "boost" credits since every vcpu having "boost" credits need to be run equally at short intervals. If there are vcpus having "boost" credits and the next-timer of a vcpu is set to 10ms, the other vcpus will be waited during 10ms.

At present, I am thinking that if the other vcpus don't have "boost" credits then we may set the next-timer to 30ms.

Quoted 6 lines

I see -- the current setup is good if there's only one "boosted" VM (per cpu) at a time; but if there are two "boosted" VMs, they're back to taking turns at 30 ms. Your 2ms patch allows several latency-sensitive VMs to share the "low latency" boost. That makes sense. I agree with your suggestion: we can set the timer to 2ms only if the next waiting vcpu on the queue is also BOOST.

OK.
We must consider also a sleeping vcpu. The vcpu will be added to the queue by wakeup. So, we can set the timer to 2ms only if the next waiting vcpu on the queue or the sleeping vcpu is also BOOST.

My thought about 2ms is: the period that the vcpu will be executed next is 2ms. Therefore, time slice of the vcpu is changed according to the number of existing vcpus. In a word, we may set the timer to 2ms or less. But I think that the number of vcpus will not be so much. Is this supposition wrong? And how about time slice of 2ms or less?

Quoted 6 lines
Quoted 2 lines

On my patch, "boost" time is tuneable. How about the default "boost" time is 30ms and if necessary, "boost" time is set? Is it acceptable?

I suspect that latency-sensitive workloads such as network, especially network servers that do very little computation, may also benefit from short boost times.

I think so, too.

Quoted 9 lines
Quoted 3 lines

In order to lengthen the "boost" time as much as possible, I will think about computing the length of the next-timer of the vcpu having "boost" credits.

If it makes things simpler, we could just stick with 10ms timeslices when there are no waiting vcpus with BOOST priority, and 2ms if there is BOOST priority. I don't think there's a particular need to give a VM only (say) 8 ms instead of 10, if there are no latency-sensitive VMs waiting.

I agree.

Quoted 14 lines
Quoted 1 line

I'll try to revise the patch.

I suggest:
* Modify the credit scheduler directly, rather than having an extra scheduler
* Break down your changes into patches that make individual changes, i.e (from your first post):
+ A patch to subtract credit consumed accurately
+ A patch to preserve the value of cpu credit when the vcpu is over upper bound
+ A patch to shorten cpu time per one credit
+ A patch to balance credits of each vcpu of a domain
+ A patch to introduce BOOST credit (both Xen and tool components)
+ A patch to shorten allocated time in BOOST priority if the next
vcpu on the runqueue is also at BOOST

Quoted 1 line

Then we can evaluate each change individually.

OK.
I’ll separate individual changes from current patch and post each patch.

Best regards,
Naoki Nishiguchi

#10 lore raw
Quoted 3 lines · NISHIGUCHI Naoki

Oh, I misread the word "battery". I understand what "a battery of tests" means.
By the way, what tests do you concretely do? I have no idea on these tests.

For basic workload tests, a couple are pretty handy. vConsolidate is a good test, but pretty hard to set up; I should be able to manage it with our infrastructure here, though. Other tests include:
* kernel-build (i.e., time how long it takes to build the Linux kernel) and or ddk-build (Windows equivalent)
* specjbb (a cpu-intensive workload)
* netperf (for networks)

For testing its effect on network, the paper I mentioned has three workloads that it combines with different ways:
* cpu (just busy spinning)
* sustained network (netbench): throughput
* network ping: latency.

Quoted 10 lines

OK.
We must consider also a sleeping vcpu. The vcpu will be added to the queue by wakeup. So, we can set the timer to 2ms only if the next waiting vcpu on the queue or the sleeping vcpu is also BOOST.

My thought about 2ms is: the period that the vcpu will be executed next is 2ms. Therefore, time slice of the vcpu is changed according to the number of existing vcpus. In a word, we may set the timer to 2ms or less. But I think that the number of vcpus will not be so much. Is this supposition wrong? And how about time slice of 2ms or less?

I think I understand you to mean: If we set the timer for 10ms, and in the mean time another vcpu wakes up and is set at BOOST, then it won't get a chance to run for another 10 ms. And you're suggesting that we run the scheduler at 2ms if there are any vcpus that *may* wake up and be at BOOST, just in case; and you don't think this situation will happen very often. Is that correct?

Unfortunately, in consolidated server workloads you're pretty likely to have more vcpus than physical cpus, so I think this case would come up pretty often. Furthermore, 2ms is really too short a scheduling quantum for normal use, especially for HVM domains, which have to take a vmexit/vmenter cycle to handle every interrupt. (I did some tests back when we were using the SEDF scheduler, and the scheduling alone was a 4-5% overhead for HVM domains.)

But I don't think we actually have a problem here: if a vcpu wakes up and is promoted to BOOST, won't it "tickle" the runqueues to find somewhere for it to run? At very least the current cpu should be able to run it, or if it's already running one at BOOST, it can set its own timer to 2ms. In any case, I think handling this corner case with some extra code is preferrable to running a 2ms timer any time it *might* happen.

Quoted 2 lines

OK.
I'll separate individual changes from current patch and post each patch.

Thanks! I'll take them for a spin today.

-George

#11 lore raw
Quoted 8 lines · George Dunlap

For basic workload tests, a couple are pretty handy. vConsolidate is a good test, but pretty hard to set up; I should be able to manage it with our infrastructure here, though. Other tests include:
* kernel-build (i.e., time how long it takes to build the Linux kernel) and or ddk-build (Windows equivalent)
* specjbb (a cpu-intensive workload)
* netperf (for networks)

Quoted 5 lines

For testing its effect on network, the paper I mentioned has three workloads that it combines with different ways:
* cpu (just busy spinning)
* sustained network (netbench): throughput
* network ping: latency.

Thanks! I'll try to prepare.

Quoted 6 lines

I think I understand you to mean: If we set the timer for 10ms, and in the mean time another vcpu wakes up and is set at BOOST, then it won't get a chance to run for another 10 ms. And you're suggesting that we run the scheduler at 2ms if there are any vcpus that *may* wake up and be at BOOST, just in case; and you don't think this situation will happen very often. Is that correct?

Almost that is correct.
I had thought that we run the scheduler at 2ms only if there are vcpus that have boost credit and are already at BOOST. But I don't think so now.

Quoted 7 lines

Unfortunately, in consolidated server workloads you're pretty likely to have more vcpus than physical cpus, so I think this case would come up pretty often. Furthermore, 2ms is really too short a scheduling quantum for normal use, especially for HVM domains, which have to take a vmexit/vmenter cycle to handle every interrupt. (I did some tests back when we were using the SEDF scheduler, and the scheduling alone was a 4-5% overhead for HVM domains.)

I see.

Quoted 7 lines

But I don't think we actually have a problem here: if a vcpu wakes up and is promoted to BOOST, won't it "tickle" the runqueues to find somewhere for it to run? At very least the current cpu should be able to run it, or if it's already running one at BOOST, it can set its own timer to 2ms. In any case, I think handling this corner case with some extra code is preferrable to running a 2ms timer any time it *might* happen.

OK.
I implemented as follows:
- If next running vcpu is at BOOST and first vcpu on run-queue is at BOOST, set the timer to 2ms.
- If next running vcpu is at BOOST and first vcpu on run-queue is not at BOOST, set the timer to 10ms.
- If next running vcpu is not at BOOST, set the timer to 30ms.
- When a vcpu wakes up, if the vcpu has boost credit then send scheduler interrupts to at least one CPU.

In my test environment, it works well.
I'll post last patch today.

Thanks,
Naoki

#12 lore raw
In reply to Keir Fraser

Thank you for your comment.

I'll try to be suitable for both server and client.

Regards,
Naoki Nishiguchi

Quoted 25 lines · Keir Fraser
Quoted 2 lines · NISHIGUCHI Naoki

Please review this patch.
Any comments are appreciated.

Don't hack it into the existing sched_credit.c unless you are really sharing significant amounts of stuff (which it looks like you aren't?). sched_bcredit.c would be a cleaner name if there's no sharing. Is a new scheduler necessary -- could the existing credit scheduler be generalised with your boost mechanism to be suitable for both client and server?

The issue with multiple schedulers is that it's most likely the non-default will not be tested, used or maintained. The default credit scheduler gets little enough love as it is, and it's really the only sensible scheduler to choose now (SEDF is not great -- good example of a rotten non-default scheduler).

-- Keir

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#16 lore raw

Naoki,

I'm working on revising the scheduler right now, so it's probably best if you hold off patches for a little while.

I'm also trying to understand the minimum that your client workloads actually need to run well. There were compontents of the "boost" patch series that helped your workload:
(a) minimum cpu time,
(b) Shortened time slices (2ms)
(c) "boosted" priority for multimedia domains

Is it possible that having (a) and (b), possibly with some other combinations, could work well without adding (c)?

At any rate, I'm going to start with a revised system that has a minimum cpu time, but no "high priority", and see if we can get things to work OK without it.

Thanks for your work, BTW -- the scheduler has needed some attention for a long time, but I don't think it would have gotten it if you hadn't introduced these patches.

Peace,
-George

Quoted 32 lines · NISHIGUCHI Naoki

Hi George,

Quoted 9 lines · George Dunlap

Sorry, didn't finish my thoughts before sending...

Quoted 5 lines

The original meaning of the "boost" priority was a priority given to domains when waking up, so that latency-sensitive workloads could achieve low latency when competing with cpu-intensive workloads, while maintaining weight. I think this meaning of "boost" (and the mechanism) is still important, especially for server-style workloads.

Quoted 3 lines

...so, I think we need to maintain the old "boost" mechanism (or something like it), and come up with a new name for this "priority cpu time" feature.

I believe that the old "boost" mechanism remains after applying my patches. But, now I think that "priority cpu time" feature needs a new name as you said.

Because of not changing the existing functionalities in credit scheduler and achieving continuous high-priority for a domain, I decided to use "boost" mechanism, especially boost priority. In my rev2 patches, old "boost" mechanism and "boost credit" I introduced were integrated strongly and the good result was obtained. But, as you said and I wrote above, I think that the "boost" mechanism and "boost credit" should be separated. I'll try to achieve this by introducing new priority for "priority cpu time" feature.

Regards,
Naoki

#17 lore raw

Hi George,

Quoted 2 lines · George Dunlap

I'm working on revising the scheduler right now, so it's probably best if you hold off patches for a little while.

OK. I'll wait to finish your work.

Quoted 9 lines

I'm also trying to understand the minimum that your client workloads actually need to run well. There were compontents of the "boost" patch series that helped your workload:
(a) minimum cpu time,
(b) Shortened time slices (2ms)
(c) "boosted" priority for multimedia domains

Is it possible that having (a) and (b), possibly with some other combinations, could work well without adding (c)?

Yes, it is possible.
I divided the rev2 "boost" patch as follows without (c).
(1) minimum cpu time (a): boost_1.patch + boost_1_tools.patch
(2) Shortened time slices (b): boost_2.patch
(3) alternative "boost" mechanism by boost_credit: boost_3.patch

These patches works with the following combinations.
(1), (1)+(2), (1)+(2)+(3)
Please apply these patches in numerical order.

Without (3), didn't solve the problem in the paper you showed.

Are these what you want?

Quoted 7 lines

At any rate, I'm going to start with a revised system that has a minimum cpu time, but no "high priority", and see if we can get things to work OK without it.

Thanks for your work, BTW -- the scheduler has needed some attention for a long time, but I don't think it would have gotten it if you hadn't introduced these patches.

Thanks.

Best regards,
Naoki

xen/common/sched_credit.c +90 -13
diff -r 56032cbaf1e8 xen/common/sched_credit.c
@@ -201,6 +201,7 @@ struct csched_vcpu {
     struct csched_dom *sdom;
     struct vcpu *vcpu;
     atomic_t credit;
+    int prev_credit;
     uint16_t flags;
     int16_t pri;
 #ifdef CSCHED_STATS
@@ -225,6 +226,7 @@ struct csched_dom {
     uint16_t active_vcpu_count;
     uint16_t weight;
     uint16_t cap;
+    uint16_t percent;
 };
 
 /*
@@ -239,6 +241,8 @@ struct csched_private {
     cpumask_t idlers;
     uint32_t weight;
     uint32_t credit;
+    uint32_t percent;
+    uint16_t total_percent;
     int credit_balance;
     uint32_t runq_sort;
     CSCHED_STATS_DEFINE()
@@ -503,6 +507,7 @@ __csched_vcpu_acct_start_locked(struct c
         {
             list_add(&sdom->active_sdom_elem, &csched_priv.active_sdom);
             csched_priv.weight += sdom->weight;
+            csched_priv.percent += sdom->percent;
         }
     }
 }
@@ -525,6 +530,7 @@ __csched_vcpu_acct_stop_locked(struct cs
         BUG_ON( csched_priv.weight < sdom->weight );
         list_del_init(&sdom->active_sdom_elem);
         csched_priv.weight -= sdom->weight;
+        csched_priv.percent -= sdom->percent;
     }
 }
 
@@ -579,6 +585,7 @@ csched_vcpu_init(struct vcpu *vc)
     svc->sdom = sdom;
     svc->vcpu = vc;
     atomic_set(&svc->credit, 0);
+    svc->prev_credit = 0;
     svc->flags = 0U;
     svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
     CSCHED_VCPU_STATS_RESET(svc);
@@ -712,25 +719,56 @@ csched_dom_cntl(
     {
         op->u.credit.weight = sdom->weight;
         op->u.credit.cap = sdom->cap;
+        op->u.credit.percent = sdom->percent;
     }
     else
     {
+        uint16_t weight = (uint16_t)~0U;
+
         ASSERT(op->cmd == XEN_DOMCTL_SCHEDOP_putinfo);
 
         spin_lock_irqsave(&csched_priv.lock, flags);
 
-        if ( op->u.credit.weight != 0 )
+        if ( (op->u.credit.weight != 0) &&
+             (sdom->percent == 0 || op->u.credit.percent == 0) )
+        {
+            weight = op->u.credit.weight;
+        }
+
+        if ( op->u.credit.cap != (uint16_t)~0U )
+            sdom->cap = op->u.credit.cap;
+
+        if ( (op->u.credit.percent != (uint16_t)~0U) &&
+             ((csched_priv.total_percent - sdom->percent +
+               op->u.credit.percent) <= 100 * csched_priv.ncpus) )
+        {
+            csched_priv.total_percent -= sdom->percent;
+            csched_priv.total_percent += op->u.credit.percent;
+
+            if ( !list_empty(&sdom->active_sdom_elem) )
+            {
+                csched_priv.percent -= sdom->percent;
+                csched_priv.percent += op->u.credit.percent;
+            }
+            sdom->percent = op->u.credit.percent;
+            if ( sdom->percent == 0 )
+            {
+                if ( sdom->weight == 0 )
+                    weight = CSCHED_DEFAULT_WEIGHT;
+            }
+            else
+                weight = 0;
+        }
+
+        if ( weight != (uint16_t)~0U )
         {
             if ( !list_empty(&sdom->active_sdom_elem) )
             {
                 csched_priv.weight -= sdom->weight;
-                csched_priv.weight += op->u.credit.weight;
+                csched_priv.weight += weight;
             }
-            sdom->weight = op->u.credit.weight;
-        }
-
-        if ( op->u.credit.cap != (uint16_t)~0U )
-            sdom->cap = op->u.credit.cap;
+            sdom->weight = weight;
+        }
 
         spin_unlock_irqrestore(&csched_priv.lock, flags);
     }
@@ -759,6 +797,7 @@ csched_dom_init(struct domain *dom)
     sdom->dom = dom;
     sdom->weight = CSCHED_DEFAULT_WEIGHT;
     sdom->cap = 0U;
+    sdom->percent = 0U;
     dom->sched_priv = sdom;
 
     return 0;
@@ -831,6 +870,7 @@ csched_acct(void)
     struct csched_dom *sdom;
     uint32_t credit_total;
     uint32_t weight_total;
+    uint32_t percent_credit;
     uint32_t weight_left;
     uint32_t credit_fair;
     uint32_t credit_peak;
@@ -857,6 +897,7 @@ csched_acct(void)
 
     weight_total = csched_priv.weight;
     credit_total = csched_priv.credit;
+    percent_credit = csched_priv.percent * CSCHED_CREDITS_PER_TSLICE / 100;
 
     /* Converge balance towards 0 when it drops negative */
     if ( csched_priv.credit_balance < 0 )
@@ -865,7 +906,7 @@ csched_acct(void)
         CSCHED_STAT_CRANK(acct_balance);
     }
 
-    if ( unlikely(weight_total == 0) )
+    if ( unlikely(weight_total == 0 && percent_credit == 0) )
     {
         csched_priv.credit_balance = 0;
         spin_unlock_irqrestore(&csched_priv.lock, flags);
@@ -880,22 +921,44 @@ csched_acct(void)
     credit_xtra = 0;
     credit_cap = 0U;
 
+    /* Firstly, subtract percent_credit from credit_total. */
+    if ( percent_credit != 0 )
+    {
+        credit_total -= percent_credit;
+        credit_balance += percent_credit;
+    }
+
+    /* Avoid 0 divide error */
+    if ( weight_total == 0 )
+        weight_total = 1;
+
     list_for_each_safe( iter_sdom, next_sdom, &csched_priv.active_sdom )
     {
         sdom = list_entry(iter_sdom, struct csched_dom, active_sdom_elem);
 
         BUG_ON( is_idle_domain(sdom->dom) );
         BUG_ON( sdom->active_vcpu_count == 0 );
-        BUG_ON( sdom->weight == 0 );
+        BUG_ON( sdom->weight == 0 && sdom->percent == 0 );
         BUG_ON( sdom->weight > weight_left );
 
-        /* Compute the average of active VCPUs. */
+        /*
+         * Compute the average of active VCPUs
+         * and adjust credit for comsumption too much.
+         */
         credit_sum = 0;
         list_for_each_safe( iter_vcpu, next_vcpu, &sdom->active_vcpu )
         {
+            int adjust;
+
             svc = list_entry(iter_vcpu, struct csched_vcpu, active_vcpu_elem);
             BUG_ON( sdom != svc->sdom );
 
+            credit = atomic_read(&svc->credit);
+            adjust = svc->prev_credit - credit - CSCHED_CREDITS_PER_TSLICE;
+            if ( adjust > 0 )
+            {
+                atomic_add(adjust, &svc->credit);
+            }
             credit_sum += atomic_read(&svc->credit);
         }
         credit_average = ( credit_sum + (sdom->active_vcpu_count - 1)
@@ -934,7 +997,9 @@ csched_acct(void)
 
         if ( credit_fair < credit_peak )
         {
-            credit_xtra = 1;
+            /* credit_fair is 0 if weight is 0. */
+            if ( sdom->weight != 0 )
+                credit_xtra = 1;
         }
         else
         {
@@ -963,9 +1028,9 @@ csched_acct(void)
         }
 
         /* Compute fair share per VCPU */
+        credit_fair += (sdom->percent * CSCHED_CREDITS_PER_ACCT)/100;
         credit_fair = ( credit_fair + ( sdom->active_vcpu_count - 1 )
                       ) / sdom->active_vcpu_count;
-
 
         list_for_each_safe( iter_vcpu, next_vcpu, &sdom->active_vcpu )
         {
@@ -1029,6 +1094,9 @@ csched_acct(void)
                 }
             }
 
+            /* save credit for adjustment */
+            svc->prev_credit = credit;
+
             CSCHED_VCPU_STAT_SET(svc, credit_last, credit);
             CSCHED_VCPU_STAT_SET(svc, credit_incr, credit_fair);
             credit_balance += credit;
@@ -1282,7 +1350,10 @@ csched_dump_vcpu(struct csched_vcpu *svc
 
     if ( sdom )
     {
-        printk(" credit=%i [w=%u]", atomic_read(&svc->credit), sdom->weight);
+        printk(" credit=%i [w=%u,p=%u]",
+               atomic_read(&svc->credit),
+               sdom->weight,
+               sdom->percent);
 #ifdef CSCHED_STATS
         printk(" (%d+%u) {a/i=%u/%u m=%u+%u}",
                 svc->stats.credit_last,
@@ -1348,6 +1419,8 @@ csched_dump(void)
            "\tcredit balance     = %d\n"
            "\tweight             = %u\n"
            "\trunq_sort          = %u\n"
+           "\tpercent            = %u\n"
+           "\ttotal_percent      = %u\n"
            "\tdefault-weight     = %d\n"
            "\tmsecs per tick     = %dms\n"
            "\tcredits per tick   = %d\n"
@@ -1359,6 +1432,8 @@ csched_dump(void)
            csched_priv.credit_balance,
            csched_priv.weight,
            csched_priv.runq_sort,
+           csched_priv.percent,
+           csched_priv.total_percent,
            CSCHED_DEFAULT_WEIGHT,
            CSCHED_MSECS_PER_TICK,
            CSCHED_CREDITS_PER_TICK,
@@ -1412,6 +1487,8 @@ csched_init(void)
     csched_priv.credit = 0U;
     csched_priv.credit_balance = 0;
     csched_priv.runq_sort = 0U;
+    csched_priv.percent = 0;
+    csched_priv.total_percent = 0;
     CSCHED_STATS_RESET();
 }
 
xen/include/public/domctl.h +1 -0
diff -r 56032cbaf1e8 xen/include/public/domctl.h
@@ -311,6 +311,7 @@ struct xen_domctl_scheduler_op {
         struct xen_domctl_sched_credit {
             uint16_t weight;
             uint16_t cap;
+            uint16_t percent;
         } credit;
     } u;
 };
tools/python/xen/lowlevel/xc/xc.c +14 -6
diff -r 56032cbaf1e8 tools/python/xen/lowlevel/xc/xc.c
@@ -1285,18 +1285,21 @@ static PyObject *pyxc_sched_credit_domai
     uint32_t domid;
     uint16_t weight;
     uint16_t cap;
-    static char *kwd_list[] = { "domid", "weight", "cap", NULL };
-    static char kwd_type[] = "I|HH";
+    uint16_t percent;
+    static char *kwd_list[] = { "domid", "weight", "cap", "percent", NULL };
+    static char kwd_type[] = "I|HHh";
     struct xen_domctl_sched_credit sdom;
     
     weight = 0;
     cap = (uint16_t)~0U;
+    percent = (uint16_t)~0U;
     if( !PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list, 
-                                     &domid, &weight, &cap) )
+                                     &domid, &weight, &cap, &percent) )
         return NULL;
 
     sdom.weight = weight;
     sdom.cap = cap;
+    sdom.percent = percent;
 
     if ( xc_sched_credit_domain_set(self->xc_handle, domid, &sdom) != 0 )
         return pyxc_error_to_exception();
@@ -1316,9 +1319,10 @@ static PyObject *pyxc_sched_credit_domai
     if ( xc_sched_credit_domain_get(self->xc_handle, domid, &sdom) != 0 )
         return pyxc_error_to_exception();
 
-    return Py_BuildValue("{s:H,s:H}",
+    return Py_BuildValue("{s:H,s:H,s:i}",
                          "weight",  sdom.weight,
-                         "cap",     sdom.cap);
+                         "cap",     sdom.cap,
+                         "percent", sdom.percent);
 }
 
 static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args)
@@ -1744,6 +1748,8 @@ static PyMethodDef pyxc_methods[] = {
       "SMP credit scheduler.\n"
       " domid     [int]:   domain id to set\n"
       " weight    [short]: domain's scheduling weight\n"
+      " cap       [short]: cap\n"
+      " percent   [short]; domain's scheduling percentage per a cpu\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
     { "sched_credit_domain_get",
@@ -1753,7 +1759,9 @@ static PyMethodDef pyxc_methods[] = {
       "SMP credit scheduler.\n"
       " domid     [int]:   domain id to get\n"
       "Returns:   [dict]\n"
-      " weight    [short]: domain's scheduling weight\n"},
+      " weight    [short]: domain's scheduling weight\n"
+      " cap       [short]: cap\n"
+      " percent   [short]: domain's scheduling percentage per a cpu\n"},
 
     { "evtchn_alloc_unbound", 
       (PyCFunction)pyxc_evtchn_alloc_unbound,
tools/python/xen/xend/XendAPI.py +4 -2
diff -r 56032cbaf1e8 tools/python/xen/xend/XendAPI.py
@@ -1505,10 +1505,12 @@ class XendAPI(object):
 
         #need to update sched params aswell
         if 'weight' in xeninfo.info['vcpus_params'] \
-           and 'cap' in xeninfo.info['vcpus_params']:
+           and 'cap' in xeninfo.info['vcpus_params'] \
+           and 'percent' in xeninfo.info['vcpus_params']:
             weight = xeninfo.info['vcpus_params']['weight']
             cap = xeninfo.info['vcpus_params']['cap']
-            xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap)
+            percent = xeninfo.info['vcpus_params']['percent']
+            xendom.domain_sched_credit_set(xeninfo.getDomid(), weight, cap, percent)
 
     def VM_set_VCPUs_number_live(self, _, vm_ref, num):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
tools/python/xen/xend/XendConfig.py +2 -0
diff -r 56032cbaf1e8 tools/python/xen/xend/XendConfig.py
@@ -591,6 +591,8 @@ class XendConfig(dict):
             int(sxp.child_value(sxp_cfg, "cpu_weight", 256))
         cfg["vcpus_params"]["cap"] = \
             int(sxp.child_value(sxp_cfg, "cpu_cap", 0))
+        cfg["vcpus_params"]["percent"] = \
+            int(sxp.child_value(sxp_cfg, "cpu_percent", 0))
 
         # Only extract options we know about.
         extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \
tools/python/xen/xend/XendDomain.py +17 -4
diff -r 56032cbaf1e8 tools/python/xen/xend/XendDomain.py
@@ -1536,7 +1536,7 @@ class XendDomain:
 
         @param domid: Domain ID or Name
         @type domid: int or string.
-        @rtype: dict with keys 'weight' and 'cap'
+        @rtype: dict with keys 'weight' and 'cap' and 'percent'
         @return: credit scheduler parameters
         """
         dominfo = self.domain_lookup_nr(domid)
@@ -1550,19 +1550,22 @@ class XendDomain:
                 raise XendError(str(ex))
         else:
             return {'weight' : dominfo.getWeight(),
-                    'cap'    : dominfo.getCap()} 
+                    'cap'    : dominfo.getCap(),
+                    'percent': dominfo.getPercent()} 
     
-    def domain_sched_credit_set(self, domid, weight = None, cap = None):
+    def domain_sched_credit_set(self, domid, weight = None, cap = None, percent = None):
         """Set credit scheduler parameters for a domain.
 
         @param domid: Domain ID or Name
         @type domid: int or string.
         @type weight: int
         @type cap: int
+        @type percent: int
         @rtype: 0
         """
         set_weight = False
         set_cap = False
+        set_percent = False
         dominfo = self.domain_lookup_nr(domid)
         if not dominfo:
             raise XendInvalidDomain(str(domid))
@@ -1581,17 +1584,27 @@ class XendDomain:
             else:
                 set_cap = True
 
+            if percent is None:
+                percent = int(~0)
+            elif percent < 0:
+                raise XendError("percent is out of range")
+            else:
+                set_percent = True
+
             assert type(weight) == int
             assert type(cap) == int
+            assert type(percent) == int
 
             rc = 0
             if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED):
-                rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap)
+                rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap, percent)
             if rc == 0:
                 if set_weight:
                     dominfo.setWeight(weight)
                 if set_cap:
                     dominfo.setCap(cap)
+                if set_percent:
+                    dominfo.setPercent(percent)
                 self.managed_config_save(dominfo)
             return rc
         except Exception, ex:
tools/python/xen/xend/XendDomainInfo.py +8 -1
diff -r 56032cbaf1e8 tools/python/xen/xend/XendDomainInfo.py
@@ -467,7 +467,8 @@ class XendDomainInfo:
                 if xennode.xenschedinfo() == 'credit':
                     xendomains.domain_sched_credit_set(self.getDomid(),
                                                        self.getWeight(),
-                                                       self.getCap())
+                                                       self.getCap(),
+                                                       self.getPercent())
             except:
                 log.exception('VM start failed')
                 self.destroy()
@@ -1705,6 +1706,12 @@ class XendDomainInfo:
     def setWeight(self, cpu_weight):
         self.info['vcpus_params']['weight'] = cpu_weight
 
+    def getPercent(self):
+        return self.info['vcpus_params']['percent']
+
+    def setPercent(self, cpu_percent):
+        self.info['vcpus_params']['percent'] = cpu_percent
+
     def getRestartCount(self):
         return self._readVm('xend/restart_count')
 
tools/python/xen/xm/main.py +23 -10
diff -r 56032cbaf1e8 tools/python/xen/xm/main.py
@@ -150,7 +150,7 @@ SUBCOMMAND_HELP = {
     'log'         : ('', 'Print Xend log'),
     'rename'      : ('<Domain> <NewDomainName>', 'Rename a domain.'),
     'sched-sedf'  : ('<Domain> [options]', 'Get/set EDF parameters.'),
-    'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
+    'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]|-p[=PERCENT]]]',
                      'Get/set credit scheduler parameters.'),
     'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
     'debug-keys'  : ('<Keys>', 'Send debug keys to Xen.'),
@@ -240,6 +240,7 @@ SUBCOMMAND_OPTIONS = {
        ('-d DOMAIN', '--domain=DOMAIN', 'Domain to modify'),
        ('-w WEIGHT', '--weight=WEIGHT', 'Weight (int)'),
        ('-c CAP',    '--cap=CAP',       'Cap (int)'),
+       ('-p PERCENT', '--percent=PERCENT', 'Percent per a cpu (int)'),
     ),
     'list': (
        ('-l', '--long',         'Output all VM details in SXP'),
@@ -1578,8 +1579,8 @@ def xm_sched_credit(args):
     check_sched_type('credit')
 
     try:
-        opts, params = getopt.getopt(args, "d:w:c:",
-            ["domain=", "weight=", "cap="])
+        opts, params = getopt.getopt(args, "d:w:c:p:",
+            ["domain=", "weight=", "cap=", "percent="])
     except getopt.GetoptError, opterr:
         err(opterr)
         usage('sched-credit')
@@ -1587,6 +1588,7 @@ def xm_sched_credit(args):
     domid = None
     weight = None
     cap = None
+    percent = None
 
     for o, a in opts:
         if o in ["-d", "--domain"]:
@@ -1594,18 +1596,20 @@ def xm_sched_credit(args):
         elif o in ["-w", "--weight"]:
             weight = int(a)
         elif o in ["-c", "--cap"]:
-            cap = int(a);
+            cap = int(a)
+        elif o in ["-p", "--percent"]:
+            percent = int(a);
 
     doms = filter(lambda x : domid_match(domid, x),
                   [parse_doms_info(dom)
                   for dom in getDomains(None, 'all')])
 
-    if weight is None and cap is None:
+    if weight is None and cap is None and percent is None:
         if domid is not None and doms == []: 
             err("Domain '%s' does not exist." % domid)
             usage('sched-credit')
         # print header if we aren't setting any parameters
-        print '%-33s %4s %6s %4s' % ('Name','ID','Weight','Cap')
+        print '%-33s %4s %6s %4s %7s' % ('Name','ID','Weight','Cap','Percent')
         
         for d in doms:
             try:
@@ -1618,16 +1622,17 @@ def xm_sched_credit(args):
             except xmlrpclib.Fault:
                 pass
 
-            if 'weight' not in info or 'cap' not in info:
+            if 'weight' not in info or 'cap' not in info or 'percent' not in info:
                 # domain does not support sched-credit?
-                info = {'weight': -1, 'cap': -1}
+                info = {'weight': -1, 'cap': -1, 'percent':-1}
 
             info['weight'] = int(info['weight'])
             info['cap']    = int(info['cap'])
+            info['percent'] = int(info['percent'])
             
             info['name']  = d['name']
             info['domid'] = str(d['domid'])
-            print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d") % info)
+            print( ("%(name)-32s %(domid)5s %(weight)6d %(cap)4d %(percent)6d") % info)
     else:
         if domid is None:
             # place holder for system-wide scheduler parameters
@@ -1644,6 +1649,10 @@ def xm_sched_credit(args):
                     get_single_vm(domid),
                     "cap",
                     cap)
+                server.xenapi.VM.add_to_VCPUs_params_live(
+                    get_single_vm(domid),
+                    "percent",
+                    percent)
             else:
                 server.xenapi.VM.add_to_VCPUs_params(
                     get_single_vm(domid),
@@ -1653,8 +1662,12 @@ def xm_sched_credit(args):
                     get_single_vm(domid),
                     "cap",
                     cap)
+                server.xenapi.VM.add_to_VCPUs_params(
+                    get_single_vm(domid),
+                    "percent",
+                    percent)
         else:
-            result = server.xend.domain.sched_credit_set(domid, weight, cap)
+            result = server.xend.domain.sched_credit_set(domid, weight, cap, percent)
             if result != 0:
                 err(str(result))
 
xen/common/sched_credit.c +18 -1
diff -r 116e2691c071 xen/common/sched_credit.c
@@ -47,6 +47,7 @@
     (CSCHED_CREDITS_PER_TICK * CSCHED_TICKS_PER_TSLICE)
 #define CSCHED_CREDITS_PER_ACCT     \
     (CSCHED_CREDITS_PER_TICK * CSCHED_TICKS_PER_ACCT)
+#define CSCHED_MSECS_PER_BOOST_TSLICE 2
 
 
 /*
@@ -245,6 +246,7 @@ struct csched_private {
     uint16_t total_percent;
     int credit_balance;
     uint32_t runq_sort;
+    s_time_t boost_tslice;
     CSCHED_STATS_DEFINE()
 };
 
@@ -253,6 +255,10 @@ struct csched_private {
  * Global variables
  */
 static struct csched_private csched_priv;
+
+/* opt_credit_tslice: time slice for BOOST priority */
+static unsigned int opt_credit_tslice = CSCHED_MSECS_PER_BOOST_TSLICE;
+integer_param("credit_tslice", opt_credit_tslice);
 
 static void csched_tick(void *_cpu);
 
@@ -1327,7 +1333,17 @@ csched_schedule(s_time_t now)
     /*
      * Return task to run next...
      */
-    ret.time = MILLISECS(CSCHED_MSECS_PER_TSLICE);
+    if ( snext->pri == CSCHED_PRI_TS_BOOST )
+    {
+        struct csched_vcpu * const svc = __runq_elem(runq->next);
+
+        if ( svc->pri == CSCHED_PRI_TS_BOOST )
+            ret.time = csched_priv.boost_tslice;
+        else
+            ret.time = MILLISECS(CSCHED_MSECS_PER_TICK);
+    }
+    else
+        ret.time = MILLISECS(CSCHED_MSECS_PER_TSLICE);
     ret.task = snext->vcpu;
 
     spc->start_time = now;
@@ -1489,6 +1505,7 @@ csched_init(void)
     csched_priv.runq_sort = 0U;
     csched_priv.percent = 0;
     csched_priv.total_percent = 0;
+    csched_priv.boost_tslice = MILLISECS(opt_credit_tslice);
     CSCHED_STATS_RESET();
 }
 
xen/common/sched_credit.c +26 -10
diff -r 64618a20b9de xen/common/sched_credit.c
@@ -202,6 +202,7 @@ struct csched_vcpu {
     struct csched_dom *sdom;
     struct vcpu *vcpu;
     atomic_t credit;
+    atomic_t boost_credit;
     int prev_credit;
     uint16_t flags;
     int16_t pri;
@@ -549,14 +550,6 @@ csched_vcpu_acct(unsigned int cpu)
     ASSERT( svc->sdom != NULL );
 
     /*
-     * If this VCPU's priority was boosted when it last awoke, reset it.
-     * If the VCPU is found here, then it's consuming a non-negligeable
-     * amount of CPU resources and should no longer be boosted.
-     */
-    if ( svc->pri == CSCHED_PRI_TS_BOOST )
-        svc->pri = CSCHED_PRI_TS_UNDER;
-
-    /*
      * If it's been active a while, check if we'd be better off
      * migrating it to run elsewhere (see multi-core and multi-thread
      * support in csched_cpu_pick()).
@@ -591,6 +584,7 @@ csched_vcpu_init(struct vcpu *vc)
     svc->sdom = sdom;
     svc->vcpu = vc;
     atomic_set(&svc->credit, 0);
+    atomic_set(&svc->boost_credit, 0);
     svc->prev_credit = 0;
     svc->flags = 0U;
     svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
@@ -706,6 +700,8 @@ csched_vcpu_wake(struct vcpu *vc)
          !(svc->flags & CSCHED_FLAG_VCPU_PARKED) )
     {
         svc->pri = CSCHED_PRI_TS_BOOST;
+        atomic_add(CSCHED_CREDITS_PER_TICK, &svc->boost_credit);
+        atomic_sub(CSCHED_CREDITS_PER_TICK, &svc->credit);
     }
 
     /* Put the VCPU on the runq and tickle CPUs */
@@ -954,11 +950,14 @@ csched_acct(void)
         credit_sum = 0;
         list_for_each_safe( iter_vcpu, next_vcpu, &sdom->active_vcpu )
         {
-            int adjust;
+            int adjust, boost_credit;
 
             svc = list_entry(iter_vcpu, struct csched_vcpu, active_vcpu_elem);
             BUG_ON( sdom != svc->sdom );
 
+            boost_credit = atomic_read(&svc->boost_credit);
+            atomic_set(&svc->boost_credit, 0);
+            atomic_add(boost_credit, &svc->credit);
             credit = atomic_read(&svc->credit);
             adjust = svc->prev_credit - credit - CSCHED_CREDITS_PER_TSLICE;
             if ( adjust > 0 )
@@ -1290,6 +1289,22 @@ csched_schedule(s_time_t now)
                ) /
                ( MILLISECS(CSCHED_MSECS_PER_TSLICE) /
                  CSCHED_CREDITS_PER_TSLICE );
+    if ( scurr->pri == CSCHED_PRI_TS_BOOST )
+    {
+        int boost_credit = atomic_read(&scurr->boost_credit);
+
+        if ( boost_credit > consumed )
+        {
+            atomic_sub(consumed, &scurr->boost_credit);
+            consumed = 0;
+        }
+        else
+        {
+            atomic_sub(boost_credit, &scurr->boost_credit);
+            consumed -= boost_credit;
+            scurr->pri = CSCHED_PRI_TS_UNDER;
+        }
+    }
     if ( consumed > 0 && !is_idle_vcpu(current) )
         atomic_sub(consumed, &scurr->credit);
 
@@ -1366,8 +1381,9 @@ csched_dump_vcpu(struct csched_vcpu *svc
 
     if ( sdom )
     {
-        printk(" credit=%i [w=%u,p=%u]",
+        printk(" credit=%i bc=%i [w=%u,p=%u]",
                atomic_read(&svc->credit),
+               atomic_read(&svc->boost_credit),
                sdom->weight,
                sdom->percent);
 #ifdef CSCHED_STATS

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel