summaryrefslogtreecommitdiff
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2004-08-23 21:08:29 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-23 21:08:29 -0700
commitc62e7cdb3655b52b3d8904efa3183b88248c92fd (patch)
treeef264cf8bd5c61659008c5f6ccc9387d3d698cdc /kernel/fork.c
parentc15d3bea6f1d48d6f4e23afcfa3282144b948207 (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/fork.c')
-rw-r--r--kernel/fork.c22
1 files changed, 11 insertions, 11 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;