MCLALLOC must be called at splimp
[unix-history] / usr / src / sys / kern / uipc_socket2.c
index 850a3ca..5cffe30 100644 (file)
@@ -1,4 +1,10 @@
-/*     uipc_socket2.c  6.6     84/11/14        */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)uipc_socket2.c      7.1 (Berkeley) %G%
+ */
 
 #include "param.h"
 #include "systm.h"
 
 #include "param.h"
 #include "systm.h"
@@ -267,11 +273,9 @@ sowakeup(so, sb)
 
        sbwakeup(sb);
        if (so->so_state & SS_ASYNC) {
 
        sbwakeup(sb);
        if (so->so_state & SS_ASYNC) {
-               if (so->so_pgrp == 0)
-                       return;
-               else if (so->so_pgrp > 0)
-                       gsignal(so->so_pgrp, SIGIO);
-               else if ((p = pfind(-so->so_pgrp)) != 0)
+               if (so->so_pgrp < 0)
+                       gsignal(-so->so_pgrp, SIGIO);
+               else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0)
                        psignal(p, SIGIO);
        }
 }
                        psignal(p, SIGIO);
        }
 }
@@ -306,25 +310,6 @@ sowakeup(so, sb)
  * some of the available buffer space in the system buffer pool for the
  * socket.  The space should be released by calling sbrelease() when the
  * socket is destroyed.
  * some of the available buffer space in the system buffer pool for the
  * socket.  The space should be released by calling sbrelease() when the
  * socket is destroyed.
- *
- * The routines sbappend() or sbappendrecord() are normally called to
- * append new mbufs to a socket buffer, after checking that adequate
- * space is available, comparing the function sbspace() with the amount
- * of data to be added.  sbappendrecord() differs from sbappend() in
- * that data supplied is treated as the beginning of a new record.
- * Data is normally removed from a socket buffer in a protocol by
- * first calling m_copy on the socket buffer mbuf chain and sending this
- * to a peer, and then removing the data from the socket buffer with
- * sbdrop() or sbdroprecord() when the data is acknowledged by the peer
- * (or immediately in the case of unreliable protocols.)
- *
- * To place a sender's name, optionally, access rights, and data in a
- * socket buffer sbappendaddr() should be used.  To place access rights
- * and data in a socket buffer sbappendrights() should be used.  Note
- * that unlike sbappend() and sbappendrecord(), these routines check
- * for the caller that there will be enough space to store the data.
- * Each fails if there is not enough space, or if it cannot find mbufs
- * to store additional information in.
  */
 
 soreserve(so, sndcc, rcvcc)
  */
 
 soreserve(so, sndcc, rcvcc)
@@ -345,17 +330,17 @@ bad:
 
 /*
  * Allot mbufs to a sockbuf.
 
 /*
  * Allot mbufs to a sockbuf.
+ * Attempt to scale cc so that mbcnt doesn't become limiting
+ * if buffering efficiency is near the normal case.
  */
 sbreserve(sb, cc)
        struct sockbuf *sb;
 {
 
  */
 sbreserve(sb, cc)
        struct sockbuf *sb;
 {
 
-       if ((unsigned) cc > SB_MAX)
+       if ((unsigned) cc > (unsigned)SB_MAX * CLBYTES / (2 * MSIZE + CLBYTES))
                return (0);
                return (0);
-       /* someday maybe this routine will fail... */
        sb->sb_hiwat = cc;
        sb->sb_hiwat = cc;
-       /* * 2 implies names can be no more than 1 mbuf each */
-       sb->sb_mbmax = MAX(cc * 2, SB_MAX);
+       sb->sb_mbmax = MIN(cc * 2, SB_MAX);
        return (1);
 }
 
        return (1);
 }
 
@@ -373,6 +358,26 @@ sbrelease(sb)
 /*
  * Routines to add and remove
  * data from an mbuf queue.
 /*
  * Routines to add and remove
  * data from an mbuf queue.
+ *
+ * The routines sbappend() or sbappendrecord() are normally called to
+ * append new mbufs to a socket buffer, after checking that adequate
+ * space is available, comparing the function sbspace() with the amount
+ * of data to be added.  sbappendrecord() differs from sbappend() in
+ * that data supplied is treated as the beginning of a new record.
+ * To place a sender's address, optional access rights, and data in a
+ * socket receive buffer, sbappendaddr() should be used.  To place
+ * access rights and data in a socket receive buffer, sbappendrights()
+ * should be used.  In either case, the new data begins a new record.
+ * Note that unlike sbappend() and sbappendrecord(), these routines check
+ * for the caller that there will be enough space to store the data.
+ * Each fails if there is not enough space, or if it cannot find mbufs
+ * to store additional information in.
+ *
+ * Reliable protocols may use the socket send buffer to hold data
+ * awaiting acknowledgement.  Data is normally copied from a socket
+ * send buffer in a protocol with m_copy for output to a peer,
+ * and then removing the data from the socket buffer with sbdrop()
+ * or sbdroprecord() when the data is acknowledged by the peer.
  */
 
 /*
  */
 
 /*
@@ -432,7 +437,7 @@ sbappendrecord(sb, m0)
  * to the receive queue of a socket.  Return 0 if
  * no space in sockbuf or insufficient mbufs.
  */
  * to the receive queue of a socket.  Return 0 if
  * no space in sockbuf or insufficient mbufs.
  */
-sbappendaddr(sb, asa, m0, rights0)             /* XXX */
+sbappendaddr(sb, asa, m0, rights0)
        register struct sockbuf *sb;
        struct sockaddr *asa;
        struct mbuf *rights0, *m0;
        register struct sockbuf *sb;
        struct sockaddr *asa;
        struct mbuf *rights0, *m0;
@@ -440,63 +445,50 @@ sbappendaddr(sb, asa, m0, rights0)                /* XXX */
        register struct mbuf *m, *n;
        int space = sizeof (*asa);
 
        register struct mbuf *m, *n;
        int space = sizeof (*asa);
 
-       m = m0;
-       if (m == 0)
-               panic("sbappendaddr");
-       do {
+       for (m = m0; m; m = m->m_next)
                space += m->m_len;
                space += m->m_len;
-               m = m->m_next;
-       } while (m);
        if (rights0)
                space += rights0->m_len;
        if (space > sbspace(sb))
                return (0);
        if (rights0)
                space += rights0->m_len;
        if (space > sbspace(sb))
                return (0);
-       m = m_get(M_DONTWAIT, MT_SONAME);
+       MGET(m, M_DONTWAIT, MT_SONAME);
        if (m == 0)
                return (0);
        *mtod(m, struct sockaddr *) = *asa;
        m->m_len = sizeof (*asa);
        if (m == 0)
                return (0);
        *mtod(m, struct sockaddr *) = *asa;
        m->m_len = sizeof (*asa);
-       if (rights0) {
-               m->m_act = m_copy(rights0, 0, rights0->m_len);
-               if (m->m_act == 0) {
+       if (rights0 && rights0->m_len) {
+               m->m_next = m_copy(rights0, 0, rights0->m_len);
+               if (m->m_next == 0) {
                        m_freem(m);
                        return (0);
                }
                        m_freem(m);
                        return (0);
                }
-               sballoc(sb, m);
-               sballoc(sb, m->m_act);
-       } else
-               sballoc(sb, m);
+               sballoc(sb, m->m_next);
+       }
+       sballoc(sb, m);
        if (n = sb->sb_mb) {
                while (n->m_act)
                        n = n->m_act;
                n->m_act = m;
        } else
                sb->sb_mb = m;
        if (n = sb->sb_mb) {
                while (n->m_act)
                        n = n->m_act;
                n->m_act = m;
        } else
                sb->sb_mb = m;
-       if (m->m_act)
-               m = m->m_act;
-       sballoc(sb, m0);
-       m->m_act = m0;
-       m = m0->m_next;
-       m0->m_next = 0;
-       sbcompress(sb, m, m0);
+       if (m->m_next)
+               m = m->m_next;
+       if (m0)
+               sbcompress(sb, m0, m);
        return (1);
 }
 
        return (1);
 }
 
-#ifdef notdef
-sbappendrights(sb, rights, m0)
+sbappendrights(sb, m0, rights)
        struct sockbuf *sb;
        struct sockbuf *sb;
-       struct mbuf *rights, *m;
+       struct mbuf *rights, *m0;
 {
        register struct mbuf *m, *n;
        int space = 0;
 
 {
        register struct mbuf *m, *n;
        int space = 0;
 
-       m = m0;
-       if (m == 0 || rights == 0)
+       if (rights == 0)
                panic("sbappendrights");
                panic("sbappendrights");
-       do {
+       for (m = m0; m; m = m->m_next)
                space += m->m_len;
                space += m->m_len;
-               m = m->m_next;
-       } while (m);
        space += rights->m_len;
        if (space > sbspace(sb))
                return (0);
        space += rights->m_len;
        if (space > sbspace(sb))
                return (0);
@@ -509,15 +501,11 @@ sbappendrights(sb, rights, m0)
                        n = n->m_act;
                n->m_act = m;
        } else
                        n = n->m_act;
                n->m_act = m;
        } else
-               n->m_act = m;
-       sballoc(sb, m0);
-       m->m_act = m0;
-       m = m0->m_next;
-       m0->m_next = 0;
-       sbcompress(sb, m, m0);
+               sb->sb_mb = m;
+       if (m0)
+               sbcompress(sb, m0, m);
        return (1);
 }
        return (1);
 }
-#endif
 
 /*
  * Compress mbuf chain m into the socket
 
 /*
  * Compress mbuf chain m into the socket
@@ -535,7 +523,8 @@ sbcompress(sb, m, n)
                        continue;
                }
                if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
                        continue;
                }
                if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
-                   (n->m_off + n->m_len + m->m_len) <= MMAXOFF) {
+                   (n->m_off + n->m_len + m->m_len) <= MMAXOFF &&
+                   n->m_type == m->m_type) {
                        bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
                            (unsigned)m->m_len);
                        n->m_len += m->m_len;
                        bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
                            (unsigned)m->m_len);
                        n->m_len += m->m_len;
@@ -564,8 +553,8 @@ sbflush(sb)
 
        if (sb->sb_flags & SB_LOCK)
                panic("sbflush");
 
        if (sb->sb_flags & SB_LOCK)
                panic("sbflush");
-       if (sb->sb_cc)
-               sbdrop(sb, sb->sb_cc);
+       while (sb->sb_mbcnt)
+               sbdrop(sb, (int)sb->sb_cc);
        if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
                panic("sbflush 2");
 }
        if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
                panic("sbflush 2");
 }
@@ -573,7 +562,6 @@ sbflush(sb)
 /*
  * Drop data from (the front of) a sockbuf.
  */
 /*
  * Drop data from (the front of) a sockbuf.
  */
-struct mbuf *
 sbdrop(sb, len)
        register struct sockbuf *sb;
        register int len;
 sbdrop(sb, len)
        register struct sockbuf *sb;
        register int len;
@@ -602,6 +590,7 @@ sbdrop(sb, len)
                m = mn;
        }
        while (m && m->m_len == 0) {
                m = mn;
        }
        while (m && m->m_len == 0) {
+               sbfree(sb, m);
                MFREE(m, mn);
                m = mn;
        }
                MFREE(m, mn);
                m = mn;
        }
@@ -610,14 +599,12 @@ sbdrop(sb, len)
                m->m_act = next;
        } else
                sb->sb_mb = next;
                m->m_act = next;
        } else
                sb->sb_mb = next;
-       return (sb->sb_mb);
 }
 
 /*
  * Drop a record off the front of a sockbuf
  * and move the next record to the front.
  */
 }
 
 /*
  * Drop a record off the front of a sockbuf
  * and move the next record to the front.
  */
-struct mbuf *
 sbdroprecord(sb)
        register struct sockbuf *sb;
 {
 sbdroprecord(sb)
        register struct sockbuf *sb;
 {
@@ -631,5 +618,4 @@ sbdroprecord(sb)
                        MFREE(m, mn);
                } while (m = mn);
        }
                        MFREE(m, mn);
                } while (m = mn);
        }
-       return (sb->sb_mb);
 }
 }