Hey,

Here I am, sorry for the delay. :-(

On Mon, 2016-02-08 at 23:33 -0500, Tianyang Chen wrote:
> Changes since v4:
>     removed unnecessary replenishment queue checks in vcpu_wake()
>     extended replq_remove() to all cases in vcpu_sleep()
>     used _deadline_queue_insert() helper function for both queues
>     _replq_insert() and _replq_remove() program timer internally
> 
> Changes since v3:
>     removed running queue.
>     added repl queue to keep track of repl events.
>     timer is now per scheduler.
>     timer is init on a valid cpu in a cpupool.
> 
> Signed-off-by: Tianyang Chen <ti...@seas.upenn.edu>
> Signed-off-by: Meng Xu <men...@cis.upenn.edu>
> Signed-off-by: Dagaen Golomb <dgol...@seas.upenn.edu>
>
So, the actual changelog... why did it disappear? :-)

> diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c
> index 2e5430f..1f0bb7b 100644
> --- a/xen/common/sched_rt.c
> +++ b/xen/common/sched_rt.c

> @@ -388,6 +424,66 @@ __q_remove(struct rt_vcpu *svc)
>  }
>  
>  /*
> + * Removing a vcpu from the replenishment queue could
> + * re-program the timer for the next replenishment event
> + * if the timer is currently active
> + */
> +static inline void
> +__replq_remove(const struct scheduler *ops, struct rt_vcpu *svc)
> +{
> +    struct rt_private *prv = rt_priv(ops);
> +    struct list_head *replq = rt_replq(ops);
> +    struct timer* repl_timer = prv->repl_timer;
> +
> +    if ( __vcpu_on_replq(svc) )
> +    {
So, can this be false? If yes, when and why?

> +        /*
> +         * disarm the timer if removing the first replenishment
> event
> +         * which is going to happen next
> +         */
> +        if( active_timer(repl_timer) )
> +        {
>
And here again, isn't it the case that, if there is a vcpu in the
replenishment queue, then the timer _must_ be active? (I.e., if the
above is true, isn't this also always true?)

> +            struct rt_vcpu *next_repl = __replq_elem(replq->next);
> +
> +            if( next_repl->cur_deadline == svc->cur_deadline )
> +                repl_timer->expires = 0;
> +
I think we need to call stop_timer() here, don't we? I know that
set_timer() does that itself, but I think it is indeed necessary. E.g.,
right now, you're manipulating the timer without the timer lock.

> +            list_del_init(&svc->replq_elem);
> +
> +            /* re-arm the timer for the next replenishment event */
> +            if( !list_empty(replq) )
> +            {
> +                struct rt_vcpu *svc_next = __replq_elem(replq-
> >next);
> +                set_timer(repl_timer, svc_next->cur_deadline);
> +            }
> +        }
> +
> +        else
> +            list_del_init(&svc->replq_elem);
>
I don't like the structure of this function, and I'd ask for a
different if/then/else logic to be used, but let's first see --by
answering the questions above-- if some of these if-s can actually go
away. :-)

> +    }
> +}
> +
> +/*
> + * An utility function that inserts a vcpu to a
> + * queue based on certain order (EDF)
>
End long comments with a full stop.

> + */
> +static void
> +_deadline_queue_insert(struct rt_vcpu * (*_get_q_elem)(struct
> list_head *elem),
>
There's really a lot of "underscore-prefixing" in this file.

This is, of course, not your fault, and should not be addressed in this
patch. But, at least when it comes to new code, let's avoid making
things worse.

So, "deadline_queue_insert()" is just ok, I think. Yes, I know I did
suggest to call it how it's called in this patch, underscore included,
but I now think it would be better to get rid of that.

> +    struct rt_vcpu *svc, struct list_head *elem, struct list_head
> *queue)
> +{
> +    struct list_head *iter;
> +
> +    list_for_each(iter, queue)
> +    {
> +        struct rt_vcpu * iter_svc = (*_get_q_elem)(iter);
> +        if ( svc->cur_deadline <= iter_svc->cur_deadline )
> +                break;
>
This looks too much indented.

> @@ -405,22 +500,37 @@ __runq_insert(const struct scheduler *ops,
> struct rt_vcpu *svc)
>  
>      /* add svc to runq if svc still has budget */
>      if ( svc->cur_budget > 0 )
> -    {
> -        list_for_each(iter, runq)
> -        {
> -            struct rt_vcpu * iter_svc = __q_elem(iter);
> -            if ( svc->cur_deadline <= iter_svc->cur_deadline )
> -                    break;
> -         }
> -        list_add_tail(&svc->q_elem, iter);
> -    }
> +        _deadline_queue_insert(&__q_elem, svc, &svc->q_elem, runq);
>      else
> -    {
>          list_add(&svc->q_elem, &prv->depletedq);
> -    }
Can we ASSERT() something about a replenishment event being queued, in
either case?

As I said already, use full words in comments ("Insert svc in the
replenishment timer queue" or "Insert svc in the replenishment events
list").

> + * vcpus that needs to be repl earlier go first.
>
Ditto. And this can just be something like "in replenishment time
order", added to the sentence above.

> + * scheduler private lock serializes this operation
>
This is true for _everything_ in this scheduler right now, so there's
no real need to say it.

> + * it could re-program the timer if it fires later than
> + * this vcpu's cur_deadline. 
>
Do you mean "The timer may be re-programmed if svc is inserted at the
front of the events list" ?

> Also, this is used to program
> + * the timer for the first time.
>
"Also, this is what programs the timer the first time, when called from
xxx"

> + */
> +static void
> +__replq_insert(const struct scheduler *ops, struct rt_vcpu *svc)
> +{
> +    struct list_head *replq = rt_replq(ops);
> +    struct rt_private *prv = rt_priv(ops);
> +    struct timer *repl_timer = prv->repl_timer;
> +
> +    ASSERT( !__vcpu_on_replq(svc) );
> +
> +    _deadline_queue_insert(&__replq_elem, svc, &svc->replq_elem,
> replq);
> +
> +    if( repl_timer->expires == 0 ||
> +        ( active_timer(repl_timer) && repl_timer->expires > svc-
> >cur_deadline ) )
> +        set_timer(repl_timer,svc->cur_deadline);
>
Is it the case that you need to call set_timer() if (and only if) svc
has been inserted at the *front* of the replenishment queue? (If list
was empty, as in the case of first timer activation, it would be the
first and only.)

If that is the case, I'd just make deadline_queue_insert() return a
flag to that effect (e.g., it can return 1 if svc is the new first
element, 0 if it is not), and use the flag itself to guard the (re-)arm 
of the timer... What do you think?

> @@ -651,6 +785,10 @@ rt_vcpu_remove(const struct scheduler *ops,
> struct vcpu *vc)
>      lock = vcpu_schedule_lock_irq(vc);
>      if ( __vcpu_on_q(svc) )
>          __q_remove(svc);
> +
> +    if( __vcpu_on_replq(svc) )
> +        __replq_remove(ops,svc);
> +
As per the code in this patch looks like, you're
checking __vcpu_on_replq(svc) twice. In fact, you do it here and inside
__replq_remove(). I've already said that I'd like for the check inside
__rqplq_remove() to go away so, keep this one here (if it's really
necessary) and kill the other one inside the function.

> @@ -924,6 +1027,9 @@ rt_vcpu_sleep(const struct scheduler *ops,
> struct vcpu *vc)
>          __q_remove(svc);
>      else if ( svc->flags & RTDS_delayed_runq_add )
>          clear_bit(__RTDS_delayed_runq_add, &svc->flags);
> +
> +    if( __vcpu_on_replq(svc) )
> +        __replq_remove(ops, svc);
>
Same here.

> @@ -1051,6 +1153,18 @@ rt_vcpu_wake(const struct scheduler *ops,
> struct vcpu *vc)
>      else
>          SCHED_STAT_CRANK(vcpu_wake_not_runnable);
>  
> +    /* budget repl here is needed before inserting back to runq. If
> so,
>
Comment style.

Also, what do you mean with that "If so"... "If so" what?
> +     * it should be re-inserted back to the replenishment queue.
> +     */
> +    if ( now >= svc->cur_deadline)
> +    {   
> +        rt_update_deadline(now, svc);
> +        __replq_remove(ops, svc);
> +    }
> +
> +    if( !__vcpu_on_replq(svc) )
> +        __replq_insert(ops, svc);
> +    
And here I am again: is it really necessary to check whether svc is not
in the replenishment queue? It looks to me that it really should not be
there... but maybe it can, because we remove the event from the queue
when the vcpu sleeps, but *not* when the vcpu blocks?

> @@ -1168,6 +1259,80 @@ rt_dom_cntl(
>      return rc;
>  }
>  
> +/*
> + * The replenishment timer handler picks vcpus
> + * from the replq and does the actual replenishment
> + */
> +static void repl_handler(void *data){
> +    unsigned long flags;
> +    s_time_t now = NOW();
> +    struct scheduler *ops = data; 
> +    struct rt_private *prv = rt_priv(ops);
> +    struct list_head *replq = rt_replq(ops);
> +    struct timer *repl_timer = prv->repl_timer;
> +    struct list_head *iter, *tmp;
> +    struct rt_vcpu *svc = NULL;
> +
> +    spin_lock_irqsave(&prv->lock, flags);
> +
> +    stop_timer(repl_timer);
> +
> +    list_for_each_safe(iter, tmp, replq)
> +    {
> +        svc = __replq_elem(iter);
> +
> +        if ( now >= svc->cur_deadline )
> +        {
> +            rt_update_deadline(now, svc);
> +
> +            /*
> +             * when the replenishment happens
> +             * svc is either on a pcpu or on
> +             * runq/depletedq
> +             */
> +            if( __vcpu_on_q(svc) )
> +            {
> +                /* put back to runq */
> +                __q_remove(svc);
> +                __runq_insert(ops, svc);
> +            }
> +
> +            /* 
> +             * tickle regardless where it's at 
> +             * because a running vcpu could have
> +             * a later deadline than others after
> +             * replenishment
> +             */
> +            runq_tickle(ops, svc);
> +
> +            /* update replenishment event queue */
> +            __replq_remove(ops, svc);
> +            __replq_insert(ops, svc);
> +        }
> +
> +        else
> +            break;
>
Invert the logic here:

    if ( now < svc->cur_deadline )
        break;

    rt_update_deadline(now, svc);
    ...

Thanks and Regards,
Dario
-- 
<<This happens because I choose it to happen!>> (Raistlin Majere)
-----------------------------------------------------------------
Dario Faggioli, Ph.D, http://about.me/dario.faggioli
Senior Software Engineer, Citrix Systems R&D Ltd., Cambridge (UK)

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to