version 1.1.1.1, 2008/06/03 10:38:51 |
version 1.1.1.1.2.1, 2008/08/13 17:12:45 |
|
|
|
|
#include "proc.h" |
#include "proc.h" |
|
|
static int vfork_start(struct proc *proc); |
static int vfork_start(struct proc *); |
|
|
/* |
/* |
* fork() support. |
* fork() support. |
* |
* |
* It creates new process data and update all process relations. |
* It creates new process data and update all process relations. |
* The task creation and the thread creation are done by the fork() |
* The task creation and the thread creation are done by the |
* library stub. |
* fork() library stub. |
*/ |
*/ |
int |
int |
proc_fork(struct msg *msg) |
proc_fork(struct msg *msg) |
|
|
struct pgrp *pgrp; |
struct pgrp *pgrp; |
task_t child; |
task_t child; |
pid_t pid; |
pid_t pid; |
int vfork; |
int vfork_flag; |
|
|
if (curproc == NULL) |
if (curproc == NULL) |
return EINVAL; |
return EINVAL; |
|
|
child = (task_t)msg->data[0]; |
child = (task_t)msg->data[0]; |
vfork = msg->data[1]; |
vfork_flag = msg->data[1]; |
|
|
dprintf("fork: parent=%x child=%x vfork=%d\n", |
DPRINTF(("fork: parent=%x child=%x vfork=%d\n", msg->hdr.task, |
msg->hdr.task, child, vfork); |
child, vfork_flag)); |
|
|
if (task_to_proc(child) != NULL) |
if (task_to_proc(child) != NULL) |
return EINVAL; /* Process already exists */ |
return EINVAL; /* Process already exists */ |
|
|
if ((p = malloc(sizeof(struct proc))) == NULL) |
if ((p = malloc(sizeof(struct proc))) == NULL) |
return ENOMEM; |
return ENOMEM; |
|
|
p->parent = curproc; |
p->p_parent = curproc; |
p->pgrp = curproc->pgrp; |
p->p_pgrp = curproc->p_pgrp; |
p->stat = SRUN; |
p->p_stat = SRUN; |
p->exit_code = 0; |
p->p_exitcode = 0; |
p->pid = pid; |
p->p_pid = pid; |
p->task = child; |
p->p_task = child; |
list_init(&p->children); |
list_init(&p->p_children); |
proc_add(p); |
proc_add(p); |
|
list_insert(&curproc->p_children, &p->p_sibling); |
|
pgrp = p->p_pgrp; |
|
list_insert(&pgrp->pg_members, &p->p_pgrp_link); |
|
list_insert(&allproc, &p->p_link); |
|
|
list_insert(&curproc->children, &p->sibling); |
if (vfork_flag) |
|
|
pgrp = p->pgrp; |
|
list_insert(&pgrp->members, &p->pgrp_link); |
|
|
|
list_insert(&allproc, &p->link); |
|
|
|
if (vfork) |
|
vfork_start(curproc); |
vfork_start(curproc); |
|
|
dprintf("fork: new pid=%d\n", p->pid); |
DPRINTF(("fork: new pid=%d\n", p->p_pid)); |
msg->data[0] = (int)p->pid; |
msg->data[0] = (int)p->p_pid; |
return 0; |
return 0; |
} |
} |
|
|
|
|
* Clean up all resource created by fork(). |
* Clean up all resource created by fork(). |
*/ |
*/ |
void |
void |
proc_cleanup(struct proc *proc) |
proc_cleanup(struct proc *p) |
{ |
{ |
struct proc *pp; |
struct proc *pp; |
|
|
pp = proc->parent; |
pp = p->p_parent; |
list_remove(&proc->sibling); |
list_remove(&p->p_sibling); |
list_remove(&proc->pgrp_link); |
list_remove(&p->p_pgrp_link); |
proc_remove(proc); |
proc_remove(p); |
list_remove(&proc->link); |
list_remove(&p->p_link); |
free(proc); |
free(p); |
} |
} |
|
|
static int |
static int |
vfork_start(struct proc *proc) |
vfork_start(struct proc *p) |
{ |
{ |
void *stack; |
void *stack; |
|
|
/* |
/* |
* Save parent's stack |
* Save parent's stack |
*/ |
*/ |
if (vm_allocate(proc->task, &stack, USTACK_SIZE, 1) != 0) |
if (vm_allocate(p->p_task, &stack, USTACK_SIZE, 1) != 0) |
return ENOMEM; |
return ENOMEM; |
|
|
memcpy(stack, proc->stack_base, USTACK_SIZE); |
memcpy(stack, p->p_stackbase, USTACK_SIZE); |
proc->stack_saved = stack; |
p->p_stacksaved = stack; |
|
|
proc->wait_vfork = 1; |
p->p_vforked = 1; |
dprintf("vfork_start: saved=%x org=%x\n", stack, proc->stack_base); |
DPRINTF(("vfork_start: saved=%x org=%x\n", stack, p->p_stackbase)); |
|
|
return 0; |
return 0; |
} |
} |
|
|
void |
void |
vfork_end(struct proc *proc) |
vfork_end(struct proc *p) |
{ |
{ |
|
|
dprintf("vfork_end: org=%x saved=%x\n", proc->stack_base, |
DPRINTF(("vfork_end: org=%x saved=%x\n", p->p_stackbase, |
proc->stack_saved); |
p->p_stacksaved)); |
/* |
/* |
* Restore parent's stack |
* Restore parent's stack |
*/ |
*/ |
memcpy(proc->stack_base, proc->stack_saved, USTACK_SIZE); |
memcpy(p->p_stackbase, p->p_stacksaved, USTACK_SIZE); |
vm_free(proc->task, proc->stack_saved); |
vm_free(p->p_task, p->p_stacksaved); |
|
|
/* |
/* |
* Resume parent |
* Resume parent |
*/ |
*/ |
proc->wait_vfork = 0; |
p->p_vforked = 0; |
task_resume(proc->task); |
task_resume(p->p_task); |
} |
} |