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 = &top;
>               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 = &top;
> +                     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 = &top;
> +     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;
>  }
>
>  /*
>

Reply via email to