[PATCH] fix init_idle() locking problem

From: Bjorn Helgaas
Date: Mon May 10 2004 - 11:33:15 EST


When starting up secondary CPUs, most architectures do something
like this:

do_boot_cpu(int cpu)
{
idle = fork_by_hand();
wake_up_forked_process(idle);
init_idle(idle, cpu);

init_idle() removes "idle" from its runqueue, but there's a window
between looking up the runqueue and locking it, where another CPU
can move "idle" to a different runqueue, i.e., via load_balance().

This is based on 2.6.6.

===== kernel/sched.c 1.261 vs edited =====
--- 1.261/kernel/sched.c Mon Apr 26 23:07:43 2004
+++ edited/kernel/sched.c Mon May 10 09:59:54 2004
@@ -2660,11 +2660,18 @@

void __init init_idle(task_t *idle, int cpu)
{
- runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(task_cpu(idle));
+ runqueue_t *idle_rq = cpu_rq(cpu), *rq;
unsigned long flags;

+repeat_lock_runqueues:
+ rq = task_rq(idle);
local_irq_save(flags);
double_rq_lock(idle_rq, rq);
+ if (rq != task_rq(idle)) {
+ double_rq_unlock(idle_rq, rq);
+ local_irq_restore(flags);
+ goto repeat_lock_runqueues;
+ }

idle_rq->curr = idle_rq->idle = idle;
deactivate_task(idle, rq);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/