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_ */

Reply via email to