From owner-p4-projects@FreeBSD.ORG Sun Jan 18 14:48:41 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 582391065673; Sun, 18 Jan 2009 14:48:41 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id ECA04106564A for ; Sun, 18 Jan 2009 14:48:40 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id D8AB98FC16 for ; Sun, 18 Jan 2009 14:48:40 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n0IEme1c075124 for ; Sun, 18 Jan 2009 14:48:40 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n0IEmege075120 for perforce@freebsd.org; Sun, 18 Jan 2009 14:48:40 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Sun, 18 Jan 2009 14:48:40 GMT Message-Id: <200901181448.n0IEmege075120@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Cc: Subject: PERFORCE change 156331 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jan 2009 14:48:42 -0000 http://perforce.freebsd.org/chv.cgi?CH=156331 Change 156331 by rwatson@rwatson_freebsd_capabilities on 2009/01/18 14:48:07 Add a mutex to struct procdesc, which will be used to synchronize event notifications using poll, select, kqueue, etc. Protect the pd_flags field using pd_lock. Add a new flag, PD_EXITED, so that procdesc contains explicit state tracking whether its process has died or not. Add pd_selinfo, PD_SELECTED, and implement poll/select for POLLHUP on process descriptors -- it is now possible to wait for a process to die using poll() on its descriptor. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_procdesc.c#4 edit .. //depot/projects/trustedbsd/capabilities/src/sys/sys/procdesc.h#3 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_procdesc.c#4 (text+ko) ==== @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -209,6 +210,7 @@ pd->pd_proc = p; pd->pd_pid = p->p_pid; p->p_procdesc = pd; + PROCDESC_LOCK_INIT(pd); /* * Process descriptors start out with two references: one from their @@ -230,6 +232,7 @@ KASSERT((pd->pd_flags & PD_CLOSED), ("procdesc_free: !PD_CLOSED")); + PROCDESC_LOCK_DESTROY(pd); uma_zfree(procdesc_zone, pd); } } @@ -250,9 +253,12 @@ pd = p->p_procdesc; + PROCDESC_LOCK(pd); KASSERT((pd->pd_flags & PD_CLOSED) == 0 || p->p_pptr == initproc, ("procdesc_exit: closed && parent not init")); + pd->pd_flags |= PD_EXITED; + /* * If the process descriptor has been closed, then we have nothing * to do; return 1 so that init will get SIGCHLD and do the reaping. @@ -260,15 +266,17 @@ * that reap. */ if (pd->pd_flags & PD_CLOSED) { + PROCDESC_UNLOCK(pd); pd->pd_proc = NULL; p->p_procdesc = NULL; procdesc_free(pd); return (1); } - - /* - * XXXRW: This is the bit where we'd do the select/kqueue thing. - */ + if (pd->pd_flags & PD_SELECTED) { + pd->pd_flags &= ~PD_SELECTED; + selwakeup(&pd->pd_selinfo); + } + PROCDESC_UNLOCK(pd); return (0); } @@ -305,11 +313,13 @@ pd = fp->f_data; fp->f_ops = &badfileops; fp->f_data = NULL; + PROCDESC_LOCK(pd); + pd->pd_flags |= PD_CLOSED; + PROCDESC_UNLOCK(pd); sx_xlock(&proctree_lock); p = pd->pd_proc; PROC_LOCK(p); - pd->pd_flags |= PD_CLOSED; if (p->p_state == PRS_ZOMBIE) { /* * If the process is already dead and just awaiting reaping, @@ -377,8 +387,20 @@ procdesc_poll(struct file *fp, int events, struct ucred *active_cred, struct thread *td) { + struct procdesc *pd; + int revents; - return (EOPNOTSUPP); + revents = 0; + pd = (struct procdesc *)fp->f_data; + PROCDESC_LOCK(pd); + if (pd->pd_flags & PD_EXITED) + revents |= POLLHUP; + if (revents == 0) { + selrecord(td, &pd->pd_selinfo); + pd->pd_flags |= PD_SELECTED; + } + PROCDESC_UNLOCK(pd); + return (revents); } static int ==== //depot/projects/trustedbsd/capabilities/src/sys/sys/procdesc.h#3 (text+ko) ==== @@ -35,6 +35,10 @@ #define _SYS_PROCDESC_H_ #ifdef _KERNEL +#include /* struct selinfo */ +#include +#include + /*- * struct procdesc describes a process descriptor, and essentially consists * of two pointers -- one to the file descriptor, and one to the process. @@ -43,28 +47,47 @@ * so a single file pointer will suffice. * * Locking key: - * (p) - Protected by the proctree_lock - * (r) - Reference count. + * (c) - Constant after initial setup. + * (p) - Protected by the process descriptor mutex. + * (r) - Atomic eference count. + * (s) - Protected by selinfo. + * (t) - Protected by the proctree_lock */ struct proc; -struct selinfo; struct sigio; struct procdesc { - struct proc *pd_proc; /* (p) Process. */ + /* + * Basic process descriptor state: the process, a cache of its pid to + * satisfy queries after the process exits, and process descriptor + * refcount. + */ + struct proc *pd_proc; /* (t) Process. */ pid_t pd_pid; /* (c) Cached pid. */ - int pd_flags; /* (p) PD_ flags. */ u_int pd_refcount; /* (r) Reference count. */ -#if 0 - struct selinfo pd_selinfo; - struct sigio *pd_sigio; -#endif + /* + * In-flight data and notification of events. + */ + int pd_flags; /* (p) PD_ flags. */ + struct selinfo pd_selinfo; /* (p) Event notification. */ + struct mtx pd_lock; /* Protect data + events. */ }; /* + * Locking macros for the procdesc itself. + */ +#define PROCDESC_LOCK_DESTROY(pd) mtx_destroy(&(pd)->pd_lock) +#define PROCDESC_LOCK_INIT(pd) mtx_init(&(pd)->pd_lock, "procdesc", NULL, \ + MTX_DEF) +#define PROCDESC_LOCK(pd) mtx_lock(&(pd)->pd_lock) +#define PROCDESC_UNLOCK(pd) mtx_unlock(&(pd)->pd_lock) + +/* * Flags for the pd_flags field. */ #define PD_CLOSED 0x00000001 /* Descriptor has closed. */ +#define PD_SELECTED 0x00000002 /* Issue selwakeup(). */ +#define PD_EXITED 0x00000004 /* Process exited. */ /* * In-kernel interfaces to process descriptors.