diff options
author | jlemon <jlemon@FreeBSD.org> | 2000-04-16 18:53:38 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2000-04-16 18:53:38 +0000 |
commit | c41c876463ee8c302f06554537e0fb22a3fcdca4 (patch) | |
tree | d2f87a6af04c4f35f243bf580d099496a4131330 /sys/kern/kern_sig.c | |
parent | f8f9ad64d408b963d98d0e11b37e871763557e95 (diff) | |
download | FreeBSD-src-c41c876463ee8c302f06554537e0fb22a3fcdca4.zip FreeBSD-src-c41c876463ee8c302f06554537e0fb22a3fcdca4.tar.gz |
Introduce kqueue() and kevent(), a kernel event notification facility.
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r-- | sys/kern/kern_sig.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index e3e0e59..52136d6 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -49,6 +49,7 @@ #include <sys/resourcevar.h> #include <sys/namei.h> #include <sys/vnode.h> +#include <sys/event.h> #include <sys/proc.h> #include <sys/pioctl.h> #include <sys/systm.h> @@ -81,6 +82,13 @@ static int sig_ffs __P((sigset_t *set)); static int sigprop __P((int sig)); static void stop __P((struct proc *)); +static int filt_sigattach(struct knote *kn); +static void filt_sigdetach(struct knote *kn); +static int filt_signal(struct knote *kn, long hint); + +struct filterops sig_filtops = + { 0, filt_sigattach, filt_sigdetach, filt_signal }; + static int kern_logsigexit = 1; SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, @@ -1002,6 +1010,8 @@ psignal(p, sig) panic("psignal signal number"); } + KNOTE(&p->p_klist, NOTE_SIGNAL | sig); + prop = sigprop(sig); /* @@ -1688,3 +1698,44 @@ pgsigio(sigio, sig, checkctty) psignal(p, sig); } } + +static int +filt_sigattach(struct knote *kn) +{ + struct proc *p = curproc; + + kn->kn_ptr.p_proc = p; + kn->kn_flags |= EV_CLEAR; /* automatically set */ + + /* XXX lock the proc here while adding to the list? */ + SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext); + + return (0); +} + +static void +filt_sigdetach(struct knote *kn) +{ + struct proc *p = kn->kn_ptr.p_proc; + + SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext); +} + +/* + * signal knotes are shared with proc knotes, so we apply a mask to + * the hint in order to differentiate them from process hints. This + * could be avoided by using a signal-specific knote list, but probably + * isn't worth the trouble. + */ +static int +filt_signal(struct knote *kn, long hint) +{ + + if (hint & NOTE_SIGNAL) { + hint &= ~NOTE_SIGNAL; + + if (kn->kn_id == hint) + kn->kn_data++; + } + return (kn->kn_data != 0); +} |