summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprovos <provos@openbsd.org>2000-11-16 20:02:15 +0000
committerprovos <provos@openbsd.org>2000-11-16 20:02:15 +0000
commit1a12e8a7ab11e47f6fb18cdbc03b05e8885dfcad (patch)
tree21c49b483d84ca5ca2b0b9f8491c15f7b579b1f3
parentAdd uscanner.c. (diff)
downloadwireguard-openbsd-1a12e8a7ab11e47f6fb18cdbc03b05e8885dfcad.tar.xz
wireguard-openbsd-1a12e8a7ab11e47f6fb18cdbc03b05e8885dfcad.zip
support kernel event queues, from FreeBSD by Jonathan Lemon,
okay art@, millert@
-rw-r--r--sys/conf/files3
-rw-r--r--sys/kern/kern_descrip.c29
-rw-r--r--sys/kern/kern_event.c887
-rw-r--r--sys/kern/kern_exec.c7
-rw-r--r--sys/kern/kern_exit.c7
-rw-r--r--sys/kern/kern_fork.c7
-rw-r--r--sys/kern/kern_sig.c55
-rw-r--r--sys/kern/sys_pipe.c64
-rw-r--r--sys/kern/syscalls.master7
-rw-r--r--sys/kern/uipc_socket.c114
-rw-r--r--sys/kern/uipc_socket2.c4
-rw-r--r--sys/kern/uipc_syscalls.c8
-rw-r--r--sys/miscfs/tcfs/tcfs_keytab.h3
-rw-r--r--sys/sys/event.h165
-rw-r--r--sys/sys/eventvar.h46
-rw-r--r--sys/sys/file.h3
-rw-r--r--sys/sys/filedesc.h7
-rw-r--r--sys/sys/malloc.h8
-rw-r--r--sys/sys/proc.h6
-rw-r--r--sys/sys/queue.h15
-rw-r--r--sys/sys/select.h5
-rw-r--r--sys/sys/socketvar.h6
-rw-r--r--sys/sys/tty.h4
23 files changed, 1433 insertions, 27 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 37357b7e816..639d057c205 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.179 2000/11/16 05:53:59 aaron Exp $
+# $OpenBSD: files,v 1.180 2000/11/16 20:02:21 provos Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -365,6 +365,7 @@ file kern/init_sysent.c
file kern/kern_acct.c
file kern/kern_clock.c
file kern/kern_descrip.c
+file kern/kern_event.c
file kern/kern_exec.c
file kern/kern_exit.c
file kern/kern_fork.c
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 48027b553b3..d1ef891fbb1 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_descrip.c,v 1.22 2000/09/27 16:13:46 mickey Exp $ */
+/* $OpenBSD: kern_descrip.c,v 1.23 2000/11/16 20:02:16 provos Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */
/*
@@ -61,6 +61,7 @@
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
+#include <sys/event.h>
#include <vm/vm.h>
@@ -463,6 +464,8 @@ fdrelease(p, fd)
*fpp = NULL;
*pf = 0;
fd_unused(fdp, fd);
+ if (fd < fdp->fd_knlistsize)
+ knote_fdclose(p, fd);
return (closef(fp, p));
}
@@ -805,6 +808,7 @@ fdinit(p)
newfdp->fd_fd.fd_nfiles = NDFILE;
newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
+ newfdp->fd_fd.fd_knlistsize = -1;
newfdp->fd_fd.fd_freefile = 0;
newfdp->fd_fd.fd_lastfile = 0;
@@ -881,8 +885,23 @@ fdcopy(p)
bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
bcopy(fdp->fd_himap, newfdp->fd_himap, NDHISLOTS(i) * sizeof(u_int));
bcopy(fdp->fd_lomap, newfdp->fd_lomap, NDLOSLOTS(i) * sizeof(u_int));
+
+ /*
+ * kq descriptors cannot be copied.
+ */
+ if (newfdp->fd_knlistsize != -1) {
+ fpp = newfdp->fd_ofiles;
+ for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
+ if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
+ fdremove(newfdp, i);
+ newfdp->fd_knlist = NULL;
+ newfdp->fd_knlistsize = -1;
+ newfdp->fd_knhash = NULL;
+ newfdp->fd_knhashmask = 0;
+ }
+
fpp = newfdp->fd_ofiles;
- for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++)
+ for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
if (*fpp != NULL) {
/*
* XXX Gruesome hack. If count gets too high, fail
@@ -890,7 +909,7 @@ fdcopy(p)
* permit it to indicate failure yet.
*/
if ((*fpp)->f_count == LONG_MAX-2)
- *fpp = NULL;
+ fdremove(newfdp, i);
else
(*fpp)->f_count++;
}
@@ -928,6 +947,10 @@ fdfree(p)
vrele(fdp->fd_cdir);
if (fdp->fd_rdir)
vrele(fdp->fd_rdir);
+ if (fdp->fd_knlist)
+ FREE(fdp->fd_knlist, M_TEMP);
+ if (fdp->fd_knhash)
+ FREE(fdp->fd_knhash, M_TEMP);
FREE(fdp, M_FILEDESC);
}
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
new file mode 100644
index 00000000000..7726c5b0554
--- /dev/null
+++ b/sys/kern/kern_event.c
@@ -0,0 +1,887 @@
+/*-
+ * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/kern/kern_event.c,v 1.15 2000/08/07 16:45:42 jlemon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/unistd.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/fcntl.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+#include <sys/event.h>
+#include <sys/eventvar.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+int filt_nullattach(struct knote *kn);
+int filt_rwtypattach(struct knote *kn);
+int filt_kqattach(struct knote *kn);
+void filt_kqdetach(struct knote *kn);
+int filt_kqueue(struct knote *kn, long hint);
+int filt_procattach(struct knote *kn);
+void filt_procdetach(struct knote *kn);
+int filt_proc(struct knote *kn, long hint);
+
+int kqueue_scan(struct file *fp, int maxevents,
+ struct kevent *ulistp, const struct timespec *timeout,
+ struct proc *p, int *retval);
+
+int kqueue_read(struct file *fp, off_t *poff, struct uio *uio,
+ struct ucred *cred);
+int kqueue_write(struct file *fp, off_t *poff, struct uio *uio,
+ struct ucred *cred);
+int kqueue_ioctl(struct file *fp, u_long com, caddr_t data,
+ struct proc *p);
+int kqueue_select(struct file *fp, int which, struct proc *p);
+int kqueue_close(struct file *fp, struct proc *p);
+void kqueue_wakeup(struct kqueue *kq);
+
+void knote_attach(struct knote *kn, struct filedesc *fdp);
+void knote_drop(struct knote *kn, struct proc *p);
+void knote_enqueue(struct knote *kn);
+void knote_dequeue(struct knote *kn);
+struct knote *knote_alloc(void);
+void knote_free(struct knote *kn);
+
+#define KNOTE_ACTIVATE(kn) do { \
+ kn->kn_status |= KN_ACTIVE; \
+ if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \
+ knote_enqueue(kn); \
+} while(0)
+
+#define KN_HASHSIZE 64 /* XXX should be tunable */
+#define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask))
+
+struct fileops kqueueops = {
+ kqueue_read,
+ kqueue_write,
+ kqueue_ioctl,
+ kqueue_select,
+ kqueue_close
+};
+
+extern struct filterops so_rwfiltops[];
+extern struct filterops pipe_rwfiltops[];
+#ifdef notyet
+extern struct filterops fifo_rwfiltops[];
+extern struct filterops vn_rwfiltops[];
+#endif
+
+struct filterops kq_rwfiltops[] = {
+ { 1, filt_kqattach, filt_kqdetach, filt_kqueue },
+ { 1, filt_nullattach, NULL, NULL },
+};
+
+extern struct filterops sig_filtops;
+#ifdef notyet
+extern struct filterops aio_filtops;
+extern struct filterops vn_filtops;
+#endif
+
+struct filterops rwtype_filtops =
+ { 1, filt_rwtypattach, NULL, NULL };
+struct filterops proc_filtops =
+ { 0, filt_procattach, filt_procdetach, filt_proc };
+
+/*
+ * XXX
+ * These must match the order of defines in <sys/file.h>
+ */
+struct filterops *rwtypfilt_sw[] = {
+ NULL, /* 0 */
+ NULL, /* vn_rwfiltops, */ /* DTYPE_VNODE */
+ so_rwfiltops, /* DTYPE_SOCKET */
+ pipe_rwfiltops, /* DTYPE_PIPE */
+ /* fifo_rwfiltops, */ /* DTYPE_FIFO */
+ kq_rwfiltops, /* DTYPE_KQUEUE */
+};
+
+/*
+ * table for for all system-defined filters.
+ */
+struct filterops *sysfilt_ops[] = {
+ &rwtype_filtops, /* EVFILT_READ */
+ &rwtype_filtops, /* EVFILT_WRITE */
+ NULL, /*&aio_filtops,*/ /* EVFILT_AIO */
+ NULL, /*&vn_filtops,*/ /* EVFILT_VNODE */
+ &proc_filtops, /* EVFILT_PROC */
+ &sig_filtops, /* EVFILT_SIGNAL */
+};
+
+int
+filt_nullattach(struct knote *kn)
+{
+ return (ENXIO);
+}
+
+/*
+ * file-type specific attach routine for read/write filters
+ */
+int
+filt_rwtypattach(struct knote *kn)
+{
+ struct filterops *fops;
+
+ fops = rwtypfilt_sw[kn->kn_fp->f_type];
+ if (fops == NULL)
+ return (EINVAL);
+ kn->kn_fop = &fops[~kn->kn_filter]; /* convert to 0-base index */
+ return (kn->kn_fop->f_attach(kn));
+}
+
+int
+filt_kqattach(struct knote *kn)
+{
+ struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
+
+ SLIST_INSERT_HEAD(&kq->kq_sel.si_note, kn, kn_selnext);
+ return (0);
+}
+
+void
+filt_kqdetach(struct knote *kn)
+{
+ struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
+
+ SLIST_REMOVE(&kq->kq_sel.si_note, kn, knote, kn_selnext);
+}
+
+/*ARGSUSED*/
+int
+filt_kqueue(struct knote *kn, long hint)
+{
+ struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
+
+ kn->kn_data = kq->kq_count;
+ return (kn->kn_data > 0);
+}
+
+int
+filt_procattach(struct knote *kn)
+{
+ struct proc *p;
+
+ p = pfind(kn->kn_id);
+ if (p == NULL)
+ return (ESRCH);
+ if (suser(p->p_ucred, &p->p_acflag) != 0)
+ return (EACCES);
+
+ kn->kn_ptr.p_proc = p;
+ kn->kn_flags |= EV_CLEAR; /* automatically set */
+
+ /*
+ * internal flag indicating registration done by kernel
+ */
+ if (kn->kn_flags & EV_FLAG1) {
+ kn->kn_data = kn->kn_sdata; /* ppid */
+ kn->kn_fflags = NOTE_CHILD;
+ kn->kn_flags &= ~EV_FLAG1;
+ }
+
+ /* XXX lock the proc here while adding to the list? */
+ SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
+
+ return (0);
+}
+
+/*
+ * The knote may be attached to a different process, which may exit,
+ * leaving nothing for the knote to be attached to. So when the process
+ * exits, the knote is marked as DETACHED and also flagged as ONESHOT so
+ * it will be deleted when read out. However, as part of the knote deletion,
+ * this routine is called, so a check is needed to avoid actually performing
+ * a detach, because the original process does not exist any more.
+ */
+void
+filt_procdetach(struct knote *kn)
+{
+ struct proc *p = kn->kn_ptr.p_proc;
+
+ if (kn->kn_status & KN_DETACHED)
+ return;
+
+ /* XXX locking? this might modify another process. */
+ SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
+}
+
+int
+filt_proc(struct knote *kn, long hint)
+{
+ u_int event;
+
+ /*
+ * mask off extra data
+ */
+ event = (u_int)hint & NOTE_PCTRLMASK;
+
+ /*
+ * if the user is interested in this event, record it.
+ */
+ if (kn->kn_sfflags & event)
+ kn->kn_fflags |= event;
+
+ /*
+ * process is gone, so flag the event as finished.
+ */
+ if (event == NOTE_EXIT) {
+ kn->kn_status |= KN_DETACHED;
+ kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ return (1);
+ }
+
+ /*
+ * process forked, and user wants to track the new process,
+ * so attach a new knote to it, and immediately report an
+ * event with the parent's pid.
+ */
+ if ((event == NOTE_FORK) && (kn->kn_sfflags & NOTE_TRACK)) {
+ struct kevent kev;
+ int error;
+
+ /*
+ * register knote with new process.
+ */
+ kev.ident = hint & NOTE_PDATAMASK; /* pid */
+ kev.filter = kn->kn_filter;
+ kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1;
+ kev.fflags = kn->kn_sfflags;
+ kev.data = kn->kn_id; /* parent */
+ kev.udata = kn->kn_kevent.udata; /* preserve udata */
+ error = kqueue_register(kn->kn_kq, &kev, NULL);
+ if (error)
+ kn->kn_fflags |= NOTE_TRACKERR;
+ }
+
+ return (kn->kn_fflags != 0);
+}
+
+int
+sys_kqueue(struct proc *p, void *v, register_t *retval)
+{
+ struct filedesc *fdp = p->p_fd;
+ struct kqueue *kq;
+ struct file *fp;
+ int fd, error;
+
+ error = falloc(p, &fp, &fd);
+ if (error)
+ return (error);
+ fp->f_flag = FREAD | FWRITE;
+ fp->f_type = DTYPE_KQUEUE;
+ fp->f_ops = &kqueueops;
+ kq = malloc(sizeof(struct kqueue), M_TEMP, M_WAITOK);
+ bzero(kq, sizeof(*kq));
+ TAILQ_INIT(&kq->kq_head);
+ fp->f_data = (caddr_t)kq;
+ *retval = fd;
+ if (fdp->fd_knlistsize < 0)
+ fdp->fd_knlistsize = 0; /* this process has a kq */
+ kq->kq_fdp = fdp;
+ return (error);
+}
+
+int
+sys_kevent(struct proc *p, void *v, register_t *retval)
+{
+ struct filedesc* fdp = p->p_fd;
+ struct sys_kevent_args /* {
+ syscallarg(int) fd;
+ syscallarg(const struct kevent *) changelist;
+ syscallarg(int) nchanges;
+ syscallarg(struct kevent *) eventlist;
+ syscallarg(int) nevents;
+ syscallarg(const struct timespec *) timeout;
+ } */ *uap = v;
+ struct kevent *kevp;
+ struct kqueue *kq;
+ struct file *fp;
+ struct timespec ts;
+ int i, n, nerrors, error;
+
+ if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
+ (fp->f_type != DTYPE_KQUEUE))
+ return (EBADF);
+
+ if (SCARG(uap, timeout) != NULL) {
+ error = copyin(SCARG(uap, timeout), &ts, sizeof(ts));
+ if (error)
+ return error;
+ SCARG(uap, timeout) = &ts;
+ }
+
+ kq = (struct kqueue *)fp->f_data;
+ nerrors = 0;
+
+ while (SCARG(uap, nchanges) > 0) {
+ n = SCARG(uap, nchanges) > KQ_NEVENTS
+ ? KQ_NEVENTS : SCARG(uap, nchanges);
+ error = copyin(SCARG(uap, changelist), kq->kq_kev,
+ n * sizeof(struct kevent));
+ if (error)
+ return (error);
+ for (i = 0; i < n; i++) {
+ kevp = &kq->kq_kev[i];
+ kevp->flags &= ~EV_SYSFLAGS;
+ error = kqueue_register(kq, kevp, p);
+ if (error) {
+ if (SCARG(uap, nevents) != 0) {
+ kevp->flags = EV_ERROR;
+ kevp->data = error;
+ (void) copyout((caddr_t)kevp,
+ (caddr_t)SCARG(uap, eventlist),
+ sizeof(*kevp));
+ SCARG(uap, eventlist)++;
+ SCARG(uap, nevents)--;
+ nerrors++;
+ } else {
+ return (error);
+ }
+ }
+ }
+ SCARG(uap, nchanges) -= n;
+ SCARG(uap, changelist) += n;
+ }
+ if (nerrors) {
+ *retval = nerrors;
+ return (0);
+ }
+
+ error = kqueue_scan(fp, SCARG(uap, nevents), SCARG(uap, eventlist),
+ SCARG(uap, timeout), p, &n);
+ *retval = n;
+ return (error);
+}
+
+int
+kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p)
+{
+ struct filedesc *fdp = kq->kq_fdp;
+ struct filterops *fops = NULL;
+ struct file *fp = NULL;
+ struct knote *kn = NULL;
+ int s, error = 0;
+
+ if (kev->filter < 0) {
+ if (kev->filter + EVFILT_SYSCOUNT < 0)
+ return (EINVAL);
+ fops = sysfilt_ops[~kev->filter]; /* to 0-base index */
+ }
+
+ if (fops == NULL) {
+ /*
+ * XXX
+ * filter attach routine is responsible for insuring that
+ * the identifier can be attached to it.
+ */
+ printf("unknown filter: %d\n", kev->filter);
+ return (EINVAL);
+ }
+
+ if (fops->f_isfd) {
+ /* validate descriptor */
+ if ((u_int)kev->ident >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[kev->ident]) == NULL)
+ return (EBADF);
+
+ if (kev->ident < fdp->fd_knlistsize) {
+ SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link)
+ if (kq == kn->kn_kq &&
+ kev->filter == kn->kn_filter)
+ break;
+ }
+ } else {
+ if (fdp->fd_knhashmask != 0) {
+ struct klist *list;
+
+ list = &fdp->fd_knhash[
+ KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)];
+ SLIST_FOREACH(kn, list, kn_link)
+ if (kev->ident == kn->kn_id &&
+ kq == kn->kn_kq &&
+ kev->filter == kn->kn_filter)
+ break;
+ }
+ }
+
+ if (kn == NULL && ((kev->flags & EV_ADD) == 0))
+ return (ENOENT);
+
+ /*
+ * kn now contains the matching knote, or NULL if no match
+ */
+ if (kev->flags & EV_ADD) {
+
+ if (kn == NULL) {
+ kn = knote_alloc();
+ if (kn == NULL)
+ return (ENOMEM);
+ if (fp != NULL)
+ fp->f_count++;
+ kn->kn_fp = fp;
+ kn->kn_kq = kq;
+ kn->kn_fop = fops;
+
+ kn->kn_sfflags = kev->fflags;
+ kn->kn_sdata = kev->data;
+ kev->fflags = 0;
+ kev->data = 0;
+ kn->kn_kevent = *kev;
+
+ knote_attach(kn, fdp);
+ if ((error = fops->f_attach(kn)) != 0) {
+ knote_drop(kn, p);
+ goto done;
+ }
+ } else {
+ /*
+ * The user may change some filter values after the
+ * initial EV_ADD, but doing so will not reset any
+ * filter which have already been triggered.
+ */
+ kn->kn_sfflags = kev->fflags;
+ kn->kn_sdata = kev->data;
+ kn->kn_kevent.udata = kev->udata;
+ }
+
+ s = splhigh();
+ if (kn->kn_fop->f_event(kn, 0))
+ KNOTE_ACTIVATE(kn);
+ splx(s);
+
+ } else if (kev->flags & EV_DELETE) {
+ kn->kn_fop->f_detach(kn);
+ knote_drop(kn, p);
+ goto done;
+ }
+
+ if ((kev->flags & EV_DISABLE) &&
+ ((kn->kn_status & KN_DISABLED) == 0)) {
+ s = splhigh();
+ kn->kn_status |= KN_DISABLED;
+ splx(s);
+ }
+
+ if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) {
+ s = splhigh();
+ kn->kn_status &= ~KN_DISABLED;
+ if ((kn->kn_status & KN_ACTIVE) &&
+ ((kn->kn_status & KN_QUEUED) == 0))
+ knote_enqueue(kn);
+ splx(s);
+ }
+
+done:
+ return (error);
+}
+
+int
+kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp,
+ const struct timespec *tsp, struct proc *p, int *retval)
+{
+ struct kqueue *kq = (struct kqueue *)fp->f_data;
+ struct kevent *kevp;
+ struct timeval atv, ttv;
+ struct knote *kn, marker;
+ int s, count, timeout, nkev = 0, error = 0;
+
+ count = maxevents;
+ if (count == 0)
+ goto done;
+
+ if (tsp != NULL) {
+ TIMESPEC_TO_TIMEVAL(&atv, tsp);
+ if (itimerfix(&atv)) {
+ error = EINVAL;
+ goto done;
+ }
+ if (tsp->tv_sec == 0 && tsp->tv_nsec == 0)
+ timeout = -1;
+ else
+ timeout = atv.tv_sec > 24 * 60 * 60 ?
+ 24 * 60 * 60 * hz : hzto(&atv);
+ timeradd(&atv, &time, &atv);
+ } else {
+ atv.tv_sec = 0;
+ atv.tv_usec = 0;
+ timeout = 0;
+ }
+ goto start;
+
+retry:
+ if (atv.tv_sec || atv.tv_usec) {
+ if (timercmp(&time, &atv, >=))
+ goto done;
+ ttv = atv;
+ timersub(&ttv, &ttv, &time);
+ timeout = ttv.tv_sec > 24 * 60 * 60 ?
+ 24 * 60 * 60 * hz : hzto(&ttv);
+ }
+
+start:
+ kevp = kq->kq_kev;
+ s = splhigh();
+ if (kq->kq_count == 0) {
+ if (timeout < 0) {
+ error = EWOULDBLOCK;
+ } else {
+ kq->kq_state |= KQ_SLEEP;
+ error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout);
+ }
+ splx(s);
+ if (error == 0)
+ goto retry;
+ /* don't restart after signals... */
+ if (error == ERESTART)
+ error = EINTR;
+ else if (error == EWOULDBLOCK)
+ error = 0;
+ goto done;
+ }
+
+ TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
+ while (count) {
+ kn = TAILQ_FIRST(&kq->kq_head);
+ TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
+ if (kn == &marker) {
+ splx(s);
+ if (count == maxevents)
+ goto retry;
+ goto done;
+ }
+ if (kn->kn_status & KN_DISABLED) {
+ kn->kn_status &= ~KN_QUEUED;
+ kq->kq_count--;
+ continue;
+ }
+ if ((kn->kn_flags & EV_ONESHOT) == 0 &&
+ kn->kn_fop->f_event(kn, 0) == 0) {
+ kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
+ kq->kq_count--;
+ continue;
+ }
+ *kevp = kn->kn_kevent;
+ kevp++;
+ nkev++;
+ if (kn->kn_flags & EV_ONESHOT) {
+ kn->kn_status &= ~KN_QUEUED;
+ kq->kq_count--;
+ splx(s);
+ kn->kn_fop->f_detach(kn);
+ knote_drop(kn, p);
+ s = splhigh();
+ } else if (kn->kn_flags & EV_CLEAR) {
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
+ kq->kq_count--;
+ } else {
+ TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
+ }
+ count--;
+ if (nkev == KQ_NEVENTS) {
+ splx(s);
+ error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
+ sizeof(struct kevent) * nkev);
+ ulistp += nkev;
+ nkev = 0;
+ kevp = kq->kq_kev;
+ s = splhigh();
+ if (error)
+ break;
+ }
+ }
+ TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe);
+ splx(s);
+done:
+ if (nkev != 0)
+ error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
+ sizeof(struct kevent) * nkev);
+ *retval = maxevents - count;
+ return (error);
+}
+
+/*
+ * XXX
+ * This could be expanded to call kqueue_scan, if desired.
+ */
+/*ARGSUSED*/
+int
+kqueue_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
+{
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+int
+kqueue_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
+
+{
+ return (ENXIO);
+}
+
+/*ARGSUSED*/
+int
+kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
+{
+ return (ENOTTY);
+}
+
+/*ARGSUSED*/
+int
+kqueue_select(struct file *fp, int which, struct proc *p)
+{
+ struct kqueue *kq = (struct kqueue *)fp->f_data;
+ int res = 0;
+ int s = splnet();
+
+ if (which == FREAD) {
+ if (kq->kq_count) {
+ res = 1;
+ } else {
+ selrecord(p, &kq->kq_sel);
+ kq->kq_state |= KQ_SEL;
+ }
+ }
+ splx(s);
+ return (res);
+}
+
+/*ARGSUSED*/
+int
+kqueue_close(struct file *fp, struct proc *p)
+{
+ struct kqueue *kq = (struct kqueue *)fp->f_data;
+ struct filedesc *fdp = p->p_fd;
+ struct knote **knp, *kn, *kn0;
+ int i;
+
+ for (i = 0; i < fdp->fd_knlistsize; i++) {
+ knp = &SLIST_FIRST(&fdp->fd_knlist[i]);
+ kn = *knp;
+ while (kn != NULL) {
+ kn0 = SLIST_NEXT(kn, kn_link);
+ if (kq == kn->kn_kq) {
+ kn->kn_fop->f_detach(kn);
+ closef(kn->kn_fp, p);
+ knote_free(kn);
+ *knp = kn0;
+ } else {
+ knp = &SLIST_NEXT(kn, kn_link);
+ }
+ kn = kn0;
+ }
+ }
+ if (fdp->fd_knhashmask != 0) {
+ for (i = 0; i < fdp->fd_knhashmask + 1; i++) {
+ knp = &SLIST_FIRST(&fdp->fd_knhash[i]);
+ kn = *knp;
+ while (kn != NULL) {
+ kn0 = SLIST_NEXT(kn, kn_link);
+ if (kq == kn->kn_kq) {
+ kn->kn_fop->f_detach(kn);
+ /* XXX non-fd release of kn->kn_ptr */
+ knote_free(kn);
+ *knp = kn0;
+ } else {
+ knp = &SLIST_NEXT(kn, kn_link);
+ }
+ kn = kn0;
+ }
+ }
+ }
+ free(kq, M_TEMP);
+ fp->f_data = NULL;
+
+ return (0);
+}
+
+void
+kqueue_wakeup(struct kqueue *kq)
+{
+
+ if (kq->kq_state & KQ_SLEEP) {
+ kq->kq_state &= ~KQ_SLEEP;
+ wakeup(kq);
+ }
+ if (kq->kq_state & KQ_SEL) {
+ kq->kq_state &= ~KQ_SEL;
+ selwakeup(&kq->kq_sel);
+ }
+ KNOTE(&kq->kq_sel.si_note, 0);
+}
+
+/*
+ * walk down a list of knotes, activating them if their event has triggered.
+ */
+void
+knote(struct klist *list, long hint)
+{
+ struct knote *kn;
+
+ SLIST_FOREACH(kn, list, kn_selnext)
+ if (kn->kn_fop->f_event(kn, hint))
+ KNOTE_ACTIVATE(kn);
+}
+
+/*
+ * remove all knotes from a specified klist
+ */
+void
+knote_remove(struct proc *p, struct klist *list)
+{
+ struct knote *kn;
+
+ while ((kn = SLIST_FIRST(list)) != NULL) {
+ kn->kn_fop->f_detach(kn);
+ knote_drop(kn, p);
+ }
+}
+
+/*
+ * remove all knotes referencing a specified fd
+ */
+void
+knote_fdclose(struct proc *p, int fd)
+{
+ struct filedesc *fdp = p->p_fd;
+ struct klist *list = &fdp->fd_knlist[fd];
+
+ knote_remove(p, list);
+}
+
+void
+knote_attach(struct knote *kn, struct filedesc *fdp)
+{
+ struct klist *list;
+ int size;
+
+ if (! kn->kn_fop->f_isfd) {
+ if (fdp->fd_knhashmask == 0)
+ fdp->fd_knhash = hashinit(KN_HASHSIZE, M_TEMP,
+ M_WAITOK, &fdp->fd_knhashmask);
+ list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
+ goto done;
+ }
+
+ if (fdp->fd_knlistsize <= kn->kn_id) {
+ size = fdp->fd_knlistsize;
+ while (size <= kn->kn_id)
+ size += KQEXTENT;
+ MALLOC(list, struct klist *,
+ size * sizeof(struct klist *), M_TEMP, M_WAITOK);
+ bcopy((caddr_t)fdp->fd_knlist, (caddr_t)list,
+ fdp->fd_knlistsize * sizeof(struct klist *));
+ bzero((caddr_t)list +
+ fdp->fd_knlistsize * sizeof(struct klist *),
+ (size - fdp->fd_knlistsize) * sizeof(struct klist *));
+ if (fdp->fd_knlist != NULL)
+ FREE(fdp->fd_knlist, M_TEMP);
+ fdp->fd_knlistsize = size;
+ fdp->fd_knlist = list;
+ }
+ list = &fdp->fd_knlist[kn->kn_id];
+done:
+ SLIST_INSERT_HEAD(list, kn, kn_link);
+ kn->kn_status = 0;
+}
+
+/*
+ * should be called at spl == 0, since we don't want to hold spl
+ * while calling closef and free.
+ */
+void
+knote_drop(struct knote *kn, struct proc *p)
+{
+ struct filedesc *fdp = p->p_fd;
+ struct klist *list;
+
+ if (kn->kn_fop->f_isfd)
+ list = &fdp->fd_knlist[kn->kn_id];
+ else
+ list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
+
+ SLIST_REMOVE(list, kn, knote, kn_link);
+ if (kn->kn_status & KN_QUEUED)
+ knote_dequeue(kn);
+ if (kn->kn_fop->f_isfd)
+ closef(kn->kn_fp, p);
+ knote_free(kn);
+}
+
+
+void
+knote_enqueue(struct knote *kn)
+{
+ struct kqueue *kq = kn->kn_kq;
+ int s = splhigh();
+
+ KASSERT((kn->kn_status & KN_QUEUED) == 0);
+
+ TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
+ kn->kn_status |= KN_QUEUED;
+ kq->kq_count++;
+ splx(s);
+ kqueue_wakeup(kq);
+}
+
+void
+knote_dequeue(struct knote *kn)
+{
+ struct kqueue *kq = kn->kn_kq;
+ int s = splhigh();
+
+ KASSERT(kn->kn_status & KN_QUEUED);
+
+ TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
+ kn->kn_status &= ~KN_QUEUED;
+ kq->kq_count--;
+ splx(s);
+}
+
+struct knote *
+knote_alloc(void)
+{
+ return (malloc(sizeof (struct knote), M_KNOTE, M_NOWAIT));
+}
+
+void
+knote_free(struct knote *kn)
+{
+ free(kn, M_KNOTE);
+}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 162313d55e4..71c068a9348 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.45 2000/11/10 18:15:46 art Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.46 2000/11/16 20:02:16 provos Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -599,6 +599,11 @@ sys_execve(p, v, retval)
VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
vput(pack.ep_vp);
+ /*
+ * notify others that we exec'd
+ */
+ KNOTE(&p->p_klist, NOTE_EXEC);
+
/* setup new registers and do misc. setup. */
if(pack.ep_emul->e_fixup != NULL) {
if((*pack.ep_emul->e_fixup)(p, &pack) != 0)
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index cb2aea9696a..96c19a5d6ed 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.27 2000/06/06 18:50:32 art Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.28 2000/11/16 20:02:16 provos Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -264,6 +264,11 @@ exit1(p, rv)
p->p_pctcpu = 0;
/*
+ * notify interested parties of our demise.
+ */
+ KNOTE(&p->p_klist, NOTE_EXIT);
+
+ /*
* Notify parent that we're gone. If we have P_NOZOMBIE or parent has
* the P_NOCLDWAIT flag set, notify process 1 instead (and hope it
* will handle this situation).
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index aa7457f3e7b..3a8f4173220 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_fork.c,v 1.35 2000/11/09 17:02:25 art Exp $ */
+/* $OpenBSD: kern_fork.c,v 1.36 2000/11/16 20:02:17 provos Exp $ */
/* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */
/*
@@ -425,6 +425,11 @@ again:
#endif
/*
+ * tell any interested parties about the new process
+ */
+ KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid);
+
+ /*
* Preserve synchronization semantics of vfork. If waiting for
* child to exec or exit, set P_PPWAIT on child, and sleep on our
* proc (in case of exit).
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index bb5c923f364..08a902b8c32 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.39 2000/11/10 18:15:47 art Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.40 2000/11/16 20:02:17 provos Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -46,8 +46,10 @@
#include <sys/param.h>
#include <sys/signalvar.h>
#include <sys/resourcevar.h>
+#include <sys/queue.h>
#include <sys/namei.h>
#include <sys/vnode.h>
+#include <sys/event.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/timeb.h>
@@ -75,6 +77,13 @@
#include <uvm/uvm_extern.h>
#endif
+int filt_sigattach(struct knote *kn);
+void filt_sigdetach(struct knote *kn);
+int filt_signal(struct knote *kn, long hint);
+
+struct filterops sig_filtops =
+ { 0, filt_sigattach, filt_sigdetach, filt_signal };
+
void stop __P((struct proc *p));
void killproc __P((struct proc *, char *));
int cansignal __P((struct proc *, struct pcred *, struct proc *, int));
@@ -683,6 +692,9 @@ psignal(p, signum)
if ((u_int)signum >= NSIG || signum == 0)
panic("psignal signal number");
+
+ KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
+
mask = sigmask(signum);
prop = sigprop[signum];
@@ -1331,3 +1343,44 @@ initsiginfo(si, sig, code, type, val)
}
}
}
+
+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);
+}
+
+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.
+ */
+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);
+}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 497d716288b..28dfd3dc210 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_pipe.c,v 1.24 2000/04/19 08:34:54 csapuntz Exp $ */
+/* $OpenBSD: sys_pipe.c,v 1.25 2000/11/16 20:02:17 provos Exp $ */
/*
* Copyright (c) 1996 John S. Dyson
@@ -45,6 +45,7 @@
#include <sys/kernel.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
+#include <sys/event.h>
#include <vm/vm.h>
#include <vm/vm_prot.h>
@@ -71,6 +72,15 @@ int pipe_ioctl __P((struct file *, u_long, caddr_t, struct proc *));
static struct fileops pipeops =
{ pipe_read, pipe_write, pipe_ioctl, pipe_select, pipe_close };
+int filt_pipeattach(struct knote *kn);
+void filt_pipedetach(struct knote *kn);
+int filt_piperead(struct knote *kn, long hint);
+int filt_pipewrite(struct knote *kn, long hint);
+
+struct filterops pipe_rwfiltops[] = {
+ { 1, filt_pipeattach, filt_pipedetach, filt_piperead },
+ { 1, filt_pipeattach, filt_pipedetach, filt_pipewrite },
+};
/*
* Default pipe buffer size(s), this can be kind-of large now because pipe
@@ -260,6 +270,7 @@ pipeselwakeup(cpipe)
}
if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_pgid != NO_PID)
gsignal(cpipe->pipe_pgid, SIGIO);
+ KNOTE(&cpipe->pipe_sel.si_note, 0);
}
/* ARGSUSED */
@@ -745,3 +756,54 @@ pipeclose(cpipe)
}
}
#endif
+
+int
+filt_pipeattach(struct knote *kn)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+
+ SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext);
+ return (0);
+}
+
+void
+filt_pipedetach(struct knote *kn)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+
+ SLIST_REMOVE(&rpipe->pipe_sel.si_note, kn, knote, kn_selnext);
+}
+
+/*ARGSUSED*/
+int
+filt_piperead(struct knote *kn, long hint)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+ struct pipe *wpipe = rpipe->pipe_peer;
+
+ kn->kn_data = rpipe->pipe_buffer.cnt;
+
+ if ((rpipe->pipe_state & PIPE_EOF) ||
+ (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_data > 0);
+}
+
+/*ARGSUSED*/
+int
+filt_pipewrite(struct knote *kn, long hint)
+{
+ struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
+ struct pipe *wpipe = rpipe->pipe_peer;
+
+ if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
+ kn->kn_data = 0;
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
+
+ return (kn->kn_data >= PIPE_BUF);
+}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 7d4cb0c94bb..7232e9e1ca5 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.42 2000/09/12 17:25:56 millert Exp $
+; $OpenBSD: syscalls.master,v 1.43 2000/11/16 20:02:17 provos Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -525,3 +525,8 @@
268 STD { ssize_t sys_pwritev(int fd, \
const struct iovec *iovp, int iovcnt, \
int pad, off_t offset); }
+269 STD { int sys_kqueue(void); }
+270 STD { int sys_kevent(int fd, \
+ const struct kevent *changelist, int nchanges, \
+ struct kevent *eventlist, int nevents, \
+ const struct timespec *timeout); }
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 3dce36b6462..82d9575ed05 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.27 1999/10/14 08:18:49 cmetz Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.28 2000/11/16 20:02:19 provos Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -44,12 +44,29 @@
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/kernel.h>
+#include <sys/event.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/signalvar.h>
#include <sys/resourcevar.h>
+int filt_sorattach(struct knote *kn);
+void filt_sordetach(struct knote *kn);
+int filt_soread(struct knote *kn, long hint);
+int filt_sowattach(struct knote *kn);
+void filt_sowdetach(struct knote *kn);
+int filt_sowrite(struct knote *kn, long hint);
+int filt_solisten(struct knote *kn, long hint);
+
+struct filterops solisten_filtops =
+ { 1, filt_sorattach, filt_sordetach, filt_solisten };
+
+struct filterops so_rwfiltops[] = {
+ { 1, filt_sorattach, filt_sordetach, filt_soread },
+ { 1, filt_sowattach, filt_sowdetach, filt_sowrite },
+};
+
#ifndef SOMINCONN
#define SOMINCONN 80
#endif /* SOMINCONN */
@@ -1093,3 +1110,98 @@ sohasoutofband(so)
csignal(so->so_pgid, SIGURG, so->so_siguid, so->so_sigeuid);
selwakeup(&so->so_rcv.sb_sel);
}
+
+int
+filt_sorattach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ if (so->so_options & SO_ACCEPTCONN)
+ kn->kn_fop = &solisten_filtops;
+ SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext);
+ so->so_rcv.sb_flags |= SB_KNOTE;
+ splx(s);
+ return (0);
+}
+
+void
+filt_sordetach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
+ so->so_rcv.sb_flags &= ~SB_KNOTE;
+ splx(s);
+}
+
+/*ARGSUSED*/
+int
+filt_soread(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = so->so_rcv.sb_cc;
+ if (so->so_state & SS_CANTRCVMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ if (so->so_error) /* temporary udp error */
+ return (1);
+ return (kn->kn_data >= so->so_rcv.sb_lowat);
+}
+
+int
+filt_sowattach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext);
+ so->so_snd.sb_flags |= SB_KNOTE;
+ splx(s);
+ return (0);
+}
+
+void
+filt_sowdetach(struct knote *kn)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+ int s = splnet();
+
+ SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
+ if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
+ so->so_snd.sb_flags &= ~SB_KNOTE;
+ splx(s);
+}
+
+/*ARGSUSED*/
+int
+filt_sowrite(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = sbspace(&so->so_snd);
+ if (so->so_state & SS_CANTSENDMORE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ if (so->so_error) /* temporary udp error */
+ return (1);
+ if (((so->so_state & SS_ISCONNECTED) == 0) &&
+ (so->so_proto->pr_flags & PR_CONNREQUIRED))
+ return (0);
+ return (kn->kn_data >= so->so_snd.sb_lowat);
+}
+
+/*ARGSUSED*/
+int
+filt_solisten(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = so->so_qlen;
+ return (so->so_qlen != 0);
+}
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 4dd7419a52a..68cb8c9eca2 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket2.c,v 1.14 2000/02/29 19:16:46 itojun Exp $ */
+/* $OpenBSD: uipc_socket2.c,v 1.15 2000/11/16 20:02:19 provos Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */
/*
@@ -47,6 +47,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/signalvar.h>
+#include <sys/event.h>
/*
* Primitive routines for operating on sockets and socket buffers
@@ -324,6 +325,7 @@ sowakeup(so, sb)
}
if (so->so_state & SS_ASYNC)
csignal(so->so_pgid, SIGIO, so->so_siguid, so->so_sigeuid);
+ KNOTE(&sb->sb_sel.si_note, 0);
}
/*
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 786b1ed0bb5..33ddae83b58 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_syscalls.c,v 1.33 2000/11/10 18:15:48 art Exp $ */
+/* $OpenBSD: uipc_syscalls.c,v 1.34 2000/11/16 20:02:19 provos Exp $ */
/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
/*
@@ -43,6 +43,7 @@
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/malloc.h>
+#include <sys/event.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
@@ -195,11 +196,16 @@ sys_accept(p, v, retval)
return (error);
}
*retval = tmpfd;
+
+ /* connection has been removed from the listen queue */
+ KNOTE(&so->so_rcv.sb_sel.si_note, 0);
+
{ struct socket *aso = so->so_q;
if (soqremque(aso, 1) == 0)
panic("accept");
so = aso;
}
+
fp->f_type = DTYPE_SOCKET;
fp->f_flag = FREAD|FWRITE;
fp->f_ops = &socketops;
diff --git a/sys/miscfs/tcfs/tcfs_keytab.h b/sys/miscfs/tcfs/tcfs_keytab.h
index e5a286080f1..82b2e3bd353 100644
--- a/sys/miscfs/tcfs/tcfs_keytab.h
+++ b/sys/miscfs/tcfs/tcfs_keytab.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcfs_keytab.h,v 1.4 2000/06/18 16:23:10 provos Exp $ */
+/* $OpenBSD: tcfs_keytab.h,v 1.5 2000/11/16 20:02:21 provos Exp $ */
/*
* Copyright 2000 The TCFS Project at http://tcfs.dia.unisa.it/
* All rights reserved.
@@ -79,6 +79,7 @@ typedef struct _kn {
unsigned int kn_type;
void *kn_key;
+#undef kn_data
tcfs_grp_data *kn_data;
struct _kn *kn_n;
diff --git a/sys/sys/event.h b/sys/sys/event.h
new file mode 100644
index 00000000000..7ed150fa4fd
--- /dev/null
+++ b/sys/sys/event.h
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/event.h,v 1.7 2000/05/26 02:06:54 jake Exp $
+ */
+
+#ifndef _SYS_EVENT_H_
+#define _SYS_EVENT_H_
+
+#define EVFILT_READ (-1)
+#define EVFILT_WRITE (-2)
+#define EVFILT_AIO (-3) /* attached to aio requests */
+#define EVFILT_VNODE (-4) /* attached to vnodes */
+#define EVFILT_PROC (-5) /* attached to struct proc */
+#define EVFILT_SIGNAL (-6) /* attached to struct proc */
+
+#define EVFILT_SYSCOUNT 6
+
+struct kevent {
+ u_int ident; /* identifier for this event */
+ short filter; /* filter for event */
+ u_short flags;
+ u_int fflags;
+ int data;
+ void *udata; /* opaque user data identifier */
+};
+
+/* actions */
+#define EV_ADD 0x0001 /* add event to kq (implies enable) */
+#define EV_DELETE 0x0002 /* delete event from kq */
+#define EV_ENABLE 0x0004 /* enable event */
+#define EV_DISABLE 0x0008 /* disable event (not reported) */
+
+/* flags */
+#define EV_ONESHOT 0x0010 /* only report one occurrence */
+#define EV_CLEAR 0x0020 /* clear event state after reporting */
+
+#define EV_SYSFLAGS 0xF000 /* reserved by system */
+#define EV_FLAG1 0x2000 /* filter-specific flag */
+
+/* returned values */
+#define EV_EOF 0x8000 /* EOF detected */
+#define EV_ERROR 0x4000 /* error, data contains errno */
+
+/*
+ * data/hint flags for EVFILT_VNODE, shared with userspace
+ */
+#define NOTE_DELETE 0x0001 /* vnode was removed */
+#define NOTE_WRITE 0x0002 /* data contents changed */
+#define NOTE_EXTEND 0x0004 /* size increased */
+#define NOTE_ATTRIB 0x0008 /* attributes changed */
+#define NOTE_LINK 0x0010 /* link count changed */
+#define NOTE_RENAME 0x0020 /* vnode was renamed */
+
+/*
+ * data/hint flags for EVFILT_PROC, shared with userspace
+ */
+#define NOTE_EXIT 0x80000000 /* process exited */
+#define NOTE_FORK 0x40000000 /* process forked */
+#define NOTE_EXEC 0x20000000 /* process exec'd */
+#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */
+#define NOTE_PDATAMASK 0x000fffff /* mask for pid */
+
+/* additional flags for EVFILT_PROC */
+#define NOTE_TRACK 0x00000001 /* follow across forks */
+#define NOTE_TRACKERR 0x00000002 /* could not track child */
+#define NOTE_CHILD 0x00000004 /* am a child process */
+
+/*
+ * This is currently visible to userland to work around broken
+ * programs which pull in <sys/proc.h> or <sys/select.h>.
+ */
+#include <sys/queue.h>
+struct knote;
+SLIST_HEAD(klist, knote);
+
+#ifdef _KERNEL
+
+#define KNOTE(list, hint) if ((list) != NULL) knote(list, hint)
+
+/*
+ * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also
+ * shared by EVFILT_PROC (all knotes attached to p->p_klist)
+ */
+#define NOTE_SIGNAL 0x08000000
+
+struct filterops {
+ int f_isfd; /* true if ident == filedescriptor */
+ int (*f_attach) __P((struct knote *kn));
+ void (*f_detach) __P((struct knote *kn));
+ int (*f_event) __P((struct knote *kn, long hint));
+};
+
+struct knote {
+ SLIST_ENTRY(knote) kn_link; /* for fd */
+ SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */
+ TAILQ_ENTRY(knote) kn_tqe;
+ struct kqueue *kn_kq; /* which queue we are on */
+ struct kevent kn_kevent;
+ int kn_status;
+ int kn_sfflags; /* saved filter flags */
+ int kn_sdata; /* saved data field */
+ union {
+ struct file *p_fp; /* file data pointer */
+ struct proc *p_proc; /* proc pointer */
+ } kn_ptr;
+ struct filterops *kn_fop;
+#define KN_ACTIVE 0x01 /* event has been triggered */
+#define KN_QUEUED 0x02 /* event is on queue */
+#define KN_DISABLED 0x04 /* event is disabled */
+#define KN_DETACHED 0x08 /* knote is detached */
+
+#define kn_id kn_kevent.ident
+#define kn_filter kn_kevent.filter
+#define kn_flags kn_kevent.flags
+#define kn_fflags kn_kevent.fflags
+#define kn_data kn_kevent.data
+#define kn_fp kn_ptr.p_fp
+};
+
+struct proc;
+
+extern void knote(struct klist *list, long hint);
+extern void knote_remove(struct proc *p, struct klist *list);
+extern void knote_fdclose(struct proc *p, int fd);
+extern int kqueue_register(struct kqueue *kq,
+ struct kevent *kev, struct proc *p);
+
+#else /* !_KERNEL */
+
+#include <sys/cdefs.h>
+struct timespec;
+
+__BEGIN_DECLS
+int kqueue __P((void));
+int kevent __P((int kq, const struct kevent *changelist, int nchanges,
+ struct kevent *eventlist, int nevents,
+ const struct timespec *timeout));
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_EVENT_H_ */
diff --git a/sys/sys/eventvar.h b/sys/sys/eventvar.h
new file mode 100644
index 00000000000..e927b7abd18
--- /dev/null
+++ b/sys/sys/eventvar.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/sys/eventvar.h,v 1.3 2000/05/26 02:06:54 jake Exp $
+ */
+
+#ifndef _SYS_EVENTVAR_H_
+#define _SYS_EVENTVAR_H_
+
+#define KQ_NEVENTS 8 /* minimize copy{in,out} calls */
+#define KQEXTENT 256 /* linear growth by this amount */
+
+struct kqueue {
+ TAILQ_HEAD(kqlist, knote) kq_head; /* list of pending event */
+ int kq_count; /* number of pending events */
+ struct selinfo kq_sel;
+ struct filedesc *kq_fdp;
+ int kq_state;
+#define KQ_SEL 0x01
+#define KQ_SLEEP 0x02
+ struct kevent kq_kev[KQ_NEVENTS];
+};
+
+#endif /* !_SYS_EVENTVAR_H_ */
diff --git a/sys/sys/file.h b/sys/sys/file.h
index dc37d91edf5..35482f912b9 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.8 2000/05/24 15:14:59 deraadt Exp $ */
+/* $OpenBSD: file.h,v 1.9 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */
/*
@@ -55,6 +55,7 @@ struct file {
#define DTYPE_VNODE 1 /* file */
#define DTYPE_SOCKET 2 /* communications endpoint */
#define DTYPE_PIPE 3 /* pipe */
+#define DTYPE_KQUEUE 4 /* event queue */
short f_type; /* descriptor type */
long f_count; /* reference count */
long f_msgcount; /* references from message queue */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index e936413eac3..85b4c3d8530 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: filedesc.h,v 1.8 2000/04/24 06:26:23 provos Exp $ */
+/* $OpenBSD: filedesc.h,v 1.9 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $ */
/*
@@ -71,6 +71,11 @@ struct filedesc {
int fd_freefile; /* approx. next free file */
u_short fd_cmask; /* mask for file creation */
u_short fd_refcnt; /* reference count */
+
+ int fd_knlistsize; /* size of knlist */
+ struct klist *fd_knlist; /* list of attached knotes */
+ u_long fd_knhashmask; /* size of knhash */
+ struct klist *fd_knhash; /* hash table for attached knotes */
};
/*
diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h
index 6e9ba0c5fef..fd510d0e459 100644
--- a/sys/sys/malloc.h
+++ b/sys/sys/malloc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.h,v 1.29 2000/08/12 05:59:50 deraadt Exp $ */
+/* $OpenBSD: malloc.h,v 1.30 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: malloc.h,v 1.39 1998/07/12 19:52:01 augustss Exp $ */
/*
@@ -159,7 +159,6 @@
#define M_USB 101 /* USB general */
#define M_USBDEV 102 /* USB device driver */
#define M_USBHC 103 /* USB host controller */
-
/* KAME IPv6 */
#define M_IP6OPT 123 /* IPv6 options */
@@ -173,6 +172,8 @@
#define M_DEBUG 106 /* MALLOC_DEBUG structures */
+#define M_KNOTE 107 /* kernel event queue */
+
#define M_TEMP 127 /* misc temporary data buffers */
#define M_LAST 128 /* Must be last type + 1 */
@@ -285,7 +286,8 @@
"pipe", /* 104 M_PIPE */ \
"memdesc", /* 105 M_MEMDESC */ \
"malloc debug", /* 106 M_DEBUG */ \
- NULL, NULL, NULL, NULL, NULL, \
+ "knote", /* 107 M_KNOTE */ \
+ NULL, NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL, \
NULL, NULL, NULL, NULL, NULL, \
NULL, \
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index dd8b7d7924f..cf7ad3ae628 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.33 2000/11/08 05:38:47 art Exp $ */
+/* $OpenBSD: proc.h,v 1.34 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -48,6 +48,7 @@
#include <sys/select.h> /* For struct selinfo. */
#include <sys/queue.h>
#include <sys/timeout.h> /* For struct timeout. */
+#include <sys/event.h> /* For struct klist */
/*
* One structure allocated per session.
@@ -173,7 +174,8 @@ struct proc {
int p_holdcnt; /* If non-zero, don't swap. */
struct emul *p_emul; /* Emulation information */
- long p_spare[1]; /* pad to 256, avoid shifting eproc. */
+ struct klist p_klist; /* knotes attached to this process */
+ /* pad to 256, avoid shifting eproc. */
/* End area that is zeroed on creation. */
diff --git a/sys/sys/queue.h b/sys/sys/queue.h
index 269af413c35..d2aeeba377d 100644
--- a/sys/sys/queue.h
+++ b/sys/sys/queue.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */
+/* $OpenBSD: queue.h,v 1.17 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
@@ -136,6 +136,19 @@ struct { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while( curelm->field.sle_next != (elm) ) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (0)
+
/*
* List definitions.
*/
diff --git a/sys/sys/select.h b/sys/sys/select.h
index 28be22899ad..d6cada6fc36 100644
--- a/sys/sys/select.h
+++ b/sys/sys/select.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: select.h,v 1.3 1997/01/27 23:21:21 deraadt Exp $ */
+/* $OpenBSD: select.h,v 1.4 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: select.h,v 1.10 1995/03/26 20:24:38 jtc Exp $ */
/*-
@@ -39,12 +39,15 @@
#ifndef _SYS_SELECT_H_
#define _SYS_SELECT_H_
+#include <sys/event.h> /* for struct klist */
+
/*
* Used to maintain information about processes that wish to be
* notified when I/O becomes possible.
*/
struct selinfo {
pid_t si_selpid; /* process to be notified */
+ struct klist si_note; /* kernel note list */
short si_flags; /* see below */
};
#define SI_COLL 0x0001 /* collision occurred */
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 073e912ff74..034fa0fad73 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: socketvar.h,v 1.18 2000/04/19 08:34:51 csapuntz Exp $ */
+/* $OpenBSD: socketvar.h,v 1.19 2000/11/16 20:02:20 provos Exp $ */
/* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */
/*-
@@ -95,6 +95,7 @@ struct socket {
#define SB_SEL 0x08 /* someone is selecting */
#define SB_ASYNC 0x10 /* ASYNC I/O, need signals */
#define SB_NOINTR 0x40 /* operations not interruptible */
+#define SB_KNOTE 0x80 /* kernel note attached */
void *so_internal; /* Space for svr4 stream data */
void (*so_upcall) __P((struct socket *so, caddr_t arg, int waitf));
@@ -128,7 +129,8 @@ struct socket {
/*
* Do we need to notify the other side when I/O is possible?
*/
-#define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT|SB_SEL|SB_ASYNC)) != 0)
+#define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT|SB_SEL|SB_ASYNC| \
+ SB_KNOTE)) != 0)
/*
* How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index 381beb88ac9..36f822b1095 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.h,v 1.6 2000/08/13 03:38:45 ericj Exp $ */
+/* $OpenBSD: tty.h,v 1.7 2000/11/16 20:02:21 provos Exp $ */
/* $NetBSD: tty.h,v 1.30.4.1 1996/06/02 09:08:13 mrg Exp $ */
/*-
@@ -42,8 +42,8 @@
*/
#include <sys/termios.h>
-#include <sys/select.h> /* For struct selinfo. */
#include <sys/queue.h>
+#include <sys/select.h> /* For struct selinfo. */
#include <sys/timeout.h>
#ifndef REAL_CLISTS