diff options
author | Roland McGrath <roland@gnu.org> | 2001-08-04 23:32:36 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2001-08-04 23:32:36 +0000 |
commit | a07736d2abd88053b2a169d3f3e15260363b3626 (patch) | |
tree | 9a72dd34403e2240e3fe5cc48cdbd70f55d5ec1c /proc | |
parent | deec92cabde95119d76d2957c14a875a0eb711cd (diff) |
2001-08-04 Roland McGrath <roland@frob.com>
* proc.h (struct proc): New members p_rusage, p_child_rusage.
* wait.c (rusage_add): New static function.
(alert_parent): Use it to add dead child's p_rusage into parent's
p_child_rusage.
(S_proc_wait): Fill *RU out param with CHILD->p_rusage, not just zeros.
Rewrote subfunction child_ready and its two callers into new
subfunction reap to reduce duplicated code.
Diffstat (limited to 'proc')
-rw-r--r-- | proc/proc.h | 5 | ||||
-rw-r--r-- | proc/wait.c | 102 |
2 files changed, 63 insertions, 44 deletions
diff --git a/proc/proc.h b/proc/proc.h index 39755986..0e83574d 100644 --- a/proc/proc.h +++ b/proc/proc.h @@ -1,5 +1,5 @@ /* Process server definitions - Copyright (C) 1992,93,94,95,96,99,2000 Free Software Foundation, Inc. + Copyright (C) 1992,93,94,95,96,99,2000,01 Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -65,6 +65,9 @@ struct proc vm_address_t p_argv, p_envp; int p_status; /* to return via wait */ int p_sigcode; + struct rusage p_rusage; /* my usage if I'm dead, to return via wait */ + + struct rusage p_child_rusage; /* accumulates p_rusage of all dead children */ unsigned int p_exec:1; /* has called proc_mark_exec */ unsigned int p_stopped:1; /* has called proc_mark_stop */ diff --git a/proc/wait.c b/proc/wait.c index 06aa594b..3ac59566 100644 --- a/proc/wait.c +++ b/proc/wait.c @@ -19,6 +19,7 @@ #include <sys/types.h> #include <hurd/hurd_types.h> #include <sys/resource.h> +#include <sys/time.h> #include "proc.h" @@ -46,11 +47,38 @@ waiter_cares (pid_t wait_pid, pid_t mypgrp, (wait_pid == WAIT_MYPGRP && pgrp == mypgrp)); } -/* A process is dying. Send SIGCHLD to the parent. Wake the parent -if it is waiting for us to exit. */ +static inline void +rusage_add (struct rusage *acc, const struct rusage *b) +{ + timeradd (&acc->ru_utime, &b->ru_utime, &acc->ru_utime); + timeradd (&acc->ru_stime, &b->ru_stime, &acc->ru_stime); + + /* Check <bits/resource.h> definition of `struct rusage' + to make sure this gets all the fields. */ + acc->ru_maxrss += b->ru_maxrss; + acc->ru_ixrss += b->ru_ixrss; + acc->ru_idrss += b->ru_idrss; + acc->ru_isrss += b->ru_isrss; + acc->ru_minflt += b->ru_minflt; + acc->ru_majflt += b->ru_majflt; + acc->ru_nswap += b->ru_nswap; + acc->ru_inblock += b->ru_inblock; + acc->ru_oublock += b->ru_oublock; + acc->ru_msgsnd += b->ru_msgsnd; + acc->ru_msgrcv += b->ru_msgrcv; + acc->ru_nsignals += b->ru_nsignals; + acc->ru_nvcsw += b->ru_nvcsw; + acc->ru_nivcsw += b->ru_nivcsw; +} + +/* A process is dying. Send SIGCHLD to the parent. + Wake the parent if it is waiting for us to exit. */ void alert_parent (struct proc *p) { + /* We accumulate the aggregate usage stats of all our dead children. */ + rusage_add (&p->p_parent->p_child_rusage, &p->p_rusage); + send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task); if (!p->p_exiting) @@ -78,73 +106,59 @@ S_proc_wait (struct proc *p, pid_t *pid_status) { int cancel; - - int child_ready (struct proc *child) + + int reap (struct proc *child) { - if (child->p_waited) + if (child->p_waited + || (!child->p_dead + && (!child->p_stopped + || !(child->p_traced || (options & WUNTRACED))))) return 0; + child->p_waited = 1; + *status = child->p_status; + *sigcode = child->p_sigcode; + *ru = child->p_rusage; /* all zeros if !p_dead */ + *pid_status = pid; if (child->p_dead) - return 1; - if (!child->p_stopped) - return 0; - if (child->p_traced || (options & WUNTRACED)) - return 1; - return 0; + complete_exit (child); + return 1; } if (!p) return EOPNOTSUPP; - + start_over: /* See if we can satisfy the request with a stopped child; also check for invalid arguments here. */ - if (!p->p_ochild) + if (!p->p_ochild) return ECHILD; - + if (pid > 0) { struct proc *child = pid_find_allow_zombie (pid); if (!child || child->p_parent != p) return ECHILD; - if (child_ready (child)) - { - child->p_waited = 1; - *status = child->p_status; - *sigcode = child->p_sigcode; - if (child->p_dead) - complete_exit (child); - memset (ru, 0, sizeof (struct rusage)); - *pid_status = pid; - return 0; - } + if (reap (child)) + return 0; } else { struct proc *child; int had_a_match = pid == 0; - + for (child = p->p_ochild; child; child = child->p_sib) if (waiter_cares (pid, p->p_pgrp->pg_pgid, child->p_pid, child->p_pgrp->pg_pgid)) { + if (reap (child)) + return 0; had_a_match = 1; - if (child_ready (child)) - { - child->p_waited = 1; - *status = child->p_status; - *sigcode = child->p_sigcode; - *pid_status = child->p_pid; - if (child->p_dead) - complete_exit (child); - memset (ru, 0, sizeof (struct rusage)); - return 0; - } } if (!had_a_match) return ECHILD; } - + if (options & WNOHANG) return EWOULDBLOCK; @@ -170,13 +184,13 @@ S_proc_mark_stop (struct proc *p, p->p_status = W_STOPCODE (signo); p->p_sigcode = sigcode; p->p_waited = 0; - + if (p->p_parent->p_waiting) { condition_broadcast (&p->p_parent->p_wakeup); p->p_parent->p_waiting = 0; } - + if (!p->p_parent->p_nostopcld) send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task); @@ -191,10 +205,13 @@ S_proc_mark_exit (struct proc *p, { if (!p) return EOPNOTSUPP; - + if (WIFSTOPPED (status)) return EINVAL; - + + if (p->p_exiting) + return EBUSY; + p->p_exiting = 1; p->p_status = status; p->p_sigcode = sigcode; @@ -232,4 +249,3 @@ S_proc_mod_stopchild (struct proc *p, p->p_nostopcld = ! value; return 0; } - |