sched_request_migrate(): fix race condition between migration req and IRQs
make sure the caller thread holds migration queue lock with IRQs disabled until it notifies the target CPU so that an interrupt can not deschedule it in the middle of the request. Change-Id: I85995018ca1e8478ccc9723985b6e8efc9c3acfb
This commit is contained in:
committed by
Masamichi Takagi
parent
9e2196c9ce
commit
26bebb2749
@ -3727,17 +3727,24 @@ void sched_request_migrate(int cpu_id, struct thread *thread)
|
||||
unsigned long irqstate;
|
||||
DECLARE_WAITQ_ENTRY_LOCKED(entry, cpu_local_var(current));
|
||||
|
||||
/*
|
||||
* NOTES:
|
||||
* - migration queue lock must be held before runqueue lock.
|
||||
* - the lock must be held until migration request is added
|
||||
* and the target core is notified, otherwise an interrupt
|
||||
* may deschedule this thread and leave it hanging in
|
||||
* uninterruptible state forever.
|
||||
*/
|
||||
irqstate = ihk_mc_spinlock_lock(&v->migq_lock);
|
||||
waitq_init(&req.wq);
|
||||
waitq_prepare_to_wait(&req.wq, &entry, PS_UNINTERRUPTIBLE);
|
||||
|
||||
irqstate = ihk_mc_spinlock_lock(&v->migq_lock);
|
||||
list_add_tail(&req.list, &v->migq);
|
||||
ihk_mc_spinlock_unlock(&v->migq_lock, irqstate);
|
||||
|
||||
irqstate = ihk_mc_spinlock_lock(&v->runq_lock);
|
||||
ihk_mc_spinlock_lock_noirq(&v->runq_lock);
|
||||
v->flags |= CPU_FLAG_NEED_RESCHED | CPU_FLAG_NEED_MIGRATE;
|
||||
v->status = CPU_STATUS_RUNNING;
|
||||
ihk_mc_spinlock_unlock(&v->runq_lock, irqstate);
|
||||
ihk_mc_spinlock_unlock_noirq(&v->runq_lock);
|
||||
|
||||
if (cpu_id != ihk_mc_get_processor_id()) {
|
||||
/* Kick scheduler */
|
||||
@ -3746,6 +3753,7 @@ void sched_request_migrate(int cpu_id, struct thread *thread)
|
||||
}
|
||||
dkprintf("%s: tid: %d -> cpu: %d\n",
|
||||
__FUNCTION__, thread->tid, cpu_id);
|
||||
ihk_mc_spinlock_unlock(&v->migq_lock, irqstate);
|
||||
|
||||
schedule();
|
||||
waitq_finish_wait(&req.wq, &entry);
|
||||
|
||||
Reference in New Issue
Block a user