PERFORCE change 156331 for review

Robert Watson rwatson at FreeBSD.org
Sun Jan 18 06:48:42 PST 2009


http://perforce.freebsd.org/chv.cgi?CH=156331

Change 156331 by rwatson at 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.


More information about the p4-projects mailing list