From 9fb720106e1e94ded2fb229512c0349a1aba7b51 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 30 Jul 2002 01:49:23 -0700 Subject: Split up "do_fork()" into "copy_process()" and "do_fork()". copy_process() just copies the process, it doesn't actually start it. This is in preparation for doing a "atomically start process on CPU X" or other cases where we want to change the state of the process before we actually start running it. --- kernel/fork.c | 73 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 27 deletions(-) (limited to 'kernel') diff --git a/kernel/fork.c b/kernel/fork.c index dee7097ba082..d40d246ec1df 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -608,22 +608,20 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) } /* - * Ok, this is the main fork-routine. It copies the system process - * information (task[nr]) and sets up the necessary registers. It also - * copies the data segment in its entirety. The "stack_start" and - * "stack_top" arguments are simply passed along to the platform - * specific copy_thread() routine. Most platforms ignore stack_top. - * For an example that's using stack_top, see - * arch/ia64/kernel/process.c. + * This creates a new process as a copy of the old one, + * but does not actually start it yet. + * + * It copies the registers, and all the appropriate + * parts of the process environment (as per the clone + * flags). The actual kick-off is left to the caller. */ -struct task_struct *do_fork(unsigned long clone_flags, +static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size) { int retval; struct task_struct *p = NULL; - struct completion vfork; if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL); @@ -680,10 +678,6 @@ struct task_struct *do_fork(unsigned long clone_flags, INIT_LIST_HEAD(&p->sibling); init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; - if (clone_flags & CLONE_VFORK) { - p->vfork_done = &vfork; - init_completion(&vfork); - } spin_lock_init(&p->alloc_lock); spin_lock_init(&p->switch_lock); @@ -803,20 +797,6 @@ struct task_struct *do_fork(unsigned long clone_flags, hash_pid(p); nr_threads++; write_unlock_irq(&tasklist_lock); - - if (p->ptrace & PT_PTRACED) - send_sig(SIGSTOP, p, 1); - - wake_up_forked_process(p); /* do this last */ - ++total_forks; - if (clone_flags & CLONE_VFORK) - wait_for_completion(&vfork); - else - /* - * Let the child process run first, to avoid most of the - * COW overhead when the child exec()s afterwards. - */ - set_need_resched(); retval = 0; fork_out: @@ -850,6 +830,45 @@ bad_fork_free: goto fork_out; } +/* + * Ok, this is the main fork-routine. + * + * It copies the process, and if successful kick-starts + * it and waits for it to finish using the VM if required. + */ +struct task_struct *do_fork(unsigned long clone_flags, + unsigned long stack_start, + struct pt_regs *regs, + unsigned long stack_size) +{ + struct task_struct *p; + + p = copy_process(clone_flags, stack_start, regs, stack_size); + if (!IS_ERR(p)) { + struct completion vfork; + + if (clone_flags & CLONE_VFORK) { + p->vfork_done = &vfork; + init_completion(&vfork); + } + + if (p->ptrace & PT_PTRACED) + send_sig(SIGSTOP, p, 1); + + wake_up_forked_process(p); /* do this last */ + ++total_forks; + if (clone_flags & CLONE_VFORK) + wait_for_completion(&vfork); + else + /* + * Let the child process run first, to avoid most of the + * COW overhead when the child exec()s afterwards. + */ + set_need_resched(); + } + return p; +} + /* SLAB cache for signal_struct structures (tsk->sig) */ kmem_cache_t *sigact_cachep; -- cgit v1.2.3