From 31989cba5d3acc6dfad2becd96eda6f1fb37383e Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 10 Oct 2002 20:05:46 -0700 Subject: [PATCH] sched-2.5.41-A0 This fixes the scheduler's migration code to not disable preemption. It also fixes the bug that was hidden by the broken disable-preempt change: the migration thread did not kick idle CPUs if a task is migrated to them, which causes a hung boot when ksoftirqds are started. It was pure luck it worked until now, it was broken pretty much from day 1 on. --- kernel/sched.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'kernel') diff --git a/kernel/sched.c b/kernel/sched.c index 62e81a6f285d..0464ac0649b8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1953,7 +1953,6 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) BUG(); #endif - preempt_disable(); rq = task_rq_lock(p, &flags); p->cpus_allowed = new_mask; /* @@ -1962,7 +1961,7 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) */ if (new_mask & (1UL << task_cpu(p))) { task_rq_unlock(rq, &flags); - goto out; + return; } /* * If the task is not on a runqueue (and not running), then @@ -1971,17 +1970,16 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) if (!p->array && !task_running(rq, p)) { set_task_cpu(p, __ffs(p->cpus_allowed)); task_rq_unlock(rq, &flags); - goto out; + return; } init_completion(&req.done); req.task = p; list_add(&req.list, &rq->migration_queue); task_rq_unlock(rq, &flags); + wake_up_process(rq->migration_thread); wait_for_completion(&req.done); -out: - preempt_enable(); } /* @@ -1999,16 +1997,12 @@ static int migration_thread(void * data) sigfillset(¤t->blocked); set_fs(KERNEL_DS); - set_cpus_allowed(current, 1UL << cpu); - /* - * Migration can happen without a migration thread on the - * target CPU because here we remove the thread from the - * runqueue and the helper thread then moves this thread - * to the target CPU - we'll wake up there. + * Either we are running on the right CPU, or there's a + * a migration thread on the target CPU, guaranteed. */ - if (smp_processor_id() != cpu) - printk("migration_task %d on cpu=%d\n", cpu, smp_processor_id()); + set_cpus_allowed(current, 1UL << cpu); + ret = setscheduler(0, SCHED_FIFO, ¶m); rq = this_rq(); @@ -2055,6 +2049,8 @@ repeat: if (p->array) { deactivate_task(p, rq_src); activate_task(p, rq_dest); + if (p->prio < rq_dest->curr->prio) + resched_task(rq_dest->curr); } } double_rq_unlock(rq_src, rq_dest); -- cgit v1.2.3