From: William Lee Irwin III 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 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 --- 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 #include -/* 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(®s, 0, sizeof(struct pt_regs)); - task = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + task = copy_process(CLONE_VM, 0, idle_regs(®s), 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; _