|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/3] arinc: Add cpu-pool support to scheduler.
On 18/11/2013 20:16, Nathan Studer wrote:
> From: Nathan Studer <nate.studer@xxxxxxxxxxxxxxx>
>
> 1. Remove the restriction that dom0 must be in the schedule, since dom-0 may
> not belong to the scheduler's pool.
> 2. Add a schedule entry for each of dom-0's vcpus as they are created.
> 3. Add code to deal with empty schedules in the do_schedule function.
> 4. Call the correct idle task for the pcpu on which the scheduling decision
> is being made in do_schedule.
> 5. Add code to prevent migration of a vcpu.
> 6. Implement a proper cpu_pick function, which prefers the current processor.
>
> These changes do not implement arinc653 multicore. Since the schedule only
> supports 1 vcpu entry per slot, even if the vcpus of a domain are run on
> multiple pcpus, the scheduler will essentially serialize their execution.
>
> Signed-off-by: Nathan Studer <nate.studer@xxxxxxxxxxxxxxx>
> ---
> xen/common/sched_arinc653.c | 76
> +++++++++++++++++++++++++++++--------------
> 1 file changed, 52 insertions(+), 24 deletions(-)
>
> diff --git a/xen/common/sched_arinc653.c b/xen/common/sched_arinc653.c
> index f4eb943..139177e 100644
> --- a/xen/common/sched_arinc653.c
> +++ b/xen/common/sched_arinc653.c
> @@ -41,6 +41,11 @@
> **************************************************************************/
>
> /**
> + * Default timeslice for domain 0.
> + */
> +#define DEFAULT_TIMESLICE MILLISECS(10)
> +
> +/**
> * Retrieve the idle VCPU for a given physical CPU
> */
> #define IDLETASK(cpu) (idle_vcpu[cpu])
> @@ -224,8 +229,6 @@ arinc653_sched_set(
> {
> a653sched_priv_t *sched_priv = SCHED_PRIV(ops);
> s_time_t total_runtime = 0;
> - bool_t found_dom0 = 0;
> - const static xen_domain_handle_t dom0_handle = {0};
> unsigned int i;
>
> /* Check for valid major frame and number of schedule entries. */
> @@ -236,10 +239,6 @@ arinc653_sched_set(
>
> for ( i = 0; i < schedule->num_sched_entries; i++ )
> {
> - if ( dom_handle_cmp(schedule->sched_entries[i].dom_handle,
> - dom0_handle) == 0 )
> - found_dom0 = 1;
> -
> /* Check for a valid VCPU ID and run time. */
> if ( (schedule->sched_entries[i].vcpu_id >= MAX_VIRT_CPUS)
> || (schedule->sched_entries[i].runtime <= 0) )
> @@ -249,10 +248,6 @@ arinc653_sched_set(
> total_runtime += schedule->sched_entries[i].runtime;
> }
>
> - /* Error if the schedule doesn't contain a slot for domain 0. */
> - if ( !found_dom0 )
> - goto fail;
> -
> /*
> * Error if the major frame is not large enough to run all entries as
> * indicated by comparing the total run time to the major frame length.
> @@ -347,12 +342,6 @@ a653sched_init(struct scheduler *ops)
>
> ops->sched_data = prv;
>
> - prv->schedule[0].dom_handle[0] = '\0';
> - prv->schedule[0].vcpu_id = 0;
> - prv->schedule[0].runtime = MILLISECS(10);
> - prv->schedule[0].vc = NULL;
> - prv->num_schedule_entries = 1;
> - prv->major_frame = MILLISECS(10);
> prv->next_major_frame = 0;
> INIT_LIST_HEAD(&prv->vcpu_list);
>
> @@ -380,7 +369,9 @@ a653sched_deinit(const struct scheduler *ops)
> static void *
> a653sched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd)
> {
> + a653sched_priv_t *sched_priv = SCHED_PRIV(ops);
> arinc653_vcpu_t *svc;
> + int entry;
sched_priv->num_schedule_entries is inconsistently used as signed and
unsigned. It should be an unsigned value, and updated to be so
everywhere, including in the a653sched_priv_t structure.
>
> /*
> * Allocate memory for the ARINC 653-specific scheduler data information
> @@ -390,6 +381,19 @@ a653sched_alloc_vdata(const struct scheduler *ops,
> struct vcpu *vc, void *dd)
> if ( svc == NULL )
> return NULL;
>
> + /* add every one of dom0's vcpus to the schedule */
> + if (vc->domain->domain_id == 0)
Xen style would include spaces immediately inside the brackets.
Also, it looks like you could do with a bounds check against
ARINC653_MAX_DOMAINS_PER_SCHEDULE before trying to put another dom0 into
the mix.
> + {
> + entry = sched_priv->num_schedule_entries;
> + sched_priv->schedule[entry].dom_handle[0] = '\0';
> + sched_priv->schedule[entry].vcpu_id = vc->vcpu_id;
> + sched_priv->schedule[entry].runtime = DEFAULT_TIMESLICE;
> + sched_priv->schedule[entry].vc = vc;
> +
> + sched_priv->major_frame += DEFAULT_TIMESLICE;
> + ++sched_priv->num_schedule_entries;
> + }
> +
> /*
> * Initialize our ARINC 653 scheduler-specific information for the VCPU.
> * The VCPU starts "asleep." When Xen is ready for the VCPU to run, it
> @@ -450,7 +454,7 @@ a653sched_alloc_pdata(const struct scheduler *ops, int
> cpu)
> static void
> a653sched_free_pdata(const struct scheduler *ops, void *pcpu, int cpu)
> {
> - /* nop */
> + /* NOP */
This change seems a little pointless.
> }
>
> /**
> @@ -538,8 +542,13 @@ a653sched_do_schedule(
> static int sched_index = 0;
> static s_time_t next_switch_time;
> a653sched_priv_t *sched_priv = SCHED_PRIV(ops);
> + const int cpu = smp_processor_id();
This should be an unsigned int.
>
> - if ( now >= sched_priv->next_major_frame )
> + if ( sched_priv->num_schedule_entries < 1 )
> + {
> + sched_priv->next_major_frame = now + DEFAULT_TIMESLICE;
> + }
Xen style would require these braces to be omitted.
> + else if ( now >= sched_priv->next_major_frame )
> {
> /* time to enter a new major frame
> * the first time this function is called, this will be true */
> @@ -574,14 +583,14 @@ a653sched_do_schedule(
> */
> new_task = (sched_index < sched_priv->num_schedule_entries)
> ? sched_priv->schedule[sched_index].vc
> - : IDLETASK(0);
> + : IDLETASK(cpu);
>
> /* Check to see if the new task can be run (awake & runnable). */
> if ( !((new_task != NULL)
> && (AVCPU(new_task) != NULL)
> && AVCPU(new_task)->awake
> && vcpu_runnable(new_task)) )
> - new_task = IDLETASK(0);
> + new_task = IDLETASK(cpu);
> BUG_ON(new_task == NULL);
>
> /*
> @@ -592,7 +601,12 @@ a653sched_do_schedule(
>
> /* Tasklet work (which runs in idle VCPU context) overrides all else. */
> if ( tasklet_work_scheduled )
> - new_task = IDLETASK(0);
> + new_task = IDLETASK(cpu);
> +
> + /* Running this task would result in a migration */
> + if ( (!is_idle_vcpu(new_task))
The brackets around !is_idle_vcpu() are useless.
> + && (new_task->processor != cpu) )
> + new_task = IDLETASK(cpu);
>
> /*
> * Return the amount of time the next domain has to run and the address
> @@ -600,7 +614,7 @@ a653sched_do_schedule(
> */
> ret.time = next_switch_time - now;
> ret.task = new_task;
> - ret.migrated = 0; /* we do not support migration */
> + ret.migrated = 0;
>
> BUG_ON(ret.time <= 0);
>
> @@ -618,8 +632,22 @@ a653sched_do_schedule(
> static int
> a653sched_pick_cpu(const struct scheduler *ops, struct vcpu *vc)
> {
> - /* this implementation only supports one physical CPU */
> - return 0;
> + cpumask_t *online;
> + int cpu;
unsigned int.
> +
> + /* If present, prefer vc's current processor, else
> + just find the first valid vcpu */
Xen style would be:
/*
* If present....
*/
> + online = cpupool_scheduler_cpumask(vc->domain->cpupool);
> +
> + cpu = cpumask_first(online);
> +
> + if ( (cpumask_test_cpu(vc->processor, online)) ||
> + (cpu >= nr_cpu_ids) )
> + {
> + cpu = vc->processor;
> + }
superfluous brackets and braces.
~Andrew
> +
> + return cpu;
> }
>
> /**
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |