summaryrefslogtreecommitdiff
path: root/kernel
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
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')
-rw-r--r--kernel/fork.c22
-rw-r--r--kernel/sched.c14
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