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/uipc_socket.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/uipc_socket.c')
-rw-r--r-- | sys/kern/uipc_socket.c | 109 |
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)); +} |