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