|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 2/3] xen/sched: carve out memory allocation and freeing from schedule_cpu_rm()
On 02.08.2022 15:27, Juergen Gross wrote:
> --- a/xen/common/sched/core.c
> +++ b/xen/common/sched/core.c
> @@ -3190,6 +3190,66 @@ out:
> return ret;
> }
>
> +static struct cpu_rm_data *schedule_cpu_rm_alloc(unsigned int cpu)
> +{
> + struct cpu_rm_data *data;
> + struct sched_resource *sr;
const?
> + int idx;
While code is supposedly only being moved, I still question this not
being "unsigned int", the more that sr->granularity is "unsigned int"
as well. (Same then for the retained instance ofthe variable in the
original function.) Of course the loop in the error path then needs
writing differently.
> + rcu_read_lock(&sched_res_rculock);
> +
> + sr = get_sched_res(cpu);
> + data = xzalloc_flex_struct(struct cpu_rm_data, sr, sr->granularity - 1);
Afaict xmalloc_flex_struct() would do here, as you fill all fields.
> + if ( !data )
> + goto out;
> +
> + data->old_ops = sr->scheduler;
> + data->vpriv_old = idle_vcpu[cpu]->sched_unit->priv;
> + data->ppriv_old = sr->sched_priv;
At least from an abstract perspective, doesn't reading fields from
sr require the RCU lock to be held continuously (i.e. not dropping
it at the end of this function and re-acquiring it in the caller)?
> + for ( idx = 0; idx < sr->granularity - 1; idx++ )
> + {
> + data->sr[idx] = sched_alloc_res();
> + if ( data->sr[idx] )
> + {
> + data->sr[idx]->sched_unit_idle = sched_alloc_unit_mem();
> + if ( !data->sr[idx]->sched_unit_idle )
> + {
> + sched_res_free(&data->sr[idx]->rcu);
> + data->sr[idx] = NULL;
> + }
> + }
> + if ( !data->sr[idx] )
> + {
> + for ( idx--; idx >= 0; idx-- )
> + sched_res_free(&data->sr[idx]->rcu);
> + xfree(data);
> + data = NULL;
XFREE()?
> @@ -3198,53 +3258,22 @@ out:
> */
> int schedule_cpu_rm(unsigned int cpu)
> {
> - void *ppriv_old, *vpriv_old;
> - struct sched_resource *sr, **sr_new = NULL;
> + struct sched_resource *sr;
> + struct cpu_rm_data *data;
> struct sched_unit *unit;
> - struct scheduler *old_ops;
> spinlock_t *old_lock;
> unsigned long flags;
> - int idx, ret = -ENOMEM;
> + int idx = 0;
> unsigned int cpu_iter;
>
> + data = schedule_cpu_rm_alloc(cpu);
> + if ( !data )
> + return -ENOMEM;
> +
> rcu_read_lock(&sched_res_rculock);
>
> sr = get_sched_res(cpu);
> - old_ops = sr->scheduler;
>
> - if ( sr->granularity > 1 )
> - {
This conditional is lost afaict, resulting in potentially wrong behavior
in the new helper. Considering its purpose I expect there's a guarantee
that the field's value can never be zero, but then I guess an ASSERT()
would be nice next to the potentially problematic uses in the helper.
> --- a/xen/common/sched/private.h
> +++ b/xen/common/sched/private.h
> @@ -598,6 +598,14 @@ struct affinity_masks {
> cpumask_var_t soft;
> };
>
> +/* Memory allocation related data for schedule_cpu_rm(). */
> +struct cpu_rm_data {
> + struct scheduler *old_ops;
const?
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |