[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/2] credit2: Reset until the front of the runqueue is positive
>>> On 08.03.13 at 16:04, George Dunlap <george.dunlap@xxxxxxxxxxxxx> wrote: > On 08/03/13 14:35, Jan Beulich wrote: >>>>> On 08.03.13 at 15:14, George Dunlap <george.dunlap@xxxxxxxxxxxxx> wrote: >>> 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. >>> >>> Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> >>> --- >>> xen/common/sched_credit2.c | 81 >>> +++++++++++++++++++++++++++----------------- >>> 1 file changed, 49 insertions(+), 32 deletions(-) >>> >>> diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c >>> index 5bf5ebc..7265d5b 100644 >>> --- a/xen/common/sched_credit2.c >>> +++ b/xen/common/sched_credit2.c >>> @@ -588,41 +588,58 @@ 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; >>> >>> - list_for_each( iter, &rqd->svc ) >>> - { >>> - struct csched_vcpu * svc = list_entry(iter, struct csched_vcpu, >>> rqd_elem); >>> - >>> - int start_credit; >>> - >>> - BUG_ON( is_idle_vcpu(svc->vcpu) ); >>> - BUG_ON( svc->rqd != rqd ); >>> - >>> - start_credit = svc->credit; >>> - >>> - /* "Clip" credits to max carryover */ >>> - if ( svc->credit > CSCHED_CARRYOVER_MAX ) >>> - svc->credit = CSCHED_CARRYOVER_MAX; >>> - /* And add INIT */ >>> - svc->credit += CSCHED_CREDIT_INIT; >>> - svc->start_time = now; >>> - >>> - /* TRACE */ { >>> - struct { >>> - unsigned dom:16,vcpu:16; >>> - unsigned credit_start, credit_end; >>> - } d; >>> - d.dom = svc->vcpu->domain->domain_id; >>> - d.vcpu = svc->vcpu->vcpu_id; >>> - d.credit_start = start_credit; >>> - d.credit_end = svc->credit; >>> - trace_var(TRC_CSCHED2_CREDIT_RESET, 1, >>> - sizeof(d), >>> - (unsigned char *)&d); >>> + /* >>> + * 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. >>> + */ >>> + while (snext->credit <= CSCHED_CREDIT_RESET ) { >> So how long can this loop last? Can't you get away with a loop >> altogether, considering that you only add CSCHED_CREDIT_INIT >> inside the loop? > > I'm not sure what you mean? > > The point of doing the whole loop over is to make sure that everyone > gets the same number of CSCHED_CREDIT_INITs added. > > While testing this I saw a couple of instances where it did the loop 20 > times; the vast majority of the times it went around mutliple times it > only went twice. > > I suppose we could do something like this: > > if(snext->credit < -CSCHED_CREDIT_INIT) { > x = (-snext->credit)/CSCHED_CREDIT_INIT; > } else { > x = 1; > } > > Then add (x * CSCHED_CREDIT_INIT) to each one. Then in the common case > we're not doing any integer division, but in the uncommon case we have a > bounded algorithm. Does that sound better? Yes, it was something along those lines that I was hoping to get. The division still seems better than perhaps quite a few iterations of the loop. >> Also, I hope there is some sort of guarantee that snext gets >> updated by the loop in the first place. > > The inner loop iterates over the list of all vcpus assigned to this > runqueue, whether or not they are actually on the current "queue" (i.e., > runnable and waiting for the cpu) or not. snext was just taken from the > top the queue, so it should be on that list. > > Unfortunately there's not a simple ASSERT() we can add to make sure that > snext is actually in that list; we can only ASSERT that the runqueue of > snext->cpu is this runqueue. But if we're trying to check whether the > invariants are being upheld, there's no sense in assuming one of the > invariants we're trying to check. > > But if we go the "multiplier" route this whole question disappears. Indeed. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |