Commit 9fb72010 authored by Linus Torvalds's avatar Linus Torvalds

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.
parent c57f6cae
...@@ -608,22 +608,20 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) ...@@ -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 * This creates a new process as a copy of the old one,
* information (task[nr]) and sets up the necessary registers. It also * but does not actually start it yet.
* copies the data segment in its entirety. The "stack_start" and *
* "stack_top" arguments are simply passed along to the platform * It copies the registers, and all the appropriate
* specific copy_thread() routine. Most platforms ignore stack_top. * parts of the process environment (as per the clone
* For an example that's using stack_top, see * flags). The actual kick-off is left to the caller.
* arch/ia64/kernel/process.c.
*/ */
struct task_struct *do_fork(unsigned long clone_flags, static struct task_struct *copy_process(unsigned long clone_flags,
unsigned long stack_start, unsigned long stack_start,
struct pt_regs *regs, struct pt_regs *regs,
unsigned long stack_size) unsigned long stack_size)
{ {
int retval; int retval;
struct task_struct *p = NULL; struct task_struct *p = NULL;
struct completion vfork;
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -680,10 +678,6 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -680,10 +678,6 @@ struct task_struct *do_fork(unsigned long clone_flags,
INIT_LIST_HEAD(&p->sibling); INIT_LIST_HEAD(&p->sibling);
init_waitqueue_head(&p->wait_chldexit); init_waitqueue_head(&p->wait_chldexit);
p->vfork_done = NULL; 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->alloc_lock);
spin_lock_init(&p->switch_lock); spin_lock_init(&p->switch_lock);
...@@ -803,20 +797,6 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -803,20 +797,6 @@ struct task_struct *do_fork(unsigned long clone_flags,
hash_pid(p); hash_pid(p);
nr_threads++; nr_threads++;
write_unlock_irq(&tasklist_lock); 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; retval = 0;
fork_out: fork_out:
...@@ -850,6 +830,45 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -850,6 +830,45 @@ struct task_struct *do_fork(unsigned long clone_flags,
goto fork_out; 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) */ /* SLAB cache for signal_struct structures (tsk->sig) */
kmem_cache_t *sigact_cachep; kmem_cache_t *sigact_cachep;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment