Commit 69c46983 authored by William Lee Irwin III's avatar William Lee Irwin III Committed by Linus Torvalds

[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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f4205a53
...@@ -356,6 +356,11 @@ start_secondary (void *unused) ...@@ -356,6 +356,11 @@ start_secondary (void *unused)
return cpu_idle(); return cpu_idle();
} }
struct pt_regs * __init idle_regs(struct pt_regs *regs)
{
return NULL;
}
struct create_idle { struct create_idle {
struct task_struct *idle; struct task_struct *idle;
struct completion done; struct completion done;
......
...@@ -45,9 +45,6 @@ ...@@ -45,9 +45,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
/* set if new pid should be 0 (kernel only)*/
#define CLONE_IDLETASK 0x00001000
/* The idle threads do not count.. /* The idle threads do not count..
* Protected by write_lock_irq(&tasklist_lock) * Protected by write_lock_irq(&tasklist_lock)
*/ */
...@@ -897,7 +894,8 @@ static task_t *copy_process(unsigned long clone_flags, ...@@ -897,7 +894,8 @@ static task_t *copy_process(unsigned long clone_flags,
struct pt_regs *regs, struct pt_regs *regs,
unsigned long stack_size, unsigned long stack_size,
int __user *parent_tidptr, int __user *parent_tidptr,
int __user *child_tidptr) int __user *child_tidptr,
int pid)
{ {
int retval; int retval;
struct task_struct *p = NULL; struct task_struct *p = NULL;
...@@ -957,13 +955,7 @@ static task_t *copy_process(unsigned long clone_flags, ...@@ -957,13 +955,7 @@ static task_t *copy_process(unsigned long clone_flags,
p->did_exec = 0; p->did_exec = 0;
copy_flags(clone_flags, p); copy_flags(clone_flags, p);
if (clone_flags & CLONE_IDLETASK) p->pid = pid;
p->pid = 0;
else {
p->pid = alloc_pidmap();
if (p->pid == -1)
goto bad_fork_cleanup;
}
retval = -EFAULT; retval = -EFAULT;
if (clone_flags & CLONE_PARENT_SETTID) if (clone_flags & CLONE_PARENT_SETTID)
if (put_user(p->pid, parent_tidptr)) if (put_user(p->pid, parent_tidptr))
...@@ -1166,8 +1158,6 @@ static task_t *copy_process(unsigned long clone_flags, ...@@ -1166,8 +1158,6 @@ static task_t *copy_process(unsigned long clone_flags,
mpol_free(p->mempolicy); mpol_free(p->mempolicy);
#endif #endif
bad_fork_cleanup: bad_fork_cleanup:
if (p->pid > 0)
free_pidmap(p->pid);
if (p->binfmt) if (p->binfmt)
module_put(p->binfmt->module); module_put(p->binfmt->module);
bad_fork_cleanup_put_domain: bad_fork_cleanup_put_domain:
...@@ -1181,13 +1171,18 @@ static task_t *copy_process(unsigned long clone_flags, ...@@ -1181,13 +1171,18 @@ static task_t *copy_process(unsigned long clone_flags,
goto fork_out; 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 * __init fork_idle(int cpu)
{ {
task_t *task; task_t *task;
struct pt_regs regs; struct pt_regs regs;
memset(&regs, 0, sizeof(struct pt_regs)); task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
task = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
if (!task) if (!task)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
init_idle(task, cpu); init_idle(task, cpu);
...@@ -1226,22 +1221,21 @@ long do_fork(unsigned long clone_flags, ...@@ -1226,22 +1221,21 @@ long do_fork(unsigned long clone_flags,
{ {
struct task_struct *p; struct task_struct *p;
int trace = 0; int trace = 0;
long pid; long pid = alloc_pidmap();
clone_flags &= ~CLONE_IDLETASK; if (pid < 0)
return -EAGAIN;
if (unlikely(current->ptrace)) { if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags); trace = fork_traceflag (clone_flags);
if (trace) if (trace)
clone_flags |= CLONE_PTRACE; 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 * Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly. * might get invalid after that point, if the thread exits quickly.
*/ */
pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
if (!IS_ERR(p)) { if (!IS_ERR(p)) {
struct completion vfork; struct completion vfork;
...@@ -1274,6 +1268,9 @@ long do_fork(unsigned long clone_flags, ...@@ -1274,6 +1268,9 @@ long do_fork(unsigned long clone_flags,
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
} }
} else {
free_pidmap(pid);
pid = PTR_ERR(p);
} }
return pid; return pid;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment