Module Name: src
Committed By: christos
Date: Sat Apr 2 20:38:40 UTC 2016
Modified Files:
src/sys/kern: kern_exit.c
src/sys/sys: Makefile pset.h resource.h wait.h
Added Files:
src/sys/sys: idtype.h
Log Message:
Add wait6() to be used to implement waitid, mostly from FreeBSD.
Create idtypes.h shared by wait.h and pset.h
To generate a diff of this commit:
cvs rdiff -u -r1.248 -r1.249 src/sys/kern/kern_exit.c
cvs rdiff -u -r1.157 -r1.158 src/sys/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/sys/idtype.h
cvs rdiff -u -r1.4 -r1.5 src/sys/sys/pset.h
cvs rdiff -u -r1.33 -r1.34 src/sys/sys/resource.h
cvs rdiff -u -r1.27 -r1.28 src/sys/sys/wait.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_exit.c
diff -u src/sys/kern/kern_exit.c:1.248 src/sys/kern/kern_exit.c:1.249
--- src/sys/kern/kern_exit.c:1.248 Tue Oct 13 02:47:21 2015
+++ src/sys/kern/kern_exit.c Sat Apr 2 16:38:40 2016
@@ -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 @@ int debug_exit = 0;
#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 @@ retry:
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 @@ do_sys_wait(int *pid, int *status, int o
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 @@ do_sys_wait(int *pid, int *status, int o
}
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 @@ sys___wait450(struct lwp *l, const struc
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 @@ sys___wait450(struct lwp *l, const struc
* 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;
+ return EINVAL;
+ }
+
+ if ((pid_t)id == WAIT_MYPGRP && (idtype == P_PID || idtype == P_PGID)) {
+ mutex_enter(parent->p_lock);
+ id = (id_t)parent->p_pgid;
+ mutex_exit(parent->p_lock);
+ idtype = P_PGID;
+ }
for (;;) {
error = ECHILD;
dead = NULL;
LIST_FOREACH(child, &parent->p_children, p_sibling) {
- if (pid >= 0) {
- if (child->p_pid != pid) {
- child = proc_find_raw(pid);
- if (child == NULL ||
- child->p_stat == SIDL ||
- child->p_pptr != parent) {
- child = NULL;
- break;
- }
- }
- } else if (pid != WAIT_ANY && child->p_pgid != -pid) {
- /* Child not in correct pgrp */
+ int rv = match_process(parent, &child, idtype, id,
+ options, wru, si);
+ if (rv == -1)
+ break;
+ if (rv == 0)
continue;
- }
/*
* Wait for processes with p_exitsig != SIGCHLD
@@ -760,10 +960,6 @@ find_stopped_child(struct proc *parent,
if (((options & WALLSIG) == 0) &&
(options & WALTSIG ? child->p_exitsig == SIGCHLD
: P_EXITSIG(child) != SIGCHLD)){
- if (child->p_pid == pid) {
- child = NULL;
- break;
- }
continue;
}
@@ -784,7 +980,8 @@ find_stopped_child(struct proc *parent,
}
}
- if (child->p_stat == SSTOP &&
+ if ((options & WTRAPPED) != 0 &&
+ child->p_stat == SSTOP &&
child->p_waited == 0 &&
(child->p_slflag & PSL_TRACED ||
options & WUNTRACED)) {
@@ -792,13 +989,18 @@ find_stopped_child(struct proc *parent,
child->p_waited = 1;
parent->p_nstopchild--;
}
+ if (si) {
+ si->si_status = child->p_xstat;
+ si->si_code = CLD_TRAPPED;
+ }
break;
}
- if (parent->p_nstopchild == 0 || child->p_pid == pid) {
+ if (parent->p_nstopchild == 0) {
child = NULL;
break;
}
}
+ /* XXX: WCONTINUED? */
if (child != NULL || error != 0 ||
((options & WNOHANG) != 0 && dead == NULL)) {
@@ -828,7 +1030,7 @@ find_stopped_child(struct proc *parent,
* *ru is returned to the caller, and must be freed by the caller.
*/
static void
-proc_free(struct proc *p, struct rusage *ru)
+proc_free(struct proc *p, struct wrusage *wru)
{
struct proc *parent = p->p_pptr;
struct lwp *l;
@@ -878,8 +1080,10 @@ proc_free(struct proc *p, struct rusage
ruadd(&p->p_stats->p_ru, &l->l_ru);
ruadd(&p->p_stats->p_ru, &p->p_stats->p_cru);
ruadd(&parent->p_stats->p_cru, &p->p_stats->p_ru);
- if (ru != NULL)
- *ru = p->p_stats->p_ru;
+ if (wru != NULL) {
+ wru->wru_self = p->p_stats->p_ru;
+ wru->wru_children = p->p_stats->p_cru;
+ }
p->p_xstat = 0;
/*
Index: src/sys/sys/Makefile
diff -u src/sys/sys/Makefile:1.157 src/sys/sys/Makefile:1.158
--- src/sys/sys/Makefile:1.157 Mon Aug 17 02:16:03 2015
+++ src/sys/sys/Makefile Sat Apr 2 16:38:40 2016
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.157 2015/08/17 06:16:03 knakahara Exp $
+# $NetBSD: Makefile,v 1.158 2016/04/02 20:38:40 christos Exp $
.include <bsd.own.mk>
@@ -21,7 +21,8 @@ INCS= acct.h agpio.h aio.h ansi.h aout_m
exec_coff.h exec_ecoff.h exec_elf.h exec_script.h extattr.h extent.h \
fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
flashio.h float_ieee754.h fstypes.h gcq.h gmon.h gpio.h hash.h \
- ieee754.h intr.h intrio.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
+ idtype.h ieee754.h intr.h intrio.h inttypes.h ioccom.h ioctl.h \
+ ioctl_compat.h iostat.h ipc.h \
joystick.h \
kcore.h kcpuset.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
localedef.h lock.h lockf.h lua.h lwp.h lwpctl.h \
Index: src/sys/sys/pset.h
diff -u src/sys/sys/pset.h:1.4 src/sys/sys/pset.h:1.5
--- src/sys/sys/pset.h:1.4 Sat Apr 27 17:35:24 2013
+++ src/sys/sys/pset.h Sat Apr 2 16:38:40 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pset.h,v 1.4 2013/04/27 21:35:24 joerg Exp $ */
+/* $NetBSD: pset.h,v 1.5 2016/04/02 20:38:40 christos Exp $ */
/*
* Copyright (c) 2008, Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -32,17 +32,13 @@
#include <sys/cdefs.h>
#include <sys/featuretest.h>
#include <sys/types.h>
+#include <sys/idtype.h>
/* Types of processor-sets */
#define PS_NONE 0
#define PS_MYID -1
#define PS_QUERY -2
-/* ID types for processor-set calls */
-#define P_MYID -1
-#define P_PID 1
-#define P_LWPID 2
-
/* For compatibility only */
typedef cpuid_t processorid_t;
Index: src/sys/sys/resource.h
diff -u src/sys/sys/resource.h:1.33 src/sys/sys/resource.h:1.34
--- src/sys/sys/resource.h:1.33 Fri Jun 8 22:31:15 2012
+++ src/sys/sys/resource.h Sat Apr 2 16:38:40 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: resource.h,v 1.33 2012/06/09 02:31:15 christos Exp $ */
+/* $NetBSD: resource.h,v 1.34 2016/04/02 20:38:40 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -75,6 +75,13 @@ struct rusage {
#define ru_last ru_nivcsw
};
+#ifdef _NETBSD_SOURCE
+struct wrusage {
+ struct rusage wru_self;
+ struct rusage wru_children;
+};
+#endif
+
/*
* Resource limits
*/
Index: src/sys/sys/wait.h
diff -u src/sys/sys/wait.h:1.27 src/sys/sys/wait.h:1.28
--- src/sys/sys/wait.h:1.27 Sat Apr 2 07:18:26 2016
+++ src/sys/sys/wait.h Sat Apr 2 16:38:40 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: wait.h,v 1.27 2016/04/02 11:18:26 christos Exp $ */
+/* $NetBSD: wait.h,v 1.28 2016/04/02 20:38:40 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993, 1994
@@ -35,6 +35,8 @@
#define _SYS_WAIT_H_
#include <sys/featuretest.h>
+#include <sys/siginfo.h>
+#include <sys/idtype.h>
/*
* This file holds definitions relevent to the wait4 system call
@@ -87,6 +89,11 @@
#define WALLSIG 0x00000008 /* wait for processes that exit
with any signal, i.e. SIGCHLD
and alternates */
+#define WCONTINUED 0x00000010 /* Report a job control continued
+ process. */
+#define WEXITED 0x00000020 /* Wait for exited processes. */
+#define WTRAPPED 0x00000040 /* Wait for a process to hit a trap or
+ a breakpoint. */
/*
* These are the Linux names of some of the above flags, for compatibility
@@ -171,13 +178,16 @@ union wait {
__BEGIN_DECLS
struct rusage; /* forward declaration */
+struct wrusage;
pid_t wait(int *);
pid_t waitpid(pid_t, int *, int);
+int waitid(idtype_t, id_t, siginfo_t *, int);
#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
#ifndef __LIBC12_SOURCE__
pid_t wait3(int *, int, struct rusage *) __RENAME(__wait350);
pid_t wait4(pid_t, int *, int, struct rusage *) __RENAME(__wait450);
+pid_t wait6(idtype_t, id_t, int *, int, struct wrusage *, siginfo_t *);
#endif
#endif
__END_DECLS
Added files:
Index: src/sys/sys/idtype.h
diff -u /dev/null src/sys/sys/idtype.h:1.1
--- /dev/null Sat Apr 2 16:38:40 2016
+++ src/sys/sys/idtype.h Sat Apr 2 16:38:40 2016
@@ -0,0 +1,55 @@
+/* $NetBSD: idtype.h,v 1.1 2016/04/02 20:38:40 christos Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SYS_IDTYPE_H_
+#define _SYS_IDTYPE_H_
+
+/*
+ * Using the solaris constants, some of them are not applicable to us
+ */
+#define P_MYID -1 /* Me/my process group */
+#define P_PID 1 /* A process identifier. */
+#define P_PPID 2 /* A parent process identifier. */
+#define P_PGID 3 /* A process group identifier. */
+#define P_SID 4 /* A session identifier. */
+#define P_CID 5 /* A scheduling class identifier. */
+#define P_UID 6 /* A user identifier. */
+#define P_GID 7 /* A group identifier. */
+#define P_ALL 8 /* All processes. */
+#define P_LWPID 10 /* An LWP identifier. */
+#define P_TASKID 11 /* A task identifier. */
+#define P_PROJID 12 /* A project identifier. */
+#define P_POOLID 13 /* A pool identifier. */
+#define P_ZONEID 14 /* A zone identifier. */
+#define P_CTID 15 /* A (process) contract identifier. */
+#define P_CPUID 16 /* CPU identifier. */
+#define P_PSETID 17 /* Processor set identifier. */
+
+#endif /* _SYS_IDTYPE_H_ */