Date: Sun, 18 Jan 2009 14:48:40 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 156331 for review Message-ID: <200901181448.n0IEmege075120@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <sys/kernel.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/poll.h> #include <sys/proc.h> #include <sys/procdesc.h> #include <sys/sysproto.h> @@ -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 <sys/selinfo.h> /* struct selinfo */ +#include <sys/_lock.h> +#include <sys/_mutex.h> + /*- * 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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901181448.n0IEmege075120>