[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


 


Rackspace

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