Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jun 2009 16:56:45 -0700
From:      Kip Macy <kmacy@freebsd.org>
To:        Andre Oppermann <andre@freebsd.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r194672 - in head/sys: kern netinet sys
Message-ID:  <3c1674c90906221656n63aff4ddo2080bfac55496ca9@mail.gmail.com>
In-Reply-To: <200906222308.n5MN856I055711@svn.freebsd.org>
References:  <200906222308.n5MN856I055711@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Who is reviewing and testing these changes?


-Kip

On Mon, Jun 22, 2009 at 4:08 PM, Andre Oppermann<andre@freebsd.org> wrote:
> Author: andre
> Date: Mon Jun 22 23:08:05 2009
> New Revision: 194672
> URL: http://svn.freebsd.org/changeset/base/194672
>
> Log:
> =A0Add soreceive_stream(), an optimized version of soreceive() for
> =A0stream (TCP) sockets.
>
> =A0It is functionally identical to generic soreceive() but has a
> =A0number stream specific optimizations:
> =A0o does only one sockbuf unlock/lock per receive independent of
> =A0 =A0the length of data to be moved into the uio compared to
> =A0 =A0soreceive() which unlocks/locks per *mbuf*.
> =A0o uses m_mbuftouio() instead of its own copy(out) variant.
> =A0o much more compact code flow as a large number of special
> =A0 =A0cases is removed.
> =A0o much improved reability.
>
> =A0It offers significantly reduced CPU usage and lock contention
> =A0when receiving fast TCP streams. =A0Additional gains are obtained
> =A0when the receiving application is using SO_RCVLOWAT to batch up
> =A0some data before a read (and wakeup) is done.
>
> =A0This function was written by "reverse engineering" and is not
> =A0just a stripped down variant of soreceive().
>
> =A0It is not yet enabled by default on TCP sockets. =A0Instead it is
> =A0commented out in the protocol initialization in tcp_usrreq.c
> =A0until more widespread testing has been done.
>
> =A0Testers, especially with 10GigE gear, are welcome.
>
> =A0MFP4: r164817 //depot/user/andre/soreceive_stream/
>
> Modified:
> =A0head/sys/kern/uipc_socket.c
> =A0head/sys/netinet/tcp_usrreq.c
> =A0head/sys/sys/socketvar.h
>
> Modified: head/sys/kern/uipc_socket.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/kern/uipc_socket.c Mon Jun 22 22:54:44 2009 =A0 =A0 =A0 =A0(=
r194671)
> +++ head/sys/kern/uipc_socket.c Mon Jun 22 23:08:05 2009 =A0 =A0 =A0 =A0(=
r194672)
> @@ -1857,6 +1857,202 @@ release:
> =A0}
>
> =A0/*
> + * Optimized version of soreceive() for stream (TCP) sockets.
> + */
> +int
> +soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *u=
io,
> + =A0 =A0struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
> +{
> + =A0 =A0 =A0 int len =3D 0, error =3D 0, flags, oresid;
> + =A0 =A0 =A0 struct sockbuf *sb;
> + =A0 =A0 =A0 struct mbuf *m, *n =3D NULL;
> +
> + =A0 =A0 =A0 /* We only do stream sockets. */
> + =A0 =A0 =A0 if (so->so_type !=3D SOCK_STREAM)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (EINVAL);
> + =A0 =A0 =A0 if (psa !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *psa =3D NULL;
> + =A0 =A0 =A0 if (controlp !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (EINVAL);
> + =A0 =A0 =A0 if (flagsp !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 flags =3D *flagsp &~ MSG_EOR;
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 flags =3D 0;
> + =A0 =A0 =A0 if (flags & MSG_OOB)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (soreceive_rcvoob(so, uio, flags));
> + =A0 =A0 =A0 if (mp0 !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *mp0 =3D NULL;
> +
> + =A0 =A0 =A0 sb =3D &so->so_rcv;
> +
> + =A0 =A0 =A0 /* Prevent other readers from entering the socket. */
> + =A0 =A0 =A0 error =3D sblock(sb, SBLOCKWAIT(flags));
> + =A0 =A0 =A0 if (error)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 SOCKBUF_LOCK(sb);
> +
> + =A0 =A0 =A0 /* Easy one, no space to copyout anything. */
> + =A0 =A0 =A0 if (uio->uio_resid =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D EINVAL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 oresid =3D uio->uio_resid;
> +
> + =A0 =A0 =A0 /* We will never ever get anything unless we are connected.=
 */
> + =A0 =A0 =A0 if (!(so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED))) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* When disconnecting there may be still so=
me data left. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sb->sb_cc > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto deliver;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(so->so_state & SS_ISDISCONNECTED))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D ENOTCONN;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Socket buffer is empty and we shall not block. */
> + =A0 =A0 =A0 if (sb->sb_cc =3D=3D 0 &&
> + =A0 =A0 =A0 =A0 =A0 ((sb->sb_flags & SS_NBIO) || (flags & (MSG_DONTWAIT=
|MSG_NBIO)))) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D EAGAIN;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> +
> +restart:
> + =A0 =A0 =A0 SOCKBUF_LOCK_ASSERT(&so->so_rcv);
> +
> + =A0 =A0 =A0 /* Abort if socket has reported problems. */
> + =A0 =A0 =A0 if (so->so_error) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sb->sb_cc > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto deliver;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (oresid > uio->uio_resid)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D so->so_error;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(flags & MSG_PEEK))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 so->so_error =3D 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Door is closed. =A0Deliver what is left, if any. */
> + =A0 =A0 =A0 if (sb->sb_state & SBS_CANTRCVMORE) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sb->sb_cc > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto deliver;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Socket buffer got some data that we shall deliver now. *=
/
> + =A0 =A0 =A0 if (sb->sb_cc > 0 && !(flags & MSG_WAITALL) &&
> + =A0 =A0 =A0 =A0 =A0 ((sb->sb_flags & SS_NBIO) ||
> + =A0 =A0 =A0 =A0 =A0 =A0(flags & (MSG_DONTWAIT|MSG_NBIO)) ||
> + =A0 =A0 =A0 =A0 =A0 =A0sb->sb_cc >=3D sb->sb_lowat ||
> + =A0 =A0 =A0 =A0 =A0 =A0sb->sb_cc >=3D uio->uio_resid ||
> + =A0 =A0 =A0 =A0 =A0 =A0sb->sb_cc >=3D sb->sb_hiwat) ) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto deliver;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* On MSG_WAITALL we must wait until all data or error arri=
ves. */
> + =A0 =A0 =A0 if ((flags & MSG_WAITALL) &&
> + =A0 =A0 =A0 =A0 =A0 (sb->sb_cc >=3D uio->uio_resid || sb->sb_cc >=3D sb=
->sb_lowat))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto deliver;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Wait and block until (more) data comes in.
> + =A0 =A0 =A0 =A0* NB: Drops the sockbuf lock during wait.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 error =3D sbwait(sb);
> + =A0 =A0 =A0 if (error)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 goto restart;
> +
> +deliver:
> + =A0 =A0 =A0 SOCKBUF_LOCK_ASSERT(&so->so_rcv);
> + =A0 =A0 =A0 KASSERT(sb->sb_cc > 0, ("%s: sockbuf empty", __func__));
> + =A0 =A0 =A0 KASSERT(sb->sb_mb !=3D NULL, ("%s: sb_mb =3D=3D NULL", __fu=
nc__));
> +
> + =A0 =A0 =A0 /* Statistics. */
> + =A0 =A0 =A0 if (uio->uio_td)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 uio->uio_td->td_ru.ru_msgrcv++;
> +
> + =A0 =A0 =A0 /* Fill uio until full or current end of socket buffer is r=
eached. */
> + =A0 =A0 =A0 len =3D min(uio->uio_resid, sb->sb_cc);
> + =A0 =A0 =A0 if (mp0 !=3D NULL) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Dequeue as many mbufs as possible. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(flags & MSG_PEEK) && len >=3D sb->sb_=
mb->m_len) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (*mp0 =3D m =3D sb->sb_=
mb;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0m !=3D NULL && m=
->m_len <=3D len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0m =3D m->m_next)=
 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 len -=3D m-=
>m_len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 uio->uio_re=
sid -=3D m->m_len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sbfree(sb, =
m);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 n =3D m;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sb->sb_mb =3D m;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sb->sb_mb =3D=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 SB_EMPTY_FI=
XUP(sb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 n->m_next =3D NULL;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Copy the remainder. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (len > 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 KASSERT(sb->sb_mb !=3D NULL=
,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ("%s: len > 0 && sb=
->sb_mb empty", __func__));
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 m =3D m_copym(sb->sb_mb, 0,=
 len, M_DONTWAIT);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (m =3D=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 len =3D 0; =
=A0 =A0 =A0 =A0/* Don't flush data from sockbuf. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 uio->uio_re=
sid -=3D m->m_len;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (*mp0 !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 n->m_next =
=3D m;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 *mp0 =3D m;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (*mp0 =3D=3D NULL) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D E=
NOBUFS;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* NB: Must unlock socket buffer as uiomove=
 may sleep. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 SOCKBUF_UNLOCK(sb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D m_mbuftouio(uio, sb->sb_mb, len);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 SOCKBUF_LOCK(sb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (error)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 SBLASTRECORDCHK(sb);
> + =A0 =A0 =A0 SBLASTMBUFCHK(sb);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Remove the delivered data from the socket buffer unles=
s we
> + =A0 =A0 =A0 =A0* were only peeking.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (!(flags & MSG_PEEK)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (len > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sbdrop_locked(sb, len);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Notify protocol that we drained some dat=
a. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((so->so_proto->pr_flags & PR_WANTRCVD) =
&&
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (((flags & MSG_WAITALL) && uio->uio=
_resid > 0) ||
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0!(flags & MSG_SOCALLBCK))) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 SOCKBUF_UNLOCK(sb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (*so->so_proto->pr_usrreqs-=
>pru_rcvd)(so, flags);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 SOCKBUF_LOCK(sb);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* For MSG_WAITALL we may have to loop again and wait for
> + =A0 =A0 =A0 =A0* more data to come in.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if ((flags & MSG_WAITALL) && uio->uio_resid > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto restart;
> +out:
> + =A0 =A0 =A0 SOCKBUF_LOCK_ASSERT(sb);
> + =A0 =A0 =A0 SBLASTRECORDCHK(sb);
> + =A0 =A0 =A0 SBLASTMBUFCHK(sb);
> + =A0 =A0 =A0 SOCKBUF_UNLOCK(sb);
> + =A0 =A0 =A0 sbunlock(sb);
> + =A0 =A0 =A0 return (error);
> +}
> +
> +/*
> =A0* Optimized version of soreceive() for simple datagram cases from user=
space.
> =A0* Unlike in the stream case, we're able to drop a datagram if copyout(=
)
> =A0* fails, and because we handle datagrams atomically, we don't need to =
use a
>
> Modified: head/sys/netinet/tcp_usrreq.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/netinet/tcp_usrreq.c =A0 =A0 =A0 Mon Jun 22 22:54:44 2009 =
=A0 =A0 =A0 =A0(r194671)
> +++ head/sys/netinet/tcp_usrreq.c =A0 =A0 =A0 Mon Jun 22 23:08:05 2009 =
=A0 =A0 =A0 =A0(r194672)
> @@ -1032,6 +1032,9 @@ struct pr_usrreqs tcp_usrreqs =3D {
> =A0 =A0 =A0 =A0.pru_send =3D =A0 =A0 =A0 =A0 =A0 =A0 tcp_usr_send,
> =A0 =A0 =A0 =A0.pru_shutdown =3D =A0 =A0 =A0 =A0 tcp_usr_shutdown,
> =A0 =A0 =A0 =A0.pru_sockaddr =3D =A0 =A0 =A0 =A0 in_getsockaddr,
> +#if 0
> + =A0 =A0 =A0 .pru_soreceive =3D =A0 =A0 =A0 =A0soreceive_stream,
> +#endif
> =A0 =A0 =A0 =A0.pru_sosetlabel =3D =A0 =A0 =A0 in_pcbsosetlabel,
> =A0 =A0 =A0 =A0.pru_close =3D =A0 =A0 =A0 =A0 =A0 =A0tcp_usr_close,
> =A0};
> @@ -1053,6 +1056,9 @@ struct pr_usrreqs tcp6_usrreqs =3D {
> =A0 =A0 =A0 =A0.pru_send =3D =A0 =A0 =A0 =A0 =A0 =A0 tcp_usr_send,
> =A0 =A0 =A0 =A0.pru_shutdown =3D =A0 =A0 =A0 =A0 tcp_usr_shutdown,
> =A0 =A0 =A0 =A0.pru_sockaddr =3D =A0 =A0 =A0 =A0 in6_mapped_sockaddr,
> +#if 0
> + =A0 =A0 =A0 .pru_soreceive =3D =A0 =A0 =A0 =A0soreceive_stream,
> +#endif
> =A0 =A0 =A0 =A0.pru_sosetlabel =3D =A0 =A0 =A0 in_pcbsosetlabel,
> =A0 =A0 =A0 =A0.pru_close =3D =A0 =A0 =A0 =A0 =A0 =A0tcp_usr_close,
> =A0};
>
> Modified: head/sys/sys/socketvar.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/sys/socketvar.h =A0 =A0Mon Jun 22 22:54:44 2009 =A0 =A0 =A0 =
=A0(r194671)
> +++ head/sys/sys/socketvar.h =A0 =A0Mon Jun 22 23:08:05 2009 =A0 =A0 =A0 =
=A0(r194672)
> @@ -345,6 +345,9 @@ int sopoll_generic(struct socket *so, in
> =A0 =A0 =A0 =A0 =A0 =A0struct ucred *active_cred, struct thread *td);
> =A0int =A0 =A0soreceive(struct socket *so, struct sockaddr **paddr, struc=
t uio *uio,
> =A0 =A0 =A0 =A0 =A0 =A0struct mbuf **mp0, struct mbuf **controlp, int *fl=
agsp);
> +int =A0 =A0soreceive_stream(struct socket *so, struct sockaddr **paddr,
> + =A0 =A0 =A0 =A0 =A0 struct uio *uio, struct mbuf **mp0, struct mbuf **c=
ontrolp,
> + =A0 =A0 =A0 =A0 =A0 int *flagsp);
> =A0int =A0 =A0soreceive_dgram(struct socket *so, struct sockaddr **paddr,
> =A0 =A0 =A0 =A0 =A0 =A0struct uio *uio, struct mbuf **mp0, struct mbuf **=
controlp,
> =A0 =A0 =A0 =A0 =A0 =A0int *flagsp);
>



--=20
When bad men combine, the good must associate; else they will fall one
by one, an unpitied sacrifice in a contemptible struggle.

    Edmund Burke



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3c1674c90906221656n63aff4ddo2080bfac55496ca9>