summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2000-04-16 18:53:38 +0000
committerjlemon <jlemon@FreeBSD.org>2000-04-16 18:53:38 +0000
commitc41c876463ee8c302f06554537e0fb22a3fcdca4 (patch)
treed2f87a6af04c4f35f243bf580d099496a4131330 /sys/kern/uipc_socket.c
parentf8f9ad64d408b963d98d0e11b37e871763557e95 (diff)
downloadFreeBSD-src-c41c876463ee8c302f06554537e0fb22a3fcdca4.zip
FreeBSD-src-c41c876463ee8c302f06554537e0fb22a3fcdca4.tar.gz
Introduce kqueue() and kevent(), a kernel event notification facility.
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e4433be..76495e1 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -40,8 +40,10 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
+#include <sys/file.h> /* for struct knote */
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/event.h>
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/protosw.h>
@@ -55,6 +57,22 @@
#include <machine/limits.h>
+static int filt_sorattach(struct knote *kn);
+static void filt_sordetach(struct knote *kn);
+static int filt_soread(struct knote *kn, long hint);
+static int filt_sowattach(struct knote *kn);
+static void filt_sowdetach(struct knote *kn);
+static int filt_sowrite(struct knote *kn, long hint);
+static int filt_solisten(struct knote *kn, long hint);
+
+static 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 },
+};
+
struct vm_zone *socket_zone;
so_gen_t so_gencnt; /* generation count for sockets */
@@ -1388,3 +1406,94 @@ sopoll(struct socket *so, int events, struct ucred *cred, struct proc *p)
splx(s);
return (revents);
}
+
+static 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);
+}
+
+static 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*/
+static 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);
+ }
+ return (kn->kn_data > 0);
+}
+
+static 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);
+}
+
+static 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*/
+static 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_state & SS_ISCONNECTED) == 0) &&
+ (so->so_proto->pr_flags & PR_CONNREQUIRED))
+ return (0);
+ return (kn->kn_data >= so->so_snd.sb_lowat);
+}
+
+/*ARGSUSED*/
+static int
+filt_solisten(struct knote *kn, long hint)
+{
+ struct socket *so = (struct socket *)kn->kn_fp->f_data;
+
+ kn->kn_data = so->so_qlen - so->so_incqlen;
+ return (! TAILQ_EMPTY(&so->so_comp));
+}
OpenPOWER on IntegriCloud