summaryrefslogtreecommitdiff
path: root/proc/wait.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2001-08-04 23:32:36 +0000
committerRoland McGrath <roland@gnu.org>2001-08-04 23:32:36 +0000
commita07736d2abd88053b2a169d3f3e15260363b3626 (patch)
tree9a72dd34403e2240e3fe5cc48cdbd70f55d5ec1c /proc/wait.c
parentdeec92cabde95119d76d2957c14a875a0eb711cd (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/wait.c')
-rw-r--r--proc/wait.c102
1 files changed, 59 insertions, 43 deletions
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;
}
-