[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 1/2] arinc: Add cpu-pool support to scheduler.
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. 7. Add a scheduler lock to protect access to global variables from multiple PCPUs. 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> --- v2: Address Andrew Cooper's review comments. Add lock to protect global variables that could be accessed from more than one PCPU. --- xen/common/sched_arinc653.c | 111 ++++++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/xen/common/sched_arinc653.c b/xen/common/sched_arinc653.c index f4eb943..5f09ded 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]) @@ -100,6 +105,9 @@ typedef struct sched_entry_s */ typedef struct a653sched_priv_s { + /* lock for the whole pluggable scheduler, nests inside cpupool_lock */ + spinlock_t lock; + /** * This array holds the active ARINC 653 schedule. * @@ -119,7 +127,7 @@ typedef struct a653sched_priv_s * or a domain with multiple VCPUs could have a different * schedule entry for each VCPU. */ - int num_schedule_entries; + unsigned int num_schedule_entries; /** * the major frame time for the ARINC 653 schedule. @@ -224,9 +232,11 @@ 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; + unsigned long flags; + int rc = -EINVAL; + + spin_lock_irqsave(&sched_priv->lock, flags); /* Check for valid major frame and number of schedule entries. */ if ( (schedule->major_frame <= 0) @@ -236,10 +246,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 +255,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. @@ -284,10 +286,11 @@ arinc653_sched_set( */ sched_priv->next_major_frame = NOW(); - return 0; + rc = 0; fail: - return -EINVAL; + spin_unlock_irqrestore(&sched_priv->lock, flags); + return rc; } /** @@ -307,6 +310,9 @@ arinc653_sched_get( { a653sched_priv_t *sched_priv = SCHED_PRIV(ops); unsigned int i; + unsigned long flags; + + spin_lock_irqsave(&sched_priv->lock, flags); schedule->num_sched_entries = sched_priv->num_schedule_entries; schedule->major_frame = sched_priv->major_frame; @@ -319,6 +325,8 @@ arinc653_sched_get( schedule->sched_entries[i].runtime = sched_priv->schedule[i].runtime; } + spin_unlock_irqrestore(&sched_priv->lock, flags); + return 0; } @@ -347,13 +355,8 @@ 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; + spin_lock_init(&prv->lock); INIT_LIST_HEAD(&prv->vcpu_list); return 0; @@ -380,7 +383,10 @@ 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; + unsigned int entry; + unsigned long flags; /* * Allocate memory for the ARINC 653-specific scheduler data information @@ -390,6 +396,28 @@ a653sched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd) if ( svc == NULL ) return NULL; + spin_lock_irqsave(&sched_priv->lock, flags); + + /* + * Add every one of dom0's vcpus to the schedule, as long as there are + * slots available. + */ + if ( vc->domain->domain_id == 0 ) + { + entry = sched_priv->num_schedule_entries; + + if ( entry < ARINC653_MAX_DOMAINS_PER_SCHEDULE ) + { + 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 @@ -402,6 +430,8 @@ a653sched_alloc_vdata(const struct scheduler *ops, struct vcpu *vc, void *dd) list_add(&svc->list, &SCHED_PRIV(ops)->vcpu_list); update_schedule_vcpus(ops); + spin_unlock_irqrestore(&sched_priv->lock, flags); + return svc; } @@ -535,11 +565,17 @@ a653sched_do_schedule( { struct task_slice ret; /* hold the chosen domain */ struct vcpu * new_task = NULL; - static int sched_index = 0; + static unsigned int sched_index = 0; static s_time_t next_switch_time; a653sched_priv_t *sched_priv = SCHED_PRIV(ops); + const unsigned int cpu = smp_processor_id(); + unsigned long flags; + + spin_lock_irqsave(&sched_priv->lock, flags); - if ( now >= sched_priv->next_major_frame ) + if ( sched_priv->num_schedule_entries < 1 ) + sched_priv->next_major_frame = now + DEFAULT_TIMESLICE; + 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 +610,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); /* @@ -590,9 +626,16 @@ a653sched_do_schedule( */ BUG_ON(now >= sched_priv->next_major_frame); + spin_unlock_irqrestore(&sched_priv->lock, flags); + /* 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) + && (new_task->processor != cpu) ) + new_task = IDLETASK(cpu); /* * Return the amount of time the next domain has to run and the address @@ -600,7 +643,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 +661,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; + unsigned int cpu; + + /* + * If present, prefer vc's current processor, else + * just find the first valid vcpu . + */ + 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; + + return cpu; } /** -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |