Hi,
this diff works for me.
I tested TCP and Unix Domain Sockets. I did no performance tests though.
I like this version better then the one i was working with, it really
is easier to read.
For completeness follows the diff i was using:
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.152
diff -u -p -u -p -r1.152 uipc_socket.c
--- kern/uipc_socket.c 13 Jun 2016 21:24:43 -0000 1.152
+++ kern/uipc_socket.c 16 Aug 2016 14:01:39 -0000
@@ -496,15 +496,18 @@ restart:
mlen = MLEN;
}
if (resid >= MINCLSIZE && space >= MCLBYTES) {
- MCLGET(m, M_NOWAIT);
+ MCLGETI(m, M_NOWAIT, NULL, lmin(resid,
+ lmin(space, MAXMCLBYTES)));
if ((m->m_flags & M_EXT) == 0)
goto nopages;
if (atomic && top == 0) {
- len = ulmin(MCLBYTES - max_hdr,
- resid);
+ len = lmin(lmin(resid, space),
+ m->m_ext.ext_size -
+ max_hdr);
m->m_data += max_hdr;
} else
- len = ulmin(MCLBYTES, resid);
+ len = lmin(lmin(resid, space),
+ m->m_ext.ext_size);
space -= len;
} else {
nopages:
2016-08-13 10:59 GMT+02:00, Claudio Jeker <[email protected]>:
> This diff refactors the uio to mbuf code to make use of bigger buffers (up
> to 64k) and also switches the MCLGET to use M_WAIT like the MGET calls in
> the same function. I see no point in not waiting for a cluster and instead
> chain lots of mbufs together as a consequence.
>
> This makes in my opinion the code easier to read and allows for further
> optimizations (like using non-DMA reachable mbufs for AF_UNIX sockets).
>
> This increased the preformance of loopback connections significantly when
> I tested this at n2k16.
> --
> :wq Claudio
>
>
> Index: kern//uipc_socket.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_socket.c,v
> retrieving revision 1.152
> diff -u -p -r1.152 uipc_socket.c
> --- kern//uipc_socket.c 13 Jun 2016 21:24:43 -0000 1.152
> +++ kern//uipc_socket.c 12 Aug 2016 14:07:36 -0000
> @@ -373,6 +373,8 @@ bad:
> return (error);
> }
>
> +int m_getuio(struct mbuf **, int, long, struct uio *);
> +
> #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
> /*
> * Send on a socket.
> @@ -395,10 +397,7 @@ int
> sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf
> *top,
> struct mbuf *control, int flags)
> {
> - struct mbuf **mp;
> - struct mbuf *m;
> long space, clen = 0;
> - u_long len, mlen;
> size_t resid;
> int error, s;
> int atomic = sosendallatonce(so) || top;
> @@ -475,7 +474,6 @@ restart:
> goto restart;
> }
> splx(s);
> - mp = ⊤
> space -= clen;
> do {
> if (uio == NULL) {
> @@ -485,52 +483,14 @@ restart:
> resid = 0;
> if (flags & MSG_EOR)
> top->m_flags |= M_EOR;
> - } else do {
> - if (top == 0) {
> - MGETHDR(m, M_WAIT, MT_DATA);
> - mlen = MHLEN;
> - m->m_pkthdr.len = 0;
> - m->m_pkthdr.ph_ifidx = 0;
> - } else {
> - MGET(m, M_WAIT, MT_DATA);
> - mlen = MLEN;
> - }
> - if (resid >= MINCLSIZE && space >= MCLBYTES) {
> - MCLGET(m, M_NOWAIT);
> - if ((m->m_flags & M_EXT) == 0)
> - goto nopages;
> - if (atomic && top == 0) {
> - len = ulmin(MCLBYTES - max_hdr,
> - resid);
> - m->m_data += max_hdr;
> - } else
> - len = ulmin(MCLBYTES, resid);
> - space -= len;
> - } else {
> -nopages:
> - len = ulmin(ulmin(mlen, resid), space);
> - space -= len;
> - /*
> - * For datagram protocols, leave room
> - * for protocol headers in first mbuf.
> - */
> - if (atomic && top == 0 && len < mlen)
> - MH_ALIGN(m, len);
> - }
> - error = uiomove(mtod(m, caddr_t), len, uio);
> + } else {
> + error = m_getuio(&top, atomic,
> + space, uio);
> + space -= top->m_pkthdr.len;
> resid = uio->uio_resid;
> - m->m_len = len;
> - *mp = m;
> - top->m_pkthdr.len += len;
> - if (error)
> - goto release;
> - mp = &m->m_next;
> - if (resid == 0) {
> - if (flags & MSG_EOR)
> - top->m_flags |= M_EOR;
> - break;
> - }
> - } while (space > 0 && atomic);
> + if (flags & MSG_EOR)
> + top->m_flags |= M_EOR;
> + }
> s = splsoftnet(); /* XXX */
> if (resid == 0)
> so->so_state &= ~SS_ISSENDING;
> @@ -539,9 +499,8 @@ nopages:
> top, addr, control, curproc);
> splx(s);
> clen = 0;
> - control = 0;
> - top = 0;
> - mp = ⊤
> + control = NULL;
> + top = NULL;
> if (error)
> goto release;
> } while (resid && space > 0);
> @@ -556,6 +515,76 @@ out:
> if (control)
> m_freem(control);
> return (error);
> +}
> +
> +int
> +m_getuio(struct mbuf **mp, int atomic, long space, struct uio *uio)
> +{
> + struct mbuf *m, *top = NULL;
> + struct mbuf **nextp = ⊤
> + u_long len, mlen;
> + size_t resid = uio->uio_resid;
> + int error;
> +
> + do {
> + if (top == NULL) {
> + MGETHDR(m, M_WAIT, MT_DATA);
> + mlen = MHLEN;
> + m->m_pkthdr.len = 0;
> + m->m_pkthdr.ph_ifidx = 0;
> + } else {
> + MGET(m, M_WAIT, MT_DATA);
> + mlen = MLEN;
> + }
> + /* chain mbuf together */
> + *nextp = m;
> + nextp = &m->m_next;
> +
> + resid = ulmin(resid, space);
> + if (resid >= MINCLSIZE) {
> + mlen = ulmin(resid, MAXMCLBYTES);
> + MCLGETI(m, M_WAIT, NULL, mlen);
> +
> + if ((m->m_flags & M_EXT) == 0) {
> + /* should not happen */
> + m_freem(top);
> + return (ENOBUFS);
> + }
> + mlen = m->m_ext.ext_size;
> + len = ulmin(mlen, resid);
> + /*
> + * For datagram protocols, leave room
> + * for protocol headers in first mbuf.
> + */
> + if (atomic && top == NULL && len < mlen - max_hdr)
> + m->m_data += max_hdr;
> + } else {
> + len = ulmin(mlen, resid);
> + /*
> + * For datagram protocols, leave room
> + * for protocol headers in first mbuf.
> + */
> + if (atomic && top == NULL && len < mlen - max_hdr)
> + MH_ALIGN(m, len);
> + }
> +
> + error = uiomove(mtod(m, caddr_t), len, uio);
> + if (error) {
> + m_freem(top);
> + return (error);
> + }
> +
> + /* adjust counters */
> + resid = uio->uio_resid;
> + space -= len;
> + m->m_len = len;
> + top->m_pkthdr.len += len;
> +
> + /* Is there more space and more data? */
> + } while (space > 0 && resid > 0);
> +
> + *mp = top;
> + return 0;
> }
>
> /*
>