diff options
| author | Ingo Molnar <mingo@elte.hu> | 2004-08-23 21:08:29 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-08-23 21:08:29 -0700 |
| commit | c62e7cdb3655b52b3d8904efa3183b88248c92fd (patch) | |
| tree | ef264cf8bd5c61659008c5f6ccc9387d3d698cdc /kernel | |
| parent | c15d3bea6f1d48d6f4e23afcfa3282144b948207 (diff) | |
[PATCH] sched: fork hotplug hanling cleanup
- remove the hotplug lock from around much of fork(), and re-copy the
cpus_allowed mask to solve the hotplug race cleanly.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Srivatsa Vaddagiri <vatsa@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 22 | ||||
| -rw-r--r-- | kernel/sched.c | 14 |
2 files changed, 12 insertions, 24 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 2ac003c78a72..470c10e08d41 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -893,16 +893,6 @@ struct task_struct *copy_process(unsigned long clone_flags, if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM)) return ERR_PTR(-EINVAL); - /* - * The newly dup'ed task shares the same cpus_allowed mask as its - * parent (ie. current), and it is not attached to the tasklist. - * The end result is that this CPU might go down and the parent - * be migrated away, leaving the task on a dead CPU. So take the - * hotplug lock here and release it after the child has been attached - * to the tasklist. - */ - lock_cpu_hotplug(); - retval = security_task_create(clone_flags); if (retval) goto fork_out; @@ -1043,6 +1033,17 @@ struct task_struct *copy_process(unsigned long clone_flags, /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); + + /* + * The task hasn't been attached yet, so cpus_allowed mask cannot + * have changed. The cpus_allowed mask of the parent may have + * changed after it was copied first time, and it may then move to + * another CPU - so we re-copy it here and set the child's CPU to + * the parent's CPU. This avoids alot of nasty races. + */ + p->cpus_allowed = current->cpus_allowed; + set_task_cpu(p, smp_processor_id()); + /* * Check for pending SIGKILL! The new thread should not be allowed * to slip out of an OOM kill. (or normal SIGKILL.) @@ -1108,7 +1109,6 @@ struct task_struct *copy_process(unsigned long clone_flags, retval = 0; fork_out: - unlock_cpu_hotplug(); if (retval) return ERR_PTR(retval); return p; diff --git a/kernel/sched.c b/kernel/sched.c index 139a5da891b1..8a58b9f62124 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -872,22 +872,10 @@ static int find_idlest_cpu(struct task_struct *p, int this_cpu, /* * Perform scheduler related setup for a newly forked process p. - * p is forked by current. The cpu hotplug lock is held. + * p is forked by current. */ void fastcall sched_fork(task_t *p) { - int cpu = smp_processor_id(); - - /* - * The task hasn't been attached yet, so cpus_allowed mask cannot - * change. The cpus_allowed mask of the parent may have changed - * after it is copied, and it may then move to a CPU that is not - * allowed for the child. - */ - if (unlikely(!cpu_isset(cpu, p->cpus_allowed))) - cpu = any_online_cpu(p->cpus_allowed); - set_task_cpu(p, cpu); - /* * We mark the process as running here, but have not actually * inserted it onto the runqueue yet. This guarantees that |
