From: William Lee Irwin III <wli@holomorphy.com>

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.
DESC
kill-clone_idletask fix
EDESC
From: William Lee Irwin III <wli@holomorphy.com>

It fixes 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>
---

 25-akpm/arch/ia64/kernel/smpboot.c |    5 +++++
 25-akpm/kernel/fork.c              |   37 +++++++++++++++++--------------------
 2 files changed, 22 insertions(+), 20 deletions(-)

diff -puN kernel/fork.c~kill-clone_idletask kernel/fork.c
--- 25/kernel/fork.c~kill-clone_idletask	2004-08-17 00:05:27.790356376 -0700
+++ 25-akpm/kernel/fork.c	2004-08-17 00:05:27.795355616 -0700
@@ -46,9 +46,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)
  */
@@ -898,7 +895,8 @@ static task_t *copy_process(unsigned lon
 				 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;
@@ -958,13 +956,7 @@ static task_t *copy_process(unsigned lon
 
 	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))
@@ -1173,8 +1165,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:
@@ -1188,13 +1178,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);
@@ -1233,22 +1228,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;
 
@@ -1281,6 +1275,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;
 }
diff -puN arch/ia64/kernel/smpboot.c~kill-clone_idletask arch/ia64/kernel/smpboot.c
--- 25/arch/ia64/kernel/smpboot.c~kill-clone_idletask	2004-08-17 00:05:27.791356224 -0700
+++ 25-akpm/arch/ia64/kernel/smpboot.c	2004-08-17 00:05:27.796355464 -0700
@@ -356,6 +356,11 @@ start_secondary (void *unused)
 	return cpu_idle();
 }
 
+struct pt_regs * __init idle_regs(struct pt_regs *regs)
+{
+	return NULL;
+}
+
 struct create_idle {
 	struct task_struct *idle;
 	struct completion done;
_