|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |