aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Dunlap <george.dunlap@eu.citrix.com>2013-03-11 09:57:11 +0100
committerJan Beulich <jbeulich@suse.com>2013-03-11 09:57:11 +0100
commit4e98fd591232d33b1a3785fe1e5e1361955d9d90 (patch)
tree43dd953fd16f3147ba0cc7eccbaddeae8cd30e62
parent582ea94410cb266bbf3cd308046f5ea8ae25055f (diff)
downloadxen-4e98fd591232d33b1a3785fe1e5e1361955d9d90.tar.gz
xen-4e98fd591232d33b1a3785fe1e5e1361955d9d90.tar.bz2
xen-4e98fd591232d33b1a3785fe1e5e1361955d9d90.zip
credit2: Reset until the front of the runqueue is positive
Under normal circumstances, snext->credit should never be less than -CSCHED_MIN_TIMER. However, under some circumstances, a vcpu with low credits may be allowed to run long enough that its credits are actually less than -CSCHED_CREDIT_INIT. (Instances have been observed, for example, where a vcpu with 200us of credit was allowed to run for 11ms, giving it -10.8ms of credit. Thus it was still negative even after the reset.) If this is the case for snext, we simply want to keep moving everyone up until it is in the black again. This fair because none of the other vcpus want to run at the moment. Rather than loop, just detect how many times we want to add CSCHED_CREDIT_INIT. Try to avoid integer divides and multiplies in the common case. Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
-rw-r--r--xen/common/sched_credit2.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 03814b7468..825ec986e5 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -588,38 +588,70 @@ no_tickle:
/*
* Credit-related code
*/
-static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now)
+static void reset_credit(const struct scheduler *ops, int cpu, s_time_t now,
+ struct csched_vcpu *snext)
{
struct csched_runqueue_data *rqd = RQD(ops, cpu);
struct list_head *iter;
+ int m;
+
+ /*
+ * Under normal circumstances, snext->credit should never be less
+ * than -CSCHED_MIN_TIMER. However, under some circumstances, a
+ * vcpu with low credits may be allowed to run long enough that
+ * its credits are actually less than -CSCHED_CREDIT_INIT.
+ * (Instances have been observed, for example, where a vcpu with
+ * 200us of credit was allowed to run for 11ms, giving it -10.8ms
+ * of credit. Thus it was still negative even after the reset.)
+ *
+ * If this is the case for snext, we simply want to keep moving
+ * everyone up until it is in the black again. This fair because
+ * none of the other vcpus want to run at the moment.
+ *
+ * Rather than looping, however, we just calculate a multiplier,
+ * avoiding an integer division and multiplication in the common
+ * case.
+ */
+ m = 1;
+ if ( snext->credit < -CSCHED_CREDIT_INIT )
+ m += (-snext->credit) / CSCHED_CREDIT_INIT;
list_for_each( iter, &rqd->svc )
{
- struct csched_vcpu * svc = list_entry(iter, struct csched_vcpu, rqd_elem);
-
+ struct csched_vcpu * svc;
int start_credit;
+ svc = list_entry(iter, struct csched_vcpu, rqd_elem);
+
BUG_ON( is_idle_vcpu(svc->vcpu) );
BUG_ON( svc->rqd != rqd );
start_credit = svc->credit;
+ /* And add INIT * m, avoiding integer multiplication in the
+ * common case. */
+ if ( likely(m==1) )
+ svc->credit += CSCHED_CREDIT_INIT;
+ else
+ svc->credit += m * CSCHED_CREDIT_INIT;
+
/* "Clip" credits to max carryover */
- if ( svc->credit > CSCHED_CARRYOVER_MAX )
- svc->credit = CSCHED_CARRYOVER_MAX;
- /* And add INIT */
- svc->credit += CSCHED_CREDIT_INIT;
+ if ( svc->credit > CSCHED_CREDIT_INIT + CSCHED_CARRYOVER_MAX )
+ svc->credit = CSCHED_CREDIT_INIT + CSCHED_CARRYOVER_MAX;
+
svc->start_time = now;
/* TRACE */ {
struct {
unsigned dom:16,vcpu:16;
unsigned credit_start, credit_end;
+ unsigned multiplier;
} d;
d.dom = svc->vcpu->domain->domain_id;
d.vcpu = svc->vcpu->vcpu_id;
d.credit_start = start_credit;
d.credit_end = svc->credit;
+ d.multiplier = m;
trace_var(TRC_CSCHED2_CREDIT_RESET, 1,
sizeof(d),
(unsigned char *)&d);
@@ -1732,7 +1764,7 @@ csched_schedule(
/* Check for the reset condition */
if ( snext->credit <= CSCHED_CREDIT_RESET )
{
- reset_credit(ops, cpu, now);
+ reset_credit(ops, cpu, now, snext);
balance_load(ops, cpu, now);
}