[PATCH 2/5] change move_task_off_dead_cpu() to take rq->lock around select_fallback_rq() move_task_off_dead_cpu()->select_fallback_rq() reads/updates ->cpus_allowed lockless. We can race with set_cpus_allowed() running in parallel. Change it to take rq->lock around select_fallback_rq(). Note that it is not trivial to move this spin_lock() into select_fallback_rq(), we must recheck the task was not migrated after we take the lock and other callers do not need this lock. We can't race with other callers of select_fallback_rq() which rely on TASK_WAKING, try_to_wake_up() and wake_up_new_task(), they must protect themselves against cpu hotplug anyway. Also, change it to not assume irqs are disabled and absorb __migrate_task_irq(). Signed-off-by: Oleg Nesterov --- kernel/sched.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) --- 34-rc1/kernel/sched.c~2_MTODC_TAKE_RQ_LOCK 2010-03-13 19:48:15.000000000 +0100 +++ 34-rc1/kernel/sched.c 2010-03-13 19:50:57.000000000 +0100 @@ -5509,29 +5509,28 @@ static int migration_thread(void *data) } #ifdef CONFIG_HOTPLUG_CPU - -static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu) -{ - int ret; - - local_irq_disable(); - ret = __migrate_task(p, src_cpu, dest_cpu); - local_irq_enable(); - return ret; -} - /* * Figure out where task on dead CPU should go, use force if necessary. */ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) { - int dest_cpu; - + struct rq *rq = cpu_rq(dead_cpu); + int migrated, dest_cpu; + unsigned long flags; again: - dest_cpu = select_fallback_rq(dead_cpu, p); + local_irq_save(flags); + raw_spin_lock(&rq->lock); + migrated = (task_cpu(p) != dead_cpu); + if (!migrated) + dest_cpu = select_fallback_rq(dead_cpu, p); + raw_spin_unlock(&rq->lock); + + if (!migrated) + migrated = __migrate_task(p, dead_cpu, dest_cpu); + local_irq_restore(flags); /* It can have affinity changed while we were choosing. */ - if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu))) + if (unlikely(!migrated)) goto again; }