[PATCH]CPU hotplug breaks wake_up_new_task

From: Shaohua Li (shaohua.li_at_intel.com)
Date: 05/31/05

  • Next message: Benjamin Herrenschmidt: "[RFC] Add some hooks to generic suspend code"
    To: lkml <linux-kernel@vger.kernel.org>
    Date:	Tue, 31 May 2005 15:35:09 +0800
    
    

    Hi,
    There is a race condition at wake_up_new_task at CPU hotplug case.
    Say do_fork
            copy_process (which sets new forked task's current cpu, cpu_allowed)
                    <-------- the new forked task's current cpu is offline
            wake_up_new_task
    wake_up_new_task will put the forked task into a dead cpu.

    Thanks,
    Shaohua

    Signed-off-by: Shaohua Li<shaohua.li@intel.com>

    ---
     linux-2.6.11-rc5-mm1-root/kernel/sched.c |   25 +++++++++++++++++++++++--
     1 files changed, 23 insertions(+), 2 deletions(-)
    diff -puN kernel/sched.c~wake_up_new_task_to_online_cpu kernel/sched.c
    --- linux-2.6.11-rc5-mm1/kernel/sched.c~wake_up_new_task_to_online_cpu	2005-05-31 13:39:43.888682784 +0800
    +++ linux-2.6.11-rc5-mm1-root/kernel/sched.c	2005-05-31 14:49:58.537958704 +0800
    @@ -1412,6 +1412,10 @@ void fastcall sched_fork(task_t *p, int 
     	put_cpu();
     }
     
    +#ifdef CONFIG_HOTPLUG_CPU
    +static int task_select_online_cpu(int dead_cpu, struct task_struct *tsk);
    +#endif
    +
     /*
      * wake_up_new_task - wake up a newly created task for the first time.
      *
    @@ -1426,9 +1430,20 @@ void fastcall wake_up_new_task(task_t * 
     	runqueue_t *rq, *this_rq;
     
     	rq = task_rq_lock(p, &flags);
    -	BUG_ON(p->state != TASK_RUNNING);
     	this_cpu = smp_processor_id();
     	cpu = task_cpu(p);
    +#ifdef CONFIG_HOTPLUG_CPU
    +	while (!cpu_online(cpu)) {
    +		cpu = task_select_online_cpu(cpu, p);
    +		set_task_cpu(p, cpu);
    +		task_rq_unlock(rq, &flags);
    +		/* CPU hotplug might occur here */
    +		rq = task_rq_lock(p, &flags);
    +		this_cpu = smp_processor_id();
    +		cpu = task_cpu(p);
    +	}
    +#endif
    +	BUG_ON(p->state != TASK_RUNNING);
     
     	/*
     	 * We decrease the sleep average of forking parents
    @@ -4457,7 +4472,7 @@ wait_to_die:
     
     #ifdef CONFIG_HOTPLUG_CPU
     /* Figure out where task on dead CPU should go, use force if neccessary. */
    -static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
    +static int task_select_online_cpu(int dead_cpu, struct task_struct *tsk)
     {
     	int dest_cpu;
     	cpumask_t mask;
    @@ -4486,6 +4501,12 @@ static void move_task_off_dead_cpu(int d
     			       "longer affine to cpu%d\n",
     			       tsk->pid, tsk->comm, dead_cpu);
     	}
    +	return dest_cpu;
    +}
    +
    +static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
    +{
    +	int dest_cpu = task_select_online_cpu(dead_cpu, tsk);
     	__migrate_task(tsk, dead_cpu, dest_cpu);
     }
     
    _
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    

  • Next message: Benjamin Herrenschmidt: "[RFC] Add some hooks to generic suspend code"

    Relevant Pages