From 26bebb2749c045c91309ed766e9647bdfe5d52a3 Mon Sep 17 00:00:00 2001 From: Balazs Gerofi Date: Fri, 27 Dec 2019 12:22:49 +0000 Subject: [PATCH] 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 --- kernel/process.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/process.c b/kernel/process.c index c35848e3..1bcff5d6 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -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);