From: William Lee Irwin III It appears that init_idle() and fork_by_hand() could be combined into a single method that calls init_idle() on behalf of the caller. Signed-off-by: Andrew Morton --- 25-akpm/arch/alpha/kernel/smp.c | 14 +------------- 25-akpm/arch/i386/kernel/smpboot.c | 20 +------------------- 25-akpm/arch/i386/mach-voyager/voyager_smp.c | 18 +----------------- 25-akpm/arch/ia64/kernel/smpboot.c | 27 ++++++--------------------- 25-akpm/arch/mips/kernel/smp.c | 18 +----------------- 25-akpm/arch/parisc/kernel/smp.c | 23 +---------------------- 25-akpm/arch/ppc/kernel/smp.c | 7 +------ 25-akpm/arch/ppc64/kernel/smp.c | 10 +--------- 25-akpm/arch/s390/kernel/smp.c | 11 +---------- 25-akpm/arch/sh/kernel/smp.c | 7 +------ 25-akpm/arch/sparc/kernel/sun4d_smp.c | 11 +---------- 25-akpm/arch/sparc64/kernel/smp.c | 9 +-------- 25-akpm/arch/x86_64/kernel/smpboot.c | 18 +----------------- 25-akpm/include/linux/sched.h | 2 +- 25-akpm/init/main.c | 9 --------- 25-akpm/kernel/fork.c | 16 +++++++++++++++- 25-akpm/kernel/sched.c | 8 ++++++++ arch/um/kernel/smp.c | 0 18 files changed, 42 insertions(+), 186 deletions(-) diff -puN arch/alpha/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/alpha/kernel/smp.c --- 25/arch/alpha/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.178277088 -0700 +++ 25-akpm/arch/alpha/kernel/smp.c 2004-08-09 21:59:44.235268424 -0700 @@ -411,15 +411,6 @@ secondary_cpu_start(int cpuid, struct ta return 0; } -static struct task_struct * __init -fork_by_hand(void) -{ - /* Don't care about the contents of regs since we'll never - reschedule the forked task. */ - struct pt_regs regs; - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Bring one cpu online. */ @@ -435,13 +426,10 @@ smp_boot_one_cpu(int cpuid) the other task-y sort of data structures set up like we wish. We can't use kernel_thread since we must avoid rescheduling the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpuid); - init_idle(idle, cpuid); - unhash_process(idle); - DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", cpuid, idle->state, idle->flags)); diff -puN arch/i386/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation arch/i386/kernel/smpboot.c --- 25/arch/i386/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.180276784 -0700 +++ 25-akpm/arch/i386/kernel/smpboot.c 2004-08-09 21:59:44.236268272 -0700 @@ -496,16 +496,6 @@ extern struct { unsigned short ss; } stack_start; -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #ifdef CONFIG_NUMA /* which logical CPUs are on which nodes */ @@ -801,18 +791,10 @@ static int __init do_boot_cpu(int apicid * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - - /* Make this the idle thread */ - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - - /* Remove it from the pidhash */ - unhash_process(idle); - /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); diff -puN arch/i386/mach-voyager/voyager_smp.c~sched-init_idle-fork_by_hand-consolidation arch/i386/mach-voyager/voyager_smp.c --- 25/arch/i386/mach-voyager/voyager_smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.181276632 -0700 +++ 25-akpm/arch/i386/mach-voyager/voyager_smp.c 2004-08-09 21:59:44.238267968 -0700 @@ -523,15 +523,6 @@ start_secondary(void *unused) return cpu_idle(); } -static struct task_struct * __init -fork_by_hand(void) -{ - struct pt_regs regs; - /* don't care about the eip and regs settings since we'll - * never reschedule the forked task. */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* Routine to kick start the given CPU and wait for it to report ready * (or timeout in startup). When this routine returns, the requested @@ -587,17 +578,10 @@ do_boot_cpu(__u8 cpu) hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF; cpucount++; - idle = fork_by_hand(); + idle = fork_idle(cpu); if(IS_ERR(idle)) panic("failed fork for CPU%d", cpu); - - /* Make this the idle thread */ - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - - /* Remove it from the pidhash */ - unhash_process(idle); /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; diff -puN arch/ia64/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation arch/ia64/kernel/smpboot.c --- 25/arch/ia64/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.183276328 -0700 +++ 25-akpm/arch/ia64/kernel/smpboot.c 2004-08-09 21:59:44.239267816 -0700 @@ -356,19 +356,10 @@ start_secondary (void *unused) return cpu_idle(); } -static struct task_struct * __devinit -fork_by_hand (void) -{ - /* - * Don't care about the IP and regs settings since we'll never reschedule the - * forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL); -} - struct create_idle { struct task_struct *idle; struct completion done; + int cpu; }; void @@ -376,7 +367,7 @@ do_fork_idle(void *_c_idle) { struct create_idle *c_idle = _c_idle; - c_idle->idle = fork_by_hand(); + c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); } @@ -384,10 +375,11 @@ static int __devinit do_boot_cpu (int sapicid, int cpu) { int timeout; - struct create_idle c_idle; + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER(c_idle.done), + }; DECLARE_WORK(work, do_fork_idle, &c_idle); - - init_completion(&c_idle.done); /* * We can't use kernel_thread since we must avoid to reschedule the child. */ @@ -400,13 +392,6 @@ do_boot_cpu (int sapicid, int cpu) if (IS_ERR(c_idle.idle)) panic("failed fork for CPU %d", cpu); - - /* Make this the idle thread */ - init_idle(c_idle.idle, cpu); - - /* Remove it from the pidhash */ - unhash_process(c_idle.idle); - task_for_booting_cpu = c_idle.idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); diff -puN arch/mips/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/mips/kernel/smp.c --- 25/arch/mips/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.185276024 -0700 +++ 25-akpm/arch/mips/kernel/smp.c 2004-08-09 21:59:44.239267816 -0700 @@ -254,16 +254,6 @@ void __devinit smp_prepare_boot_cpu(void cpu_set(0, cpu_callin_map); } -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Startup the CPU with this logical number */ @@ -275,16 +265,10 @@ static int __init do_boot_cpu(int cpu) * The following code is purely to make sure * Linux can schedule processes on this slave. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d\n", cpu); - /* Make this the idle thread */ - init_idle(idle, cpu); - - /* Remove it from the pidhash */ - unhash_process(idle); - prom_boot_secondary(cpu, idle); /* XXXKW timeout */ diff -puN arch/parisc/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/parisc/kernel/smp.c --- 25/arch/parisc/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.187275720 -0700 +++ 25-akpm/arch/parisc/kernel/smp.c 2004-08-09 21:59:44.240267664 -0700 @@ -504,24 +504,6 @@ void __init smp_callin(void) #if 0 /* - * Create the idle task for a new Slave CPU. DO NOT use kernel_thread() - * because that could end up calling schedule(). If it did, the new idle - * task could get scheduled before we had a chance to remove it from the - * run-queue... - */ -static struct task_struct *fork_by_hand(void) -{ - struct pt_regs regs; - - /* - * don't care about the regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - - -/* * Bring one cpu online. */ int __init smp_boot_one_cpu(int cpuid, int cpunum) @@ -539,12 +521,9 @@ int __init smp_boot_one_cpu(int cpuid, i * Sheesh . . . */ - idle = fork_by_hand(); + idle = fork_idle(cpunum); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - - init_idle(idle, cpunum); - unhash_process(idle); idle->thread_info->cpu = cpunum; /* Let _start know what logical CPU we're booting diff -puN arch/ppc64/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/ppc64/kernel/smp.c --- 25/arch/ppc64/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.190275264 -0700 +++ 25-akpm/arch/ppc64/kernel/smp.c 2004-08-09 21:59:44.241267512 -0700 @@ -800,20 +800,12 @@ static void __devinit smp_store_cpu_info static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* create a process for the processor */ - /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, - 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - init_idle(p, cpu); - unhash_process(p); - paca[cpu].__current = p; current_set[cpu] = p->thread_info; } diff -puN arch/ppc/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/ppc/kernel/smp.c --- 25/arch/ppc/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.192274960 -0700 +++ 25-akpm/arch/ppc/kernel/smp.c 2004-08-09 21:59:44.242267360 -0700 @@ -364,20 +364,15 @@ int __devinit start_secondary(void *unus int __cpu_up(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; char buf[32]; int c; /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - init_idle(p, cpu); - unhash_process(p); - secondary_ti = p->thread_info; p->thread_info->cpu = cpu; diff -puN arch/s390/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/s390/kernel/smp.c --- 25/arch/s390/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.194274656 -0700 +++ 25-akpm/arch/s390/kernel/smp.c 2004-08-09 21:59:44.242267360 -0700 @@ -562,24 +562,15 @@ int __devinit start_secondary(void *cpuv static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* * don't care about the psw and regs settings since we'll never * reschedule the forked task. */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - /* Make this the idle thread */ - init_idle(p, cpu); - - /* Remove it from the pidhash */ - unhash_process(p); - current_set[cpu] = p; } diff -puN arch/sh/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/sh/kernel/smp.c --- 25/arch/sh/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.196274352 -0700 +++ 25-akpm/arch/sh/kernel/smp.c 2004-08-09 21:59:44.243267208 -0700 @@ -98,17 +98,12 @@ void __devinit smp_prepare_boot_cpu(void int __cpu_up(unsigned int cpu) { struct task_struct *tsk; - struct pt_regs regs; - memset(®s, 0, sizeof(struct pt_regs)); - tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, 0, 0); + tsk = fork_idle(cpu); if (IS_ERR(tsk)) panic("Failed forking idle task for cpu %d\n", cpu); - init_idle(tsk, cpu); - unhash_process(tsk); - tsk->thread_info->cpu = cpu; cpu_set(cpu, cpu_online_map); diff -puN arch/sparc64/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/sparc64/kernel/smp.c --- 25/arch/sparc64/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.198274048 -0700 +++ 25-akpm/arch/sparc64/kernel/smp.c 2004-08-09 21:59:44.244267056 -0700 @@ -302,14 +302,7 @@ static int __devinit smp_boot_one_cpu(un struct task_struct *p; int timeout, ret, cpu_node; - kernel_thread(NULL, NULL, CLONE_IDLETASK); - - p = prev_task(&init_task); - - init_idle(p, cpu); - - unhash_process(p); - + p = fork_idle(cpu); callin_flag = 0; cpu_new_thread = p->thread_info; cpu_set(cpu, cpu_callout_map); diff -puN arch/sparc/kernel/sun4d_smp.c~sched-init_idle-fork_by_hand-consolidation arch/sparc/kernel/sun4d_smp.c --- 25/arch/sparc/kernel/sun4d_smp.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.201273592 -0700 +++ 25-akpm/arch/sparc/kernel/sun4d_smp.c 2004-08-09 21:59:44.244267056 -0700 @@ -201,18 +201,9 @@ void __init smp4d_boot_cpus(void) int no; /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - + p = fork_idle(p, cpu); cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - current_set[i] = p->thread_info; - - unhash_process(p); - for (no = 0; !cpu_find_by_instance(no, NULL, &mid) && mid != i; no++) ; diff -puN arch/um/kernel/smp.c~sched-init_idle-fork_by_hand-consolidation arch/um/kernel/smp.c diff -puN arch/x86_64/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation arch/x86_64/kernel/smpboot.c --- 25/arch/x86_64/kernel/smpboot.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.222270400 -0700 +++ 25-akpm/arch/x86_64/kernel/smpboot.c 2004-08-09 21:59:44.245266904 -0700 @@ -392,16 +392,6 @@ void __init start_secondary(void) extern volatile unsigned long init_rsp; extern void (*initial_code)(void); -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #if APIC_DEBUG static inline void inquire_remote_apic(int apicid) { @@ -575,17 +565,11 @@ static void __init do_boot_cpu (int apic * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); x86_cpu_to_apicid[cpu] = apicid; - /* Make this the idle thread */ - init_idle(idle,cpu); - - /* Remove it from the pidhash */ - unhash_process(idle); - cpu_pda[cpu].pcurrent = idle; start_rip = setup_trampoline(); diff -puN include/linux/sched.h~sched-init_idle-fork_by_hand-consolidation include/linux/sched.h --- 25/include/linux/sched.h~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.224270096 -0700 +++ 25-akpm/include/linux/sched.h 2004-08-09 21:59:44.247266600 -0700 @@ -788,7 +788,7 @@ extern task_t *child_reaper; extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); -extern struct task_struct * copy_process(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); +task_t *fork_idle(int); extern void set_task_comm(struct task_struct *tsk, char *from); extern void get_task_comm(char *to, struct task_struct *tsk); diff -puN init/main.c~sched-init_idle-fork_by_hand-consolidation init/main.c --- 25/init/main.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.226269792 -0700 +++ 25-akpm/init/main.c 2004-08-09 21:59:44.248266448 -0700 @@ -465,15 +465,6 @@ asmlinkage void __init start_kernel(void * time - but meanwhile we still have a functioning scheduler. */ sched_init(); - - /* - * Make us the idle thread. Technically, schedule() should not be - * called from this thread, however somewhere below it might be, - * but because we are the idle thread, we just pick up running again - * when this runqueue becomes "idle". - */ - init_idle(current, smp_processor_id()); - build_all_zonelists(); page_alloc_init(); trap_init(); diff -puN kernel/fork.c~sched-init_idle-fork_by_hand-consolidation kernel/fork.c --- 25/kernel/fork.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.228269488 -0700 +++ 25-akpm/kernel/fork.c 2004-08-09 21:59:44.249266296 -0700 @@ -864,7 +864,7 @@ asmlinkage long sys_set_tid_address(int * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ -struct task_struct *copy_process(unsigned long clone_flags, +static task_t *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, @@ -1152,6 +1152,20 @@ bad_fork_free: goto fork_out; } +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); + if (!task) + return ERR_PTR(-ENOMEM); + init_idle(task, cpu); + unhash_process(task); + return task; +} + static inline int fork_traceflag (unsigned clone_flags) { if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK)) diff -puN kernel/sched.c~sched-init_idle-fork_by_hand-consolidation kernel/sched.c --- 25/kernel/sched.c~sched-init_idle-fork_by_hand-consolidation 2004-08-09 21:59:44.230269184 -0700 +++ 25-akpm/kernel/sched.c 2004-08-09 21:59:44.252265840 -0700 @@ -4535,6 +4535,14 @@ void __init sched_init(void) */ atomic_inc(&init_mm.mm_count); enter_lazy_tlb(&init_mm, current); + + /* + * Make us the idle thread. Technically, schedule() should not be + * called from this thread, however somewhere below it might be, + * but because we are the idle thread, we just pick up running again + * when this runqueue becomes "idle". + */ + init_idle(current, smp_processor_id()); } #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP _