diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2000-11-16 20:02:22 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2000-11-16 20:02:22 +0000 |
commit | e4e19f48e436ae522921b35940bd8ecaaf14c2df (patch) | |
tree | 3667a5746513529576541577c61116a26890b3ea /sys/kern/uipc_socket.c | |
parent | cc6435e3abcd82c3915650627ead7b32a29a701b (diff) |
support kernel event queues, from FreeBSD by Jonathan Lemon,
okay art@, millert@
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r-- | sys/kern/uipc_socket.c | 114 |
1 files changed, 113 insertions, 1 deletions
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); +} |