[PATCH] Hotplug CPU prep
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 13 May 2002 06:52:31 +0000 (23:52 -0700)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 13 May 2002 06:52:31 +0000 (23:52 -0700)
This changes do_fork() to return the task struct, rather than the PID.

Also changes CLONE_PID ("if my pid is 0, copy it") to CLONE_IDLETASK
("set child's pid to zero"), and disallows access to the flag from user
mode.

36 files changed:
arch/alpha/kernel/process.c
arch/alpha/kernel/smp.c
arch/arm/kernel/sys_arm.c
arch/cris/kernel/process.c
arch/i386/kernel/process.c
arch/i386/kernel/smpboot.c
arch/ia64/ia32/ia32_entry.S
arch/ia64/kernel/entry.S
arch/ia64/kernel/smpboot.c
arch/m68k/kernel/process.c
arch/mips/kernel/smp.c
arch/mips/kernel/syscall.c
arch/mips64/kernel/syscall.c
arch/mips64/sgi-ip27/ip27-init.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/process.c
arch/ppc/kernel/process.c
arch/ppc/kernel/smp.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/smp.c
arch/s390/kernel/process.c
arch/s390/kernel/smp.c
arch/s390x/kernel/process.c
arch/s390x/kernel/smp.c
arch/sh/kernel/process.c
arch/sparc/kernel/entry.S
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/smp.c
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/process.c
arch/x86_64/kernel/smpboot.c
include/linux/sched.h
kernel/fork.c

index 84871a5..8bc1ea5 100644 (file)
@@ -260,16 +260,22 @@ int
 alpha_clone(unsigned long clone_flags, unsigned long usp,
            struct switch_stack * swstack)
 {
+       struct task_struct *p;
        if (!usp)
                usp = rdusp();
-       return do_fork(clone_flags, usp, (struct pt_regs *) (swstack+1), 0);
+
+       p = do_fork(clone_flags & ~CLONE_IDLETASK,
+                   usp, (struct pt_regs *) (swstack+1), 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int
 alpha_vfork(struct switch_stack * swstack)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-                       (struct pt_regs *) (swstack+1), 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
+                   (struct pt_regs *) (swstack+1), 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 43370f3..45e5f58 100644 (file)
@@ -433,13 +433,13 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
        return 0;
 }
 
-static int __init
+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 do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 }
 
 /*
@@ -457,13 +457,10 @@ smp_boot_one_cpu(int cpuid, int cpunum)
           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.  */
-       if (fork_by_hand() < 0)
+       idle = fork_by_hand();
+       if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpuid);
 
-       idle = prev_task(&init_task);
-       if (!idle)
-               panic("No idle process for CPU %d", cpuid);
-
        init_idle(idle, cpuid);
        unhash_process(idle);
 
index 34023b9..e41a110 100644 (file)
@@ -238,7 +238,9 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
  */
 asmlinkage int sys_fork(struct pt_regs *regs)
 {
-       return do_fork(SIGCHLD, regs->ARM_sp, regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, regs->ARM_sp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /* Clone a task - this clones the calling program thread.
@@ -246,14 +248,18 @@ asmlinkage int sys_fork(struct pt_regs *regs)
  */
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
 {
+       struct task_struct *p;
        if (!newsp)
                newsp = regs->ARM_sp;
-       return do_fork(clone_flags, newsp, regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /* sys_execve() executes a new program.
index 3726347..9eb5b73 100644 (file)
@@ -299,7 +299,9 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
                        struct pt_regs *regs)
 {
-       return do_fork(SIGCHLD, rdusp(), regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, rdusp(), regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /* if newusp is 0, we just grab the old usp */
@@ -308,9 +310,11 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
                         long r12, long r13, long mof, long srp,
                         struct pt_regs *regs)
 {
+       struct task_struct *p;
        if (!newusp)
                newusp = rdusp();
-       return do_fork(flags, newusp, regs, 0);
+       p = do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /* vfork is a system call in i386 because of register-pressure - maybe
@@ -320,7 +324,9 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
 asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
                         struct pt_regs *regs)
 {
-        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
+       struct task_struct *p;
+        p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 3f3db75..b077dc2 100644 (file)
@@ -711,11 +711,15 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
-       return do_fork(SIGCHLD, regs.esp, &regs, 0);
+       struct task_struct *p;
+
+       p = do_fork(SIGCHLD, regs.esp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
+       struct task_struct *p;
        unsigned long clone_flags;
        unsigned long newsp;
 
@@ -723,7 +727,8 @@ asmlinkage int sys_clone(struct pt_regs regs)
        newsp = regs.ecx;
        if (!newsp)
                newsp = regs.esp;
-       return do_fork(clone_flags, newsp, &regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -738,7 +743,10 @@ asmlinkage int sys_clone(struct pt_regs regs)
  */
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
+       struct task_struct *p;
+
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index d1a3b69..31641d3 100644 (file)
@@ -529,14 +529,14 @@ extern struct {
        unsigned short ss;
 } stack_start;
 
-static int __init fork_by_hand(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 do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 }
 
 /* which physical APIC ID maps to which logical CPU number */
@@ -822,17 +822,14 @@ static void __init do_boot_cpu (int apicid)
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
         */
-       if (fork_by_hand() < 0)
+       idle = fork_by_hand();
+       if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
 
        /*
         * We remove it from the pidhash and the runqueue
         * once we got the process:
         */
-       idle = prev_task(&init_task);
-       if (!idle)
-               panic("No idle process for CPU %d", cpu);
-
        init_idle(idle, cpu);
 
        map_cpu_to_boot_apicid(cpu, apicid);
index f3e7e95..1cde788 100644 (file)
@@ -41,7 +41,7 @@ ENTRY(ia32_clone)
        mov out3=16                             // stacksize (compensates for 16-byte scratch area)
        adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
        zxt4 out0=in0                           // out0 = clone_flags
-       br.call.sptk.many rp=do_fork
+       br.call.sptk.many rp=do_fork_WITHOUT_CLONE_IDLETASK             // FIXME: mask out CLONE_IDLETASK from flags, and return value now task_struct *.
 .ret0: .restore sp
        adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
        mov ar.pfs=loc1
@@ -167,7 +167,7 @@ GLOBAL_ENTRY(sys32_fork)
        mov out1=0
        mov out3=0
        adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
-       br.call.sptk.few rp=do_fork
+       br.call.sptk.few rp=do_fork_FIXME_RETURNS_TASK_STRUCT
 .ret5: mov ar.pfs=loc1
        .restore sp
        adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
index 5760abe..3f053c9 100644 (file)
@@ -101,7 +101,7 @@ GLOBAL_ENTRY(sys_clone2)
        mov out3=in2
        adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
        mov out0=in0                            // out0 = clone_flags
-       br.call.sptk.many rp=do_fork
+       br.call.sptk.many rp=do_fork_WITHOUT_CLONE_IDLETASK // FIXME: mask out CLONE_IDLETASK from flags, and now returns task_struct *.
 .ret1: .restore sp
        adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
        mov ar.pfs=loc1
@@ -120,7 +120,7 @@ GLOBAL_ENTRY(sys_clone)
        mov out3=16                             // stacksize (compensates for 16-byte scratch area)
        adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
        mov out0=in0                            // out0 = clone_flags
-       br.call.sptk.many rp=do_fork
+       br.call.sptk.many rp=do_fork_WITHOUT_CLONE_IDLETASK // FIXME: mask out CLONE_IDLETASK from flags, and now return task_struct *.
 .ret2: .restore sp
        adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
        mov ar.pfs=loc1
index fcc10d7..7a1fdee 100644 (file)
@@ -391,14 +391,14 @@ start_secondary (void *unused)
        return cpu_idle();
 }
 
-static int __init
+static struct task_struct * __init
 fork_by_hand (void)
 {
        /*
         * don't care about the eip and regs settings since
         * we'll never reschedule the forked task.
         */
-       return do_fork(CLONE_VM|CLONE_PID, 0, 0, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, 0, 0);
 }
 
 static void __init
@@ -412,17 +412,14 @@ do_boot_cpu (int sapicid)
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
         */
-       if (fork_by_hand() < 0)
+       idle = fork_by_hand();
+       if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
 
        /*
         * We remove it from the pidhash and the runqueue
         * once we got the process:
         */
-       idle = prev_task(&init_task);
-       if (!idle)
-               panic("No idle process for CPU %d", cpu);
-
        init_idle(idle, cpu);
 
        ia64_cpu_to_sapicid[cpu] = sapicid;
index f7802c1..2e57f75 100644 (file)
@@ -177,25 +177,31 @@ void flush_thread(void)
 
 asmlinkage int m68k_fork(struct pt_regs *regs)
 {
-       return do_fork(SIGCHLD, rdusp(), regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, rdusp(), regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int m68k_vfork(struct pt_regs *regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int m68k_clone(struct pt_regs *regs)
 {
        unsigned long clone_flags;
        unsigned long newsp;
+       struct task_struct *p;
 
        /* syscall2 puts clone_flags in d1 and usp in d2 */
        clone_flags = regs->d1;
        newsp = regs->d2;
        if (!newsp)
                newsp = rdusp();
-       return do_fork(clone_flags, newsp, regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
index 9ea43d1..6157e23 100644 (file)
@@ -122,8 +122,7 @@ void __init smp_boot_cpus(void)
 
                /* Spawn a new process normally.  Grab a pointer to
                   its task struct so we can mess with it */
-               do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
-               p = prev_task(&init_task);
+               p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 
                /* Schedule the first task manually */
                p->processor = i;
@@ -151,7 +150,7 @@ void __init smp_boot_cpus(void)
                 * The following code is purely to make sure
                 * Linux can schedule processes on this slave.
                 */
-               kernel_thread(0, NULL, CLONE_PID);
+               kernel_thread(0, NULL, CLONE_IDLETASK);
                p = prev_task(&init_task);
                sprintf(p->comm, "%s%d", "Idle", i);
                init_tasks[i] = p;
index 0a8f796..afbce4d 100644 (file)
@@ -95,10 +95,10 @@ sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
 save_static_function(sys_fork);
 static_unused int _sys_fork(struct pt_regs regs)
 {
-       int res;
+       struct task_struct *p;
 
-       res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
-       return res;
+       p = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 
@@ -107,14 +107,14 @@ static_unused int _sys_clone(struct pt_regs regs)
 {
        unsigned long clone_flags;
        unsigned long newsp;
-       int res;
+       struct task_struct *p;
 
        clone_flags = regs.regs[4];
        newsp = regs.regs[5];
        if (!newsp)
                newsp = regs.regs[29];
-       res = do_fork(clone_flags, newsp, &regs, 0);
-       return res;
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index c54e478..6daab49 100644 (file)
@@ -77,26 +77,26 @@ out:
 
 asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs)
 {
-       int res;
+       struct task_struct *p;
 
        save_static(&regs);
-       res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
-       return res;
+       p = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs)
 {
        unsigned long clone_flags;
        unsigned long newsp;
-       int res;
+       struct task_struct *p;
 
        save_static(&regs);
        clone_flags = regs.regs[4];
        newsp = regs.regs[5];
        if (!newsp)
                newsp = regs.regs[29];
-       res = do_fork(clone_flags, newsp, &regs, 0);
-       return res;
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index d6f4a5e..191b440 100644 (file)
@@ -490,7 +490,7 @@ void allowboot(void)
                         * The following code is purely to make sure
                         * Linux can schedule processes on this slave.
                         */
-                       kernel_thread(0, NULL, CLONE_PID);
+                       kernel_thread(0, NULL, CLONE_IDLETASK);
                        p = prev_task(&init_task);
                        sprintf(p->comm, "%s%d", "Idle", num_cpus);
                        init_tasks[num_cpus] = p;
index 86bfbdd..dbc889a 100644 (file)
@@ -500,7 +500,7 @@ __kernel_thread:
        ldo     CLONE_VM(%r0), %r26   /* Force CLONE_VM since only init_mm */
        or      %r26, %r24, %r26      /* will have kernel mappings.      */
        copy    %r0, %r25
-       bl      do_fork, %r2
+       bl      do_fork_FIXME_NOW_RETURNS_TASK_STRUCT, %r2
        copy    %r1, %r24
 
        /* Parent Returns here */
index c49239b..fecfdd4 100644 (file)
@@ -159,14 +159,17 @@ int
 sys_clone(unsigned long clone_flags, unsigned long usp,
          struct pt_regs *regs)
 {
-       return do_fork(clone_flags, usp, regs, 0);
+       struct task_struct *p;
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int
 sys_vfork(struct pt_regs *regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-                      regs->gr[30], regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int
index 0531555..8435867 100644 (file)
@@ -437,22 +437,28 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
 int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
              struct pt_regs *regs)
 {
+       struct task_struct *p;
        CHECK_FULL_REGS(regs);
-       return do_fork(p1, regs->gpr[1], regs, 0);
+       p = do_fork(p1 & ~CLONE_IDLETASK, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
             struct pt_regs *regs)
 {
+       struct task_struct *p;
        CHECK_FULL_REGS(regs);
-       return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
+       p = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
              struct pt_regs *regs)
 {
+       struct task_struct *p;
        CHECK_FULL_REGS(regs);
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
index cd14604..738c81b 100644 (file)
@@ -343,11 +343,9 @@ void __init smp_boot_cpus(void)
                /* create a process for the processor */
                /* only regs.msr is actually used, and 0 is OK for it */
                memset(&regs, 0, sizeof(struct pt_regs));
-               if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
+               p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+               if (IS_ERR(p))
                        panic("failed fork for CPU %d", i);
-               p = prev_task(&init_task);
-               if (!p)
-                       panic("No idle task for CPU %d", i);
                init_idle(p, i);
                unhash_process(p);
 
index 634b5f0..97398fb 100644 (file)
@@ -256,19 +256,25 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
 int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
              struct pt_regs *regs)
 {
-       return do_fork(p1, regs->gpr[1], regs, 0);
+       struct task_struct *p;
+       p = do_fork(p1 & ~CLONE_IDLETASK, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
             struct pt_regs *regs)
 {
-       return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
                         struct pt_regs *regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
index 2b6db6c..951691a 100644 (file)
@@ -640,11 +640,9 @@ void __init smp_boot_cpus(void)
 
                memset(&regs, 0, sizeof(struct pt_regs));
 
-               if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
+               p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+               if (IS_ERR(p))
                        panic("failed fork for CPU %d", i);
-               p = prev_task(&init_task);
-               if (!p)
-                       panic("No idle task for CPU %d", i);
 
                init_idle(p, i);
 
index 9ae8a63..3a37b6f 100644 (file)
@@ -332,19 +332,23 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
-        return do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+       struct task_struct *p;
+        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
         unsigned long clone_flags;
         unsigned long newsp;
+       struct task_struct *p;
 
         clone_flags = regs.gprs[3];
         newsp = regs.orig_gpr2;
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags, newsp, &regs, 0);
+        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -359,8 +363,9 @@ asmlinkage int sys_clone(struct pt_regs regs)
  */
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-                       regs.gprs[15], &regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.gprs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 9e1c5dd..5c269b8 100644 (file)
@@ -505,13 +505,13 @@ void __init initialize_secondary(void)
 {
 }
 
-static int __init fork_by_hand(void)
+static struct task_struct *__init fork_by_hand(void)
 {
        struct pt_regs regs;
        /* don't care about the psw and regs settings since we'll never
           reschedule the forked task. */
        memset(&regs,0,sizeof(struct pt_regs));
-       return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 }
 
 static void __init do_boot_cpu(int cpu)
@@ -521,16 +521,14 @@ static void __init do_boot_cpu(int cpu)
 
         /* We can't use kernel_thread since we must _avoid_ to reschedule
            the child. */
-        if (fork_by_hand() < 0)
+        idle = fork_by_hand();
+       if (IS_ERR(idle))
                 panic("failed fork for CPU %d", cpu);
 
         /*
          * We remove it from the pidhash and the runqueue
          * once we got the process:
          */
-        idle = prev_task(&init_task);
-        if (!idle)
-                panic("No idle process for CPU %d",cpu);
         idle->processor = cpu;
        idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
 
index caa8b60..04ca3d6 100644 (file)
@@ -331,19 +331,23 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
-        return do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+       struct task_struct *p;
+        p = do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
         unsigned long clone_flags;
         unsigned long newsp;
+       struct task_struct *p;
 
         clone_flags = regs.gprs[3];
         newsp = regs.orig_gpr2;
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags, newsp, &regs, 0);
+        p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -358,8 +362,9 @@ asmlinkage int sys_clone(struct pt_regs regs)
  */
 asmlinkage int sys_vfork(struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
-                       regs.gprs[15], &regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.gprs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 4f781c3..6c9c37f 100644 (file)
@@ -484,13 +484,13 @@ void __init initialize_secondary(void)
 {
 }
 
-static int __init fork_by_hand(void)
+static struct task_struct * __init fork_by_hand(void)
 {
        struct pt_regs regs;
        /* don't care about the psw and regs settings since we'll never
           reschedule the forked task. */
        memset(&regs,0,sizeof(struct pt_regs));
-       return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 }
 
 static void __init do_boot_cpu(int cpu)
@@ -500,16 +500,14 @@ static void __init do_boot_cpu(int cpu)
 
         /* We can't use kernel_thread since we must _avoid_ to reschedule
            the child. */
-        if (fork_by_hand() < 0)
+        idle = fork_by_hand();
+       if (IS_ERR(idle))
                 panic("failed fork for CPU %d", cpu);
 
         /*
          * We remove it from the pidhash and the runqueue
          * once we got the process:
          */
-        idle = prev_task(&init_task);
-        if (!idle)
-                panic("No idle process for CPU %d",cpu);
         idle->processor = cpu;
        idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
 
index 6d11338..4c897ef 100644 (file)
@@ -276,16 +276,20 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
                        unsigned long r6, unsigned long r7,
                        struct pt_regs regs)
 {
-       return do_fork(SIGCHLD, regs.regs[15], &regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, regs.regs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs regs)
 {
+       struct task_struct *p;
        if (!newsp)
                newsp = regs.regs[15];
-       return do_fork(clone_flags, newsp, &regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -302,7 +306,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 48a26da..da3261a 100644 (file)
@@ -1393,7 +1393,7 @@ flush_patch_two:
        std     %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
        add     %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
        mov     0, %o3
-       call    C_LABEL(do_fork)
+       call    C_LABEL(do_fork_FIXME_NOW_RETURNS_TASK_STRUCT)
         mov    %l5, %o7
        
        /* Whee, kernel threads! */
@@ -1416,7 +1416,8 @@ flush_patch_three:
        std     %g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
        add     %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
        mov     0, %o3
-       call    C_LABEL(do_fork)
+       /* FIXME:       remove CLONE_IDLETASK from flags first */
+       call    C_LABEL(do_fork_WITHOUT_CLONE_IDLETASK)
         mov    %l5, %o7
 
        /* Whee, real vfork! */
@@ -1432,9 +1433,9 @@ flush_patch_four:
        sethi   %hi(0x4000 | 0x0100 | SIGCHLD), %o0
        mov     %fp, %o1
        or      %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
-       sethi   %hi(C_LABEL(do_fork)), %l1
+       sethi   %hi(C_LABEL(do_fork_FIXME_NOW_RETURNS_TASK_STRUCT)), %l1
        mov     0, %o3
-       jmpl    %l1 + %lo(C_LABEL(do_fork)), %g0
+       jmpl    %l1 + %lo(C_LABEL(do_fork_FIXME_NOW_RETURNS_TASK_STRUCT)), %g0
         add    %sp, REGWIN_SZ, %o2
 
         .align  4
index 248cc71..234bd35 100644 (file)
@@ -214,7 +214,7 @@ void __init smp4d_boot_cpus(void)
                        int no;
 
                        /* Cook up an idler for this guy. */
-                       kernel_thread(start_secondary, NULL, CLONE_PID);
+                       kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
 
                        cpucount++;
 
index 7641b26..0837605 100644 (file)
@@ -187,7 +187,7 @@ void __init smp4m_boot_cpus(void)
                        int timeout;
 
                        /* Cook up an idler for this guy. */
-                       kernel_thread(start_secondary, NULL, CLONE_PID);
+                       kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
 
                        cpucount++;
 
index 5af0275..5989903 100644 (file)
@@ -1429,7 +1429,7 @@ sys_fork:  clr            %o1
 sys_clone:     flushw
                movrz           %o1, %fp, %o1
                mov             0, %o3
-               ba,pt           %xcc, do_fork
+               ba,pt           %xcc, do_fork_FIXME_NOW_RETURNS_TASK_STRUCT
                 add            %sp, STACK_BIAS + REGWIN_SZ, %o2
 ret_from_syscall:
                /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
index 1c1e51e..9575623 100644 (file)
@@ -268,7 +268,7 @@ void __init smp_boot_cpus(void)
                        int no;
 
                        prom_printf("Starting CPU %d... ", i);
-                       kernel_thread(NULL, NULL, CLONE_PID);
+                       kernel_thread(NULL, NULL, CLONE_IDLETASK);
                        cpucount++;
 
                        p = prev_task(&init_task);
index 1ec9ea4..409bd78 100644 (file)
@@ -2683,14 +2683,18 @@ free:
 
 asmlinkage int sys32_fork(struct pt_regs regs)
 {
-       return do_fork(SIGCHLD, regs.rsp, &regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, regs.rsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage int sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs)
 {
+       struct task_struct *p;
        if (!newsp)
                newsp = regs.rsp;
-       return do_fork(clone_flags, newsp, &regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -2705,7 +2709,9 @@ asmlinkage int sys32_clone(unsigned int clone_flags, unsigned int newsp, struct
  */
 asmlinkage int sys32_vfork(struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 16c6e3f..79877bb 100644 (file)
@@ -570,7 +570,7 @@ ENTRY(kernel_thread)
        movq %rsp, %rdx
 
        # clone now
-       call do_fork
+       call do_fork_FIXME_NOW_RETURNS_TASK_STRUCT
        # save retval on the stack so it's popped before `ret`
        movq %rax, RAX(%rsp)
 
index 878802a..d2f587e 100644 (file)
@@ -608,14 +608,18 @@ void set_personality_64bit(void)
 
 asmlinkage long sys_fork(struct pt_regs regs)
 {
-       return do_fork(SIGCHLD, regs.rsp, &regs, 0);
+       struct task_struct *p;
+       p = do_fork(SIGCHLD, regs.rsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs regs)
 {
+       struct task_struct *p;
        if (!newsp)
                newsp = regs.rsp;
-       return do_fork(clone_flags, newsp, &regs, 0);
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -630,7 +634,9 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, struct
  */
 asmlinkage long sys_vfork(struct pt_regs regs)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0);
+       struct task_struct *p;
+       p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0);
+       return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
index 417ee68..6651ff1 100644 (file)
@@ -476,14 +476,14 @@ void __init initialize_secondary(void)
 extern volatile unsigned long init_rsp; 
 extern void (*initial_code)(void);
 
-static int __init fork_by_hand(void)
+static struct task_struct * __init fork_by_hand(void)
 {
        struct pt_regs regs;
        /*
         * don't care about the rip and regs settings since
         * we'll never reschedule the forked task.
         */
-       return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+       return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
 }
 
 #if APIC_DEBUG
@@ -538,17 +538,14 @@ static void __init do_boot_cpu (int apicid)
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
         */
-       if (fork_by_hand() < 0)
+       idle = fork_by_hand();
+       if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
 
        /*
         * We remove it from the pidhash and the runqueue
         * once we got the process:
         */
-       idle = prev_task(&init_task);
-       if (!idle)
-               panic("No idle process for CPU %d", cpu);
-
        init_idle(idle,cpu);
 
        x86_cpu_to_apicid[cpu] = apicid;
index fdf83fa..392d217 100644 (file)
@@ -39,7 +39,7 @@ struct exec_domain;
 #define CLONE_FS       0x00000200      /* set if fs info shared between processes */
 #define CLONE_FILES    0x00000400      /* set if open files shared between processes */
 #define CLONE_SIGHAND  0x00000800      /* set if signal handlers and blocked signals shared */
-#define CLONE_PID      0x00001000      /* set if pid shared */
+#define CLONE_IDLETASK 0x00001000      /* set if new pid should be 0 (kernel only)*/
 #define CLONE_PTRACE   0x00002000      /* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK    0x00004000      /* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT   0x00008000      /* set if we want to have the same parent as the cloner */
@@ -663,7 +663,7 @@ extern void daemonize(void);
 extern task_t *child_reaper;
 
 extern int do_execve(char *, char **, char **, struct pt_regs *);
-extern int do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long);
+extern struct task_struct *do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long);
 
 extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
index 61a6c77..3a77871 100644 (file)
@@ -136,8 +136,8 @@ static int get_pid(unsigned long flags)
        struct task_struct *p;
        int pid;
 
-       if (flags & CLONE_PID)
-               return current->pid;
+       if (flags & CLONE_IDLETASK)
+               return 0;
 
        spin_lock(&lastpid_lock);
        if((++last_pid) & 0xffff8000) {
@@ -608,27 +608,18 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p)
  * For an example that's using stack_top, see
  * arch/ia64/kernel/process.c.
  */
-int do_fork(unsigned long clone_flags, unsigned long stack_start,
-           struct pt_regs *regs, unsigned long stack_size)
+struct task_struct *do_fork(unsigned long clone_flags,
+                           unsigned long stack_start,
+                           struct pt_regs *regs,
+                           unsigned long stack_size)
 {
        int retval;
        unsigned long flags;
-       struct task_struct *p;
+       struct task_struct *p = NULL;
        struct completion vfork;
 
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
-               return -EINVAL;
-
-       retval = -EPERM;
-
-       /* 
-        * CLONE_PID is only allowed for the initial SMP swapper
-        * calls
-        */
-       if (clone_flags & CLONE_PID) {
-               if (current->pid)
-                       goto fork_out;
-       }
+               return ERR_PTR(-EINVAL);
 
        retval = -ENOMEM;
        p = dup_task_struct(current);
@@ -768,8 +759,7 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
         *
         * Let it rip!
         */
-       retval = p->pid;
-       p->tgid = retval;
+       p->tgid = p->pid;
        INIT_LIST_HEAD(&p->thread_group);
 
        /* Need tasklist lock for parent etc handling! */
@@ -807,9 +797,12 @@ int do_fork(unsigned long clone_flags, unsigned long stack_start,
                 * COW overhead when the child exec()s afterwards.
                 */
                set_need_resched();
+       retval = 0;
 
 fork_out:
-       return retval;
+       if (retval)
+               return ERR_PTR(retval);
+       return p;
 
 bad_fork_cleanup_namespace:
        exit_namespace(p);