Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add wait6() to be used to implement waitid, mostly from ...
details: https://anonhg.NetBSD.org/src/rev/10f9c957b503
branches: trunk
changeset: 344498:10f9c957b503
user: christos <christos%NetBSD.org@localhost>
date: Sat Apr 02 20:38:40 2016 +0000
description:
Add wait6() to be used to implement waitid, mostly from FreeBSD.
Create idtypes.h shared by wait.h and pset.h
diffstat:
sys/kern/kern_exit.c | 280 ++++++++++++++++++++++++++++++++++++++++++++------
sys/sys/Makefile | 5 +-
sys/sys/idtype.h | 55 ++++++++++
sys/sys/pset.h | 8 +-
sys/sys/resource.h | 9 +-
sys/sys/wait.h | 12 ++-
6 files changed, 321 insertions(+), 48 deletions(-)
diffs (truncated from 576 to 300 lines):
diff -r 54c7b32c2062 -r 10f9c957b503 sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c Sat Apr 02 16:18:54 2016 +0000
+++ b/sys/kern/kern_exit.c Sat Apr 02 20:38:40 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exit.c,v 1.248 2015/10/13 06:47:21 pgoyette Exp $ */
+/* $NetBSD: kern_exit.c,v 1.249 2016/04/02 20:38:40 christos Exp $ */
/*-
* Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.248 2015/10/13 06:47:21 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.249 2016/04/02 20:38:40 christos Exp $");
#include "opt_ktrace.h"
#include "opt_dtrace.h"
@@ -118,8 +118,9 @@
#define DPRINTF(x)
#endif
-static int find_stopped_child(struct proc *, pid_t, int, struct proc **, int *);
-static void proc_free(struct proc *, struct rusage *);
+static int find_stopped_child(struct proc *, idtype_t, id_t, int,
+ struct proc **, int *, struct wrusage *, siginfo_t *);
+static void proc_free(struct proc *, struct wrusage *);
/*
* DTrace SDT provider definitions
@@ -645,17 +646,22 @@
KASSERT(p->p_nlwps == 1);
}
-int
-do_sys_wait(int *pid, int *status, int options, struct rusage *ru)
+static int
+do_sys_waitid(idtype_t idtype, id_t id, int *pid, int *status, int options,
+ struct wrusage *wru, siginfo_t *si)
{
proc_t *child;
int error;
- if (ru != NULL) {
- memset(ru, 0, sizeof(*ru));
- }
+
+ if (wru != NULL)
+ memset(wru, 0, sizeof(*wru));
+ if (si != NULL)
+ memset(si, 0, sizeof(*si));
+
mutex_enter(proc_lock);
- error = find_stopped_child(curproc, *pid, options, &child, status);
+ error = find_stopped_child(curproc, idtype, id, options, &child, status,
+ wru, si);
if (child == NULL) {
mutex_exit(proc_lock);
*pid = 0;
@@ -668,7 +674,7 @@
if (options & WNOWAIT) {
mutex_exit(proc_lock);
} else {
- proc_free(child, ru);
+ proc_free(child, wru);
}
} else {
/* Child state must have been SSTOP. */
@@ -679,6 +685,37 @@
}
int
+do_sys_wait(int *pid, int *status, int options, struct rusage *ru)
+{
+ idtype_t idtype;
+ id_t id;
+ int ret;
+ struct wrusage wru;
+
+ /*
+ * Translate the special pid values into the (idtype, pid)
+ * pair for wait6. The WAIT_MYPGRP case is handled by
+ * find_stopped_child() on its own.
+ */
+ if (*pid == WAIT_ANY) {
+ idtype = P_ALL;
+ id = 0;
+ } else if (*pid < 0) {
+ idtype = P_PGID;
+ id = (id_t)-*pid;
+ } else {
+ idtype = P_PID;
+ id = (id_t)*pid;
+ }
+ options |= WEXITED | WTRAPPED;
+ ret = do_sys_waitid(idtype, id, pid, status, options, ru ? &wru : NULL,
+ NULL);
+ if (ru)
+ *ru = wru.wru_self;
+ return ret;
+}
+
+int
sys___wait450(struct lwp *l, const struct sys___wait450_args *uap,
register_t *retval)
{
@@ -707,6 +744,161 @@
return error;
}
+int
+sys_wait6(struct lwp *l, const struct sys_wait6_args *uap, register_t *retval)
+{
+ /* {
+ syscallarg(idtype_t) idtype;
+ syscallarg(id_t) id;
+ syscallarg(int *) status;
+ syscallarg(int) options;
+ syscallarg(struct wrusage *) wru;
+ syscallarg(siginfo_t *) si;
+ } */
+ struct wrusage wru, *wrup;
+ siginfo_t si, *sip;
+ idtype_t idtype;
+ int pid;
+ id_t id;
+ int error, status;
+
+ idtype = SCARG(uap, idtype);
+ id = SCARG(uap, id);
+
+ if (SCARG(uap, wru) != NULL)
+ wrup = &wru;
+ else
+ wrup = NULL;
+
+ if (SCARG(uap, info) != NULL)
+ sip = &si;
+ else
+ sip = NULL;
+
+ /*
+ * We expect all callers of wait6() to know about WEXITED and
+ * WTRAPPED.
+ */
+ error = do_sys_waitid(idtype, id, &pid, &status, SCARG(uap, options),
+ wrup, sip);
+
+ if (SCARG(uap, status) != NULL && error == 0)
+ error = copyout(&status, SCARG(uap, status), sizeof(status));
+ if (SCARG(uap, wru) != NULL && error == 0)
+ error = copyout(&wru, SCARG(uap, wru), sizeof(wru));
+ if (SCARG(uap, info) != NULL && error == 0)
+ error = copyout(&si, SCARG(uap, info), sizeof(si));
+ return error;
+}
+
+
+static int
+match_process(struct proc *pp, struct proc **q, idtype_t idtype, id_t id,
+ int options, struct wrusage *wrusage, siginfo_t *siginfo)
+{
+ struct rusage *rup;
+ struct proc *p = *q;
+
+ mutex_enter(p->p_lock);
+ switch (idtype) {
+ case P_ALL:
+ break;
+ case P_PID:
+ if (p->p_pid != (pid_t)id) {
+ mutex_exit(p->p_lock);
+ p = *q = proc_find_raw((pid_t)id);
+ if (p == NULL || p->p_stat == SIDL || p->p_pptr != pp) {
+ *q = NULL;
+ return -1;
+ }
+ mutex_enter(p->p_lock);
+ }
+ break;
+ case P_PGID:
+ if (p->p_pgid != (pid_t)id)
+ goto out;
+ break;
+ case P_SID:
+ if (p->p_session->s_sid != (pid_t)id)
+ goto out;
+ break;
+ case P_UID:
+ if (kauth_cred_getuid(p->p_cred) != (uid_t)id)
+ goto out;
+ break;
+ case P_GID:
+ if (kauth_cred_getgid(p->p_cred) != (gid_t)id)
+ goto out;
+ break;
+ case P_CID:
+ case P_PSETID:
+ case P_CPUID:
+ /* XXX: Implement me */
+ default:
+ out:
+ mutex_exit(p->p_lock);
+ return 0;
+ }
+
+ if ((options & WEXITED) == 0 && p->p_stat == SZOMB)
+ goto out;
+
+ if (siginfo != NULL) {
+ siginfo->si_errno = 0;
+
+ /*
+ * SUSv4 requires that the si_signo value is always
+ * SIGCHLD. Obey it despite the rfork(2) interface
+ * allows to request other signal for child exit
+ * notification.
+ */
+ siginfo->si_signo = SIGCHLD;
+
+ /*
+ * This is still a rough estimate. We will fix the
+ * cases TRAPPED, STOPPED, and CONTINUED later.
+ */
+ if (WCOREDUMP(p->p_xstat)) {
+ siginfo->si_code = CLD_DUMPED;
+ siginfo->si_status = WTERMSIG(p->p_xstat);
+ } else if (WIFSIGNALED(p->p_xstat)) {
+ siginfo->si_code = CLD_KILLED;
+ siginfo->si_status = WTERMSIG(p->p_xstat);
+ } else {
+ siginfo->si_code = CLD_EXITED;
+ siginfo->si_status = WEXITSTATUS(p->p_xstat);
+ }
+
+ siginfo->si_pid = p->p_pid;
+ siginfo->si_uid = kauth_cred_getuid(p->p_cred);
+
+ /*
+ * The si_addr field would be useful additional
+ * detail, but apparently the PC value may be lost
+ * when we reach this point. bzero() above sets
+ * siginfo->si_addr to NULL.
+ */
+ }
+
+ /*
+ * There should be no reason to limit resources usage info to
+ * exited processes only. A snapshot about any resources used
+ * by a stopped process may be exactly what is needed.
+ */
+ if (wrusage != NULL) {
+ rup = &wrusage->wru_self;
+ *rup = p->p_stats->p_ru;
+ calcru(p, &rup->ru_utime, &rup->ru_stime, NULL, NULL);
+
+ rup = &wrusage->wru_children;
+ *rup = p->p_stats->p_cru;
+ calcru(p, &rup->ru_utime, &rup->ru_stime, NULL, NULL);
+ }
+
+ mutex_exit(p->p_lock);
+ return 1;
+}
+
/*
* Scan list of child processes for a child process that has stopped or
* exited. Used by sys_wait4 and 'compat' equivalents.
@@ -714,42 +906,50 @@
* Must be called with the proc_lock held, and may release while waiting.
*/
static int
-find_stopped_child(struct proc *parent, pid_t pid, int options,
- struct proc **child_p, int *status_p)
+find_stopped_child(struct proc *parent, idtype_t idtype, id_t id, int options,
+ struct proc **child_p, int *status_p, struct wrusage *wru, siginfo_t *si)
{
struct proc *child, *dead;
int error;
KASSERT(mutex_owned(proc_lock));
- if (options & ~(WUNTRACED|WNOHANG|WALTSIG|WALLSIG)
+ if (options & ~(WUNTRACED|WNOHANG|WALTSIG|WALLSIG|WTRAPPED|WEXITED|
+ WNOWAIT|WCONTINUED)
&& !(options & WOPTSCHECKED)) {
*child_p = NULL;
return EINVAL;
}
- if (pid == 0 && !(options & WOPTSCHECKED))
- pid = -parent->p_pgid;
+ if ((options & (WEXITED|WUNTRACED|WCONTINUED|WTRAPPED)) == 0) {
+ /*
+ * We will be unable to find any matching processes,
+ * because there are no known events to look for.
+ * Prefer to return error instead of blocking
+ * indefinitely.
+ */
+ *child_p = NULL;
Home |
Main Index |
Thread Index |
Old Index