diff -r 56032cbaf1e8 xen/common/sched_credit.c --- a/xen/common/sched_credit.c Thu Jan 22 10:43:50 2009 +0900 +++ b/xen/common/sched_credit.c Thu Jan 22 13:06:24 2009 +0900 @@ -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(); } diff -r 56032cbaf1e8 xen/include/public/domctl.h --- a/xen/include/public/domctl.h Thu Jan 22 10:43:50 2009 +0900 +++ b/xen/include/public/domctl.h Thu Jan 22 13:06:24 2009 +0900 @@ -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; };