[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH 01/10] sched: core: save IRQ state during locking
Hi Jurgen, Jürgen Groß writes: > On 23.02.21 03:34, Volodymyr Babchuk wrote: >> With XEN preemption enabled, scheduler functions can be called with >> IRQs disabled (for example, at end of IRQ handler), so we should >> save and restore IRQ state in schedulers code. > > This breaks core scheduling. Yes, thank you. I forgot to mention that this PoC is not compatible with core scheduling. It is not used on ARM, so I could not test it anyways. > Waiting for another sibling with interrupts disabled is an absolute > no go, as deadlocks are the consequence. > > You could (in theory) make preemption and core scheduling mutually > exclusive, but this would break the forward path to mutexes etc. > Well, I implemented the most naive way to enable hypervisor preemption. I'm sure that with a bit more careful approach I can make it compatible with core scheduling. There is no strict requirement to run scheduler with IRQs disabled. > > Juergen > >> Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@xxxxxxxx> >> --- >> xen/common/sched/core.c | 33 ++++++++++++++++++--------------- >> 1 file changed, 18 insertions(+), 15 deletions(-) >> diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c >> index 9745a77eee..7e075613d5 100644 >> --- a/xen/common/sched/core.c >> +++ b/xen/common/sched/core.c >> @@ -2470,7 +2470,8 @@ static struct vcpu *sched_force_context_switch(struct >> vcpu *vprev, >> * sched_res_rculock has been dropped. >> */ >> static struct sched_unit *sched_wait_rendezvous_in(struct sched_unit *prev, >> - spinlock_t **lock, int >> cpu, >> + spinlock_t **lock, >> + unsigned long *flags, >> int cpu, >> s_time_t now) >> { >> struct sched_unit *next; >> @@ -2500,7 +2501,7 @@ static struct sched_unit >> *sched_wait_rendezvous_in(struct sched_unit *prev, >> prev->rendezvous_in_cnt++; >> atomic_set(&prev->rendezvous_out_cnt, 0); >> - pcpu_schedule_unlock_irq(*lock, cpu); >> + pcpu_schedule_unlock_irqrestore(*lock, *flags, cpu); >> sched_context_switch(vprev, v, false, now); >> @@ -2530,7 +2531,7 @@ static struct sched_unit >> *sched_wait_rendezvous_in(struct sched_unit *prev, >> prev->rendezvous_in_cnt++; >> atomic_set(&prev->rendezvous_out_cnt, 0); >> - pcpu_schedule_unlock_irq(*lock, cpu); >> + pcpu_schedule_unlock_irqrestore(*lock, *flags, cpu); >> raise_softirq(SCHED_SLAVE_SOFTIRQ); >> sched_context_switch(vprev, vprev, false, now); >> @@ -2538,11 +2539,11 @@ static struct sched_unit >> *sched_wait_rendezvous_in(struct sched_unit *prev, >> return NULL; /* ARM only. */ >> } >> - pcpu_schedule_unlock_irq(*lock, cpu); >> + pcpu_schedule_unlock_irqrestore(*lock, *flags, cpu); >> cpu_relax(); >> - *lock = pcpu_schedule_lock_irq(cpu); >> + *lock = pcpu_schedule_lock_irqsave(cpu, flags); >> /* >> * Check for scheduling resource switched. This happens when we are >> @@ -2557,7 +2558,7 @@ static struct sched_unit >> *sched_wait_rendezvous_in(struct sched_unit *prev, >> ASSERT(is_idle_unit(prev)); >> atomic_set(&prev->next_task->rendezvous_out_cnt, 0); >> prev->rendezvous_in_cnt = 0; >> - pcpu_schedule_unlock_irq(*lock, cpu); >> + pcpu_schedule_unlock_irqrestore(*lock, *flags, cpu); >> rcu_read_unlock(&sched_res_rculock); >> return NULL; >> } >> @@ -2574,12 +2575,13 @@ static void sched_slave(void) >> spinlock_t *lock; >> bool do_softirq = false; >> unsigned int cpu = smp_processor_id(); >> + unsigned long flags; >> ASSERT_NOT_IN_ATOMIC(); >> rcu_read_lock(&sched_res_rculock); >> - lock = pcpu_schedule_lock_irq(cpu); >> + lock = pcpu_schedule_lock_irqsave(cpu, &flags); >> now = NOW(); >> @@ -2590,7 +2592,7 @@ static void sched_slave(void) >> if ( v ) >> { >> - pcpu_schedule_unlock_irq(lock, cpu); >> + pcpu_schedule_unlock_irqrestore(lock, flags, cpu); >> sched_context_switch(vprev, v, false, now); >> @@ -2602,7 +2604,7 @@ static void sched_slave(void) >> if ( !prev->rendezvous_in_cnt ) >> { >> - pcpu_schedule_unlock_irq(lock, cpu); >> + pcpu_schedule_unlock_irqrestore(lock, flags, cpu); >> rcu_read_unlock(&sched_res_rculock); >> @@ -2615,11 +2617,11 @@ static void sched_slave(void) >> stop_timer(&get_sched_res(cpu)->s_timer); >> - next = sched_wait_rendezvous_in(prev, &lock, cpu, now); >> + next = sched_wait_rendezvous_in(prev, &lock, &flags, cpu, now); >> if ( !next ) >> return; >> - pcpu_schedule_unlock_irq(lock, cpu); >> + pcpu_schedule_unlock_irqrestore(lock, flags, cpu); >> sched_context_switch(vprev, sched_unit2vcpu_cpu(next, cpu), >> is_idle_unit(next) && !is_idle_unit(prev), now); >> @@ -2637,6 +2639,7 @@ static void schedule(void) >> s_time_t now; >> struct sched_resource *sr; >> spinlock_t *lock; >> + unsigned long flags; >> int cpu = smp_processor_id(); >> unsigned int gran; >> @@ -2646,7 +2649,7 @@ static void schedule(void) >> rcu_read_lock(&sched_res_rculock); >> - lock = pcpu_schedule_lock_irq(cpu); >> + lock = pcpu_schedule_lock_irqsave(cpu, &flags); >> sr = get_sched_res(cpu); >> gran = sr->granularity; >> @@ -2657,7 +2660,7 @@ static void schedule(void) >> * We have a race: sched_slave() should be called, so raise a >> softirq >> * in order to re-enter schedule() later and call sched_slave() >> now. >> */ >> - pcpu_schedule_unlock_irq(lock, cpu); >> + pcpu_schedule_unlock_irqrestore(lock, flags, cpu); >> rcu_read_unlock(&sched_res_rculock); >> @@ -2676,7 +2679,7 @@ static void schedule(void) >> prev->rendezvous_in_cnt = gran; >> cpumask_andnot(mask, sr->cpus, cpumask_of(cpu)); >> cpumask_raise_softirq(mask, SCHED_SLAVE_SOFTIRQ); >> - next = sched_wait_rendezvous_in(prev, &lock, cpu, now); >> + next = sched_wait_rendezvous_in(prev, &lock, &flags, cpu, now); >> if ( !next ) >> return; >> } >> @@ -2687,7 +2690,7 @@ static void schedule(void) >> atomic_set(&next->rendezvous_out_cnt, 0); >> } >> - pcpu_schedule_unlock_irq(lock, cpu); >> + pcpu_schedule_unlock_irqrestore(lock, flags, cpu); >> vnext = sched_unit2vcpu_cpu(next, cpu); >> sched_context_switch(vprev, vnext, >> -- Volodymyr Babchuk at EPAM
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |