summaryrefslogtreecommitdiff
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorWilliam Lee Irwin III <wli@holomorphy.com>2004-08-23 21:27:20 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-23 21:27:20 -0700
commit69c46983febf3acfa45c868fa18ae213c87b5c01 (patch)
treeb6fa0a41401335d3f4e46893be906e90e2290074 /kernel/fork.c
parentf4205a53c8f5184e0275ed30dc9f20e1d5d69015 (diff)
[PATCH] kill CLONE_IDLETASK
The sole remaining usage of CLONE_IDLETASK is to determine whether pid allocation should be performed in copy_process(). This patch eliminates that last branch on CLONE_IDLETASK in the normal process creation path, removes the masking of CLONE_IDLETASK from clone_flags as it's now ignored under all circumstances, and furthermore eliminates the symbol CLONE_IDLETASK entirely. From: William Lee Irwin III <wli@holomorphy.com> Fix the fork-idle consolidation. During that consolidation, the generic code was made to pass a pointer to on-stack pt_regs that had been memset() to 0. ia64, however, requires a NULL pt_regs pointer argument and dispatches on that in its copy_thread() function to do SMP trampoline-specific RSE -related setup. Passing pointers to zeroed pt_regs resulted in SMP wakeup -time deadlocks and exceptions. 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.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 5bc6a0aae69f..cc0aa2726a84 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -45,9 +45,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-/* set if new pid should be 0 (kernel only)*/
-#define CLONE_IDLETASK 0x00001000
-
/* The idle threads do not count..
* Protected by write_lock_irq(&tasklist_lock)
*/
@@ -897,7 +894,8 @@ static task_t *copy_process(unsigned long clone_flags,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
- int __user *child_tidptr)
+ int __user *child_tidptr,
+ int pid)
{
int retval;
struct task_struct *p = NULL;
@@ -957,13 +955,7 @@ static task_t *copy_process(unsigned long clone_flags,
p->did_exec = 0;
copy_flags(clone_flags, p);
- if (clone_flags & CLONE_IDLETASK)
- p->pid = 0;
- else {
- p->pid = alloc_pidmap();
- if (p->pid == -1)
- goto bad_fork_cleanup;
- }
+ p->pid = pid;
retval = -EFAULT;
if (clone_flags & CLONE_PARENT_SETTID)
if (put_user(p->pid, parent_tidptr))
@@ -1166,8 +1158,6 @@ bad_fork_cleanup_policy:
mpol_free(p->mempolicy);
#endif
bad_fork_cleanup:
- if (p->pid > 0)
- free_pidmap(p->pid);
if (p->binfmt)
module_put(p->binfmt->module);
bad_fork_cleanup_put_domain:
@@ -1181,13 +1171,18 @@ bad_fork_free:
goto fork_out;
}
+struct pt_regs * __init __attribute__((weak)) idle_regs(struct pt_regs *regs)
+{
+ memset(regs, 0, sizeof(struct pt_regs));
+ return regs;
+}
+
task_t * __init fork_idle(int cpu)
{
task_t *task;
struct pt_regs regs;
- memset(&regs, 0, sizeof(struct pt_regs));
- task = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+ task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
if (!task)
return ERR_PTR(-ENOMEM);
init_idle(task, cpu);
@@ -1226,22 +1221,21 @@ long do_fork(unsigned long clone_flags,
{
struct task_struct *p;
int trace = 0;
- long pid;
+ long pid = alloc_pidmap();
- clone_flags &= ~CLONE_IDLETASK;
+ if (pid < 0)
+ return -EAGAIN;
if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags);
if (trace)
clone_flags |= CLONE_PTRACE;
}
- p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
+ p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
*/
- pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
-
if (!IS_ERR(p)) {
struct completion vfork;
@@ -1274,6 +1268,9 @@ long do_fork(unsigned long clone_flags,
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
}
+ } else {
+ free_pidmap(pid);
+ pid = PTR_ERR(p);
}
return pid;
}