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

Re: [Xen-devel] [PATCH 7/7] xen: sched_rt: print useful affinity info when dumping



Hi Dario,

2015-03-16 13:05 GMT-04:00 Dario Faggioli <dario.faggioli@xxxxxxxxxx>:
> In fact, printing the cpupool's CPU online mask
> for each vCPU is just redundant, as that is the
> same for all the vCPUs of all the domains in the
> same cpupool, while hard affinity is already part
> of the output of dumping domains info.
>
> Instead, print the intersection between hard
> affinity and online CPUs, which is --in case of this
> scheduler-- the effective affinity always used for
> the vCPUs.

Agree.

>
> This change also takes the chance to add a scratch
> cpumask, to avoid having to create one more
> cpumask_var_t on the stack of the dumping routine.

Actually, I have a question about the strength of this design. When we
have a machine with many cpus, we will end up with allocating a
cpumask for each cpu. Is this better than having a cpumask_var_t on
the stack of the dumping routine, since the dumping routine is not in
the hot path?

> Such scratch area can be used to kill most of the
> cpumasks_var_t local variables in other functions
> in the file, but that is *NOT* done in this chage.
>
> Finally, convert the file to use keyhandler scratch,
> instead of open coded string buffers.
>
> Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx>
> Cc: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
> Cc: Meng Xu <xumengpanda@xxxxxxxxx>
> Cc: Jan Beulich <JBeulich@xxxxxxxx>
> Cc: Keir Fraser <keir@xxxxxxx>
> ---
>  xen/common/sched_rt.c |   40 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 32 insertions(+), 8 deletions(-)
>
> diff --git a/xen/common/sched_rt.c b/xen/common/sched_rt.c
> index 167a484..7aa3ac8 100644
> --- a/xen/common/sched_rt.c
> +++ b/xen/common/sched_rt.c
> @@ -124,6 +124,12 @@
>  #define TRC_RTDS_BUDGET_REPLENISH TRC_SCHED_CLASS_EVT(RTDS, 4)
>  #define TRC_RTDS_SCHED_TASKLET    TRC_SCHED_CLASS_EVT(RTDS, 5)
>
> + /*
> +  * Useful to avoid too many cpumask_var_t on the stack.
> +  */
> +static cpumask_t **_cpumask_scratch;
> +#define cpumask_scratch _cpumask_scratch[smp_processor_id()]
> +
>  /*
>   * Systme-wide private data, include global RunQueue/DepletedQ
>   * Global lock is referenced by schedule_data.schedule_lock from all
> @@ -218,7 +224,6 @@ __q_elem(struct list_head *elem)
>  static void
>  rt_dump_vcpu(const struct scheduler *ops, const struct rt_vcpu *svc)
>  {
> -    char cpustr[1024];
>      cpumask_t *cpupool_mask;
>
>      ASSERT(svc != NULL);
> @@ -229,10 +234,22 @@ rt_dump_vcpu(const struct scheduler *ops, const struct 
> rt_vcpu *svc)
>          return;
>      }
>
> -    cpumask_scnprintf(cpustr, sizeof(cpustr), svc->vcpu->cpu_hard_affinity);
> +    cpupool_mask = cpupool_scheduler_cpumask(svc->vcpu->domain->cpupool);
> +    /*
> +     * We can't just use 'cpumask_scratch' because the dumping can
> +     * happen from a pCPU outside of this scheduler's cpupool, and
> +     * hence it's not right to use the pCPU's scratch mask (which
> +     * may even not exist!). On the other hand, it is safe to use
> +     * svc->vcpu->processor's own scratch space, since we own the
> +     * runqueue lock.
> +     */
> +    cpumask_and(_cpumask_scratch[svc->vcpu->processor], cpupool_mask,
> +                svc->vcpu->cpu_hard_affinity);
> +    cpulist_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch),
> +                      _cpumask_scratch[svc->vcpu->processor]);
>      printk("[%5d.%-2u] cpu %u, (%"PRI_stime", %"PRI_stime"),"
>             " cur_b=%"PRI_stime" cur_d=%"PRI_stime" last_start=%"PRI_stime"\n"
> -           " \t\t onQ=%d runnable=%d cpu_hard_affinity=%s ",
> +           " \t\t onQ=%d runnable=%d flags=%x effective hard_affinity=%s\n",
>              svc->vcpu->domain->domain_id,
>              svc->vcpu->vcpu_id,
>              svc->vcpu->processor,
> @@ -243,11 +260,8 @@ rt_dump_vcpu(const struct scheduler *ops, const struct 
> rt_vcpu *svc)
>              svc->last_start,
>              __vcpu_on_q(svc),
>              vcpu_runnable(svc->vcpu),
> -            cpustr);
> -    memset(cpustr, 0, sizeof(cpustr));
> -    cpupool_mask = cpupool_scheduler_cpumask(svc->vcpu->domain->cpupool);
> -    cpumask_scnprintf(cpustr, sizeof(cpustr), cpupool_mask);
> -    printk("cpupool=%s\n", cpustr);
> +            svc->flags,
> +            keyhandler_scratch);
>  }
>
>  static void
> @@ -409,6 +423,10 @@ rt_init(struct scheduler *ops)
>      if ( prv == NULL )
>          return -ENOMEM;
>
> +    _cpumask_scratch = xmalloc_array(cpumask_var_t, nr_cpu_ids);

Is it better to use xzalloc_array?

> +    if ( _cpumask_scratch == NULL )
> +        return -ENOMEM;
> +
>      spin_lock_init(&prv->lock);
>      INIT_LIST_HEAD(&prv->sdom);
>      INIT_LIST_HEAD(&prv->runq);
> @@ -426,6 +444,7 @@ rt_deinit(const struct scheduler *ops)
>  {
>      struct rt_private *prv = rt_priv(ops);
>
> +    xfree(_cpumask_scratch);
>      xfree(prv);
>  }
>
> @@ -443,6 +462,9 @@ rt_alloc_pdata(const struct scheduler *ops, int cpu)
>      per_cpu(schedule_data, cpu).schedule_lock = &prv->lock;
>      spin_unlock_irqrestore(&prv->lock, flags);
>
> +    if ( !alloc_cpumask_var(&_cpumask_scratch[cpu]) )

Is it better to use zalloc_cpumask_var() here?


> +        return NULL;
> +
>      /* 1 indicates alloc. succeed in schedule.c */
>      return (void *)1;
>  }
> @@ -462,6 +484,8 @@ rt_free_pdata(const struct scheduler *ops, void *pcpu, 
> int cpu)
>      sd->schedule_lock = &sd->_lock;
>
>      spin_unlock_irqrestore(&prv->lock, flags);
> +
> +    free_cpumask_var(_cpumask_scratch[cpu]);
>  }
>
>  static void *
>

Others look good to me!

Thank you very much! :-)

Best,

Meng


-----------
Meng Xu
PhD Student in Computer and Information Science
University of Pennsylvania

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