version 1.1.1.1, 2008/06/03 10:38:51 |
version 1.1.1.1.2.1, 2008/08/13 17:12:45 |
|
|
/* |
/* |
* Copyright (c) 2005-2006, Kohsuke Ohtani |
* Copyright (c) 2005-2008, Kohsuke Ohtani |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
|
|
/* |
/* |
* Exit process. |
* Exit process. |
* |
* |
* process_exit() sets the process state to zombie state, and it saves |
* process_exit() sets the process state to zombie state, and it |
* the exit code for waiting process. |
* saves the exit code for waiting process. |
*/ |
*/ |
int |
int |
proc_exit(struct msg *msg) |
proc_exit(struct msg *msg) |
{ |
{ |
int exit_code; |
int exitcode; |
struct proc *child, *parent; |
struct proc *child, *parent; |
list_t head, n; |
list_t head, n; |
|
|
if (curproc == NULL) |
if (curproc == NULL) |
return EINVAL; |
return EINVAL; |
|
|
exit_code = msg->data[0]; |
exitcode = msg->data[0]; |
dprintf("exit proc=%x task=%x code=%x\n", curproc, |
DPRINTF(("exit pid=%d task=%x code=%x\n", curproc->p_pid, |
msg->hdr.task, exit_code); |
msg->hdr.task, exitcode)); |
|
|
if (curproc->stat == SZOMB) |
if (curproc->p_stat == SZOMB) |
return EBUSY; |
return EBUSY; |
|
|
curproc->stat = SZOMB; |
curproc->p_stat = SZOMB; |
curproc->exit_code = exit_code; |
curproc->p_exitcode = exitcode; |
|
|
/* |
/* |
* Set the parent pid of all child processes to 1 (init). |
* Set the parent pid of all child processes to 1 (init). |
*/ |
*/ |
head = &curproc->children; |
head = &curproc->p_children; |
for (n = list_first(head); n != head; n = list_next(n)) { |
n = list_first(head); |
child = list_entry(n, struct proc, sibling); |
while (n != head) { |
child->parent = &initproc; |
child = list_entry(n, struct proc, p_sibling); |
list_insert(&initproc.children, &child->sibling); |
n = list_next(n); |
|
|
|
child->p_parent = &initproc; |
|
list_remove(&child->p_sibling); |
|
list_insert(&initproc.p_children, &child->p_sibling); |
} |
} |
|
|
/* |
/* |
* Resume parent process which is wating in vfork. |
* Resume parent process which is wating in vfork. |
*/ |
*/ |
parent = curproc->parent; |
parent = curproc->p_parent; |
if (parent != NULL && parent->wait_vfork) { |
if (parent != NULL && parent->p_vforked) { |
vfork_end(parent); |
vfork_end(parent); |
|
|
/* |
/* |
* The child task loses its stack data. |
* The child task loses its stack data. |
* So, it can not run anymore. |
* So, it can not run anymore. |
*/ |
*/ |
task_terminate(curproc->task); |
task_terminate(curproc->p_task); |
} |
} |
|
|
/* Send a signal to the parent process. */ |
/* Send a signal to the parent process. */ |
exception_raise(curproc->parent->task, SIGCHLD); |
exception_raise(curproc->p_parent->p_task, SIGCHLD); |
return 0; |
return 0; |
} |
} |
|
|
|
|
return EINVAL; |
return EINVAL; |
|
|
code = msg->data[0]; |
code = msg->data[0]; |
dprintf("stop task=%x code=%x\n", msg->hdr.task, code); |
DPRINTF(("stop task=%x code=%x\n", msg->hdr.task, code)); |
|
|
if (curproc->stat == SZOMB) |
if (curproc->p_stat == SZOMB) |
return EBUSY; |
return EBUSY; |
|
|
curproc->stat = SSTOP; |
curproc->p_stat = SSTOP; |
curproc->exit_code = code; |
curproc->p_exitcode = code; |
|
|
/* Send a signal to the parent process. */ |
/* Send a signal to the parent process. */ |
exception_raise(curproc->parent->task, SIGCHLD); |
exception_raise(curproc->p_parent->p_task, SIGCHLD); |
return 0; |
return 0; |
} |
} |
|
|
/* |
/* |
* Find the zombie process in the child processes. It just returns |
* Find the zombie process in the child processes. It just |
* the pid and exit code if it find at least one zombie process. |
* returns the pid and exit code if it find at least one zombie |
|
* process. |
* |
* |
* The library stub for waitpid() will wait the SIGCHLD signal in |
* The library stub for waitpid() will wait the SIGCHLD signal in |
* the stub code if there is no zombie process in child process. |
* the stub code if there is no zombie process in child process. |
|
|
proc_waitpid(struct msg *msg) |
proc_waitpid(struct msg *msg) |
{ |
{ |
pid_t pid, pid_child; |
pid_t pid, pid_child; |
int options, code; |
int options, code, match; |
struct proc *p; |
struct proc *p; |
list_t head, n; |
list_t head, n; |
|
|
|
|
|
|
pid = (pid_t)msg->data[0]; |
pid = (pid_t)msg->data[0]; |
options = msg->data[1]; |
options = msg->data[1]; |
dprintf("wait task=%x pid=%x options=%x\n", |
DPRINTF(("wait task=%x pid=%d options=%x\n", msg->hdr.task, |
msg->hdr.task, pid, options); |
pid, options)); |
|
|
if (list_empty(&curproc->children)) |
if (list_empty(&curproc->p_children)) |
return ECHILD; /* No child process */ |
return ECHILD; /* No child process */ |
|
|
/* Set the default pid and exit code */ |
/* Set the default pid and exit code */ |
|
|
* Check all processes. |
* Check all processes. |
*/ |
*/ |
p = NULL; |
p = NULL; |
head = &curproc->children; |
head = &curproc->p_children; |
for (n = list_first(head); n != head; n = list_next(n)) { |
for (n = list_first(head); n != head; n = list_next(n)) { |
p = list_entry(n, struct proc, sibling); |
p = list_entry(n, struct proc, p_sibling); |
|
|
/* |
/* |
* Check if pid matches. |
* Check if pid matches. |
*/ |
*/ |
|
match = 0; |
if (pid > 0) { |
if (pid > 0) { |
if (p->pid != pid) |
/* |
continue; |
* Wait a specific child process. |
|
*/ |
|
if (p->p_pid == pid) |
|
match = 1; |
} else if (pid == 0) { |
} else if (pid == 0) { |
if (p->pgrp->pgid != curproc->pgrp->pgid) |
/* |
continue; |
* Wait a process who has same pgid. |
|
*/ |
|
if (p->p_pgrp->pg_pgid == curproc->p_pgrp->pg_pgid) |
|
match = 1; |
} else if (pid != -1) { |
} else if (pid != -1) { |
if (p->pgrp->pgid != -pid) |
/* |
continue; |
* Wait a specific pgid. |
|
*/ |
|
if (p->p_pgrp->pg_pgid == -pid) |
|
match = 1; |
|
} else { |
|
/* |
|
* pid = -1 means wait any child process. |
|
*/ |
|
match = 1; |
} |
} |
/* |
if (match) { |
* Get the exit code. |
/* |
*/ |
* Get the exit code. |
if (p->stat == SSTOP) { |
*/ |
pid_child = p->pid; |
if (p->p_stat == SSTOP) { |
code = p->exit_code; |
pid_child = p->p_pid; |
break; |
code = p->p_exitcode; |
} else if (p->stat == SZOMB) { |
break; |
pid_child = p->pid; |
} else if (p->p_stat == SZOMB) { |
code = p->exit_code; |
pid_child = p->p_pid; |
proc_cleanup(p); |
code = p->p_exitcode; |
break; |
proc_cleanup(p); |
|
break; |
|
} |
} |
} |
} |
} |
msg->data[0] = pid_child; |
msg->data[0] = pid_child; |