[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH for 4.7 4/4] xen: adopt .deinit_pdata and improve timer handling



On 03/05/16 22:46, Dario Faggioli wrote:
> The scheduling hooks API is now used properly, and no
> initialization or de-initialization happen in
> alloc/free_pdata any longer.
> 
> In fact, just like it is for Credit2, there is no real
> need for implementing alloc_pdata and free_pdata.
> 
> This also made it possible to improve the replenishment
> timer handling logic, such that now the timer is always
> kept on one of the pCPU of the scheduler it's servicing.
> Before this commit, in fact, even if the pCPU where the
> timer happened to be initialized at creation time was
> moved to another cpupool, the timer stayed there,
> potentially inferfearing with the new scheduler of the

* interfering

> pCPU itself.
> 
> Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx>

I don't know much about the logic, so I'll wait for Meng Xu to review it.

 -George

> --
> Cc: Meng Xu <mengxu@xxxxxxxxxxxxx>
> Cc: George Dunlap <george.dunlap@xxxxxxxxxx>
> Cc: Tianyang Chen <tiche@xxxxxxxxxxxxxx>
> Cc: Wei Liu <wei.liu2@xxxxxxxxxx>
> ---
>  xen/common/sched_rt.c |   74 
> ++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 55 insertions(+), 19 deletions(-)
> 
> diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c
> index 673fc92..7f8f411 100644
> --- a/xen/common/sched_rt.c
> +++ b/xen/common/sched_rt.c
> @@ -590,6 +590,10 @@ rt_init(struct scheduler *ops)
>      if ( prv == NULL )
>          return -ENOMEM;
>  
> +    prv->repl_timer = xzalloc(struct timer);
> +    if ( prv->repl_timer == NULL )
> +        return -ENOMEM;
> +
>      spin_lock_init(&prv->lock);
>      INIT_LIST_HEAD(&prv->sdom);
>      INIT_LIST_HEAD(&prv->runq);
> @@ -600,12 +604,6 @@ rt_init(struct scheduler *ops)
>  
>      ops->sched_data = prv;
>  
> -    /*
> -     * The timer initialization will happen later when
> -     * the first pcpu is added to this pool in alloc_pdata.
> -     */
> -    prv->repl_timer = NULL;
> -
>      return 0;
>  }
>  
> @@ -614,7 +612,8 @@ rt_deinit(struct scheduler *ops)
>  {
>      struct rt_private *prv = rt_priv(ops);
>  
> -    kill_timer(prv->repl_timer);
> +    ASSERT(prv->repl_timer->status == TIMER_STATUS_invalid ||
> +           prv->repl_timer->status == TIMER_STATUS_killed);
>      xfree(prv->repl_timer);
>  
>      ops->sched_data = NULL;
> @@ -632,9 +631,19 @@ rt_init_pdata(const struct scheduler *ops, void *pdata, 
> int cpu)
>      spinlock_t *old_lock;
>      unsigned long flags;
>  
> -    /* Move the scheduler lock to our global runqueue lock.  */
>      old_lock = pcpu_schedule_lock_irqsave(cpu, &flags);
>  
> +    /*
> +     * TIMER_STATUS_invalid means we are the first cpu that sees the timer
> +     * allocated but not initialized, and so it's up to us to initialize it.
> +     */
> +    if ( prv->repl_timer->status == TIMER_STATUS_invalid )
> +    {
> +        init_timer(prv->repl_timer, repl_timer_handler, (void*) ops, cpu);
> +        dprintk(XENLOG_DEBUG, "RTDS: timer initialized on cpu %u\n", cpu);
> +    }
> +
> +    /* Move the scheduler lock to our global runqueue lock.  */
>      per_cpu(schedule_data, cpu).schedule_lock = &prv->lock;
>  
>      /* _Not_ pcpu_schedule_unlock(): per_cpu().schedule_lock changed! */
> @@ -659,6 +668,20 @@ rt_switch_sched(struct scheduler *new_ops, unsigned int 
> cpu,
>       */
>      ASSERT(per_cpu(schedule_data, cpu).schedule_lock != &prv->lock);
>  
> +    /*
> +     * If we are the absolute first cpu being switched toward this
> +     * scheduler (in which case we'll see TIMER_STATUS_invalid), or the
> +     * first one that is added back to the cpupool that had all its cpus
> +     * removed (in which case we'll see TIMER_STATUS_killed), it's our
> +     * job to (re)initialize the timer.
> +     */
> +    if ( prv->repl_timer->status == TIMER_STATUS_invalid ||
> +         prv->repl_timer->status == TIMER_STATUS_killed )
> +    {
> +        init_timer(prv->repl_timer, repl_timer_handler, (void*) new_ops, 
> cpu);
> +        dprintk(XENLOG_DEBUG, "RTDS: timer initialized on cpu %u\n", cpu);
> +    }
> +
>      idle_vcpu[cpu]->sched_priv = vdata;
>      per_cpu(scheduler, cpu) = new_ops;
>      per_cpu(schedule_data, cpu).sched_priv = NULL; /* no pdata */
> @@ -672,23 +695,36 @@ rt_switch_sched(struct scheduler *new_ops, unsigned int 
> cpu,
>      per_cpu(schedule_data, cpu).schedule_lock = &prv->lock;
>  }
>  
> -static void *
> -rt_alloc_pdata(const struct scheduler *ops, int cpu)
> +static void
> +rt_deinit_pdata(const struct scheduler *ops, void *pcpu, int cpu)
>  {
> +    unsigned long flags;
>      struct rt_private *prv = rt_priv(ops);
>  
> -    if ( prv->repl_timer == NULL )
> -    {
> -        /* Allocate the timer on the first cpu of this pool. */
> -        prv->repl_timer = xzalloc(struct timer);
> +    spin_lock_irqsave(&prv->lock, flags);
>  
> -        if ( prv->repl_timer == NULL )
> -            return ERR_PTR(-ENOMEM);
> +    if ( prv->repl_timer->cpu == cpu )
> +    {
> +        struct cpupool *c = per_cpu(cpupool, cpu);
> +        unsigned int new_cpu = cpumask_cycle(cpu, cpupool_online_cpumask(c));
>  
> -        init_timer(prv->repl_timer, repl_timer_handler, (void *)ops, cpu);
> +        /*
> +         * Make sure the timer run on one of the cpus that are still 
> available
> +         * to this scheduler. If there aren't any left, it means it's the 
> time
> +         * to just kill it.
> +         */
> +        if ( new_cpu >= nr_cpu_ids )
> +        {
> +            kill_timer(prv->repl_timer);
> +            dprintk(XENLOG_DEBUG, "RTDS: timer killed on cpu %d\n", cpu);
> +        }
> +        else
> +        {
> +            migrate_timer(prv->repl_timer, new_cpu);
> +        }
>      }
>  
> -    return NULL;
> +    spin_unlock_irqrestore(&prv->lock, flags);
>  }
>  
>  static void *
> @@ -1433,9 +1469,9 @@ static const struct scheduler sched_rtds_def = {
>      .dump_settings  = rt_dump,
>      .init           = rt_init,
>      .deinit         = rt_deinit,
> -    .alloc_pdata    = rt_alloc_pdata,
>      .init_pdata     = rt_init_pdata,
>      .switch_sched   = rt_switch_sched,
> +    .deinit_pdata   = rt_deinit_pdata,
>      .alloc_domdata  = rt_alloc_domdata,
>      .free_domdata   = rt_free_domdata,
>      .init_domain    = rt_dom_init,
> 


_______________________________________________
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®.