[BACK]Return to uipc_socket.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/uipc_socket.c between version 1.54.2.18 and 1.55

version 1.54.2.18, 2002/12/11 06:43:10 version 1.55, 2001/03/21 19:22:29
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  
  * Copyright (c) 2002 The NetBSD Foundation, Inc.  
  * All rights reserved.  
  *  
  * This code is derived from software contributed to The NetBSD Foundation  
  * by Jason R. Thorpe of Wasabi Systems, Inc.  
  *  
  * Redistribution and use in source and binary forms, with or without  
  * modification, are permitted provided that the following conditions  
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice, this list of conditions and the following disclaimer in the  
  *    documentation and/or other materials provided with the distribution.  
  * 3. All advertising materials mentioning features or use of this software  
  *    must display the following acknowledgement:  
  *      This product includes software developed by the NetBSD  
  *      Foundation, Inc. and its contributors.  
  * 4. Neither the name of The NetBSD Foundation nor the names of its  
  *    contributors may be used to endorse or promote products derived  
  *    from this software without specific prior written permission.  
  *  
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS  
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED  
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS  
  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  
  * POSSIBILITY OF SUCH DAMAGE.  
  */  
   
 /*  /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993   * Copyright (c) 1982, 1986, 1988, 1990, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
Line 71 
Line 35 
  *      @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95   *      @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95
  */   */
   
 #include <sys/cdefs.h>  #include "opt_compat_sunos.h"
 __KERNEL_RCSID(0, "$NetBSD$");  
   
 #include "opt_sock_counters.h"  
 #include "opt_sosend_loan.h"  
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
Line 91  __KERNEL_RCSID(0, "$NetBSD$");
Line 51  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/signalvar.h>  #include <sys/signalvar.h>
 #include <sys/resourcevar.h>  #include <sys/resourcevar.h>
 #include <sys/pool.h>  #include <sys/pool.h>
 #include <sys/event.h>  
   
 #include <uvm/uvm.h>  
   
 struct pool     socket_pool;  struct pool     socket_pool;
   
 extern int      somaxconn;                      /* patchable (XXX sysctl) */  extern int      somaxconn;                      /* patchable (XXX sysctl) */
 int             somaxconn = SOMAXCONN;  int             somaxconn = SOMAXCONN;
   
 #ifdef SOSEND_COUNTERS  
 #include <sys/device.h>  
   
 struct evcnt sosend_loan_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,  
     NULL, "sosend", "loan big");  
 struct evcnt sosend_copy_big = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,  
     NULL, "sosend", "copy big");  
 struct evcnt sosend_copy_small = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,  
     NULL, "sosend", "copy small");  
 struct evcnt sosend_kvalimit = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,  
     NULL, "sosend", "kva limit");  
   
 #define SOSEND_COUNTER_INCR(ev)         (ev)->ev_count++  
   
 #else  
   
 #define SOSEND_COUNTER_INCR(ev)         /* nothing */  
   
 #endif /* SOSEND_COUNTERS */  
   
 void  void
 soinit(void)  soinit(void)
 {  {
   
         pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0,          pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0,
             "sockpl", NULL);              "sockpl", 0, NULL, NULL, M_SOCKET);
   
 #ifdef SOSEND_COUNTERS  
         evcnt_attach_static(&sosend_loan_big);  
         evcnt_attach_static(&sosend_copy_big);  
         evcnt_attach_static(&sosend_copy_small);  
         evcnt_attach_static(&sosend_kvalimit);  
 #endif /* SOSEND_COUNTERS */  
 }  
   
 #ifdef SOSEND_NO_LOAN  
 int use_sosend_loan = 0;  
 #else  
 int use_sosend_loan = 1;  
 #endif  
   
 struct mbuf *so_pendfree;  
   
 int somaxkva = 16 * 1024 * 1024;  
 int socurkva;  
 int sokvawaiters;  
   
 #define SOCK_LOAN_THRESH        4096  
 #define SOCK_LOAN_CHUNK         65536  
   
 static void  
 sodoloanfree(caddr_t buf, u_int size)  
 {  
         struct vm_page **pgs;  
         vaddr_t va, sva, eva;  
         vsize_t len;  
         paddr_t pa;  
         int i, npgs;  
   
         eva = round_page((vaddr_t) buf + size);  
         sva = trunc_page((vaddr_t) buf);  
         len = eva - sva;  
         npgs = len >> PAGE_SHIFT;  
   
         pgs = alloca(npgs * sizeof(*pgs));  
   
         for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {  
                 if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)  
                         panic("sodoloanfree: va 0x%lx not mapped", va);  
                 pgs[i] = PHYS_TO_VM_PAGE(pa);  
         }  
   
         pmap_kremove(sva, len);  
         pmap_update(pmap_kernel());  
         uvm_unloan(pgs, npgs, UVM_LOAN_TOPAGE);  
         uvm_km_free(kernel_map, sva, len);  
         socurkva -= len;  
         if (sokvawaiters)  
                 wakeup(&socurkva);  
 }  
   
 static size_t  
 sodopendfree(struct socket *so)  
 {  
         struct mbuf *m;  
         size_t rv = 0;  
         int s;  
   
         s = splvm();  
   
         for (;;) {  
                 m = so_pendfree;  
                 if (m == NULL)  
                         break;  
                 so_pendfree = m->m_next;  
                 splx(s);  
   
                 rv += m->m_ext.ext_size;  
                 sodoloanfree(m->m_ext.ext_buf, m->m_ext.ext_size);  
                 s = splvm();  
                 pool_cache_put(&mbpool_cache, m);  
         }  
   
         for (;;) {  
                 m = so->so_pendfree;  
                 if (m == NULL)  
                         break;  
                 so->so_pendfree = m->m_next;  
                 splx(s);  
   
                 rv += m->m_ext.ext_size;  
                 sodoloanfree(m->m_ext.ext_buf, m->m_ext.ext_size);  
                 s = splvm();  
                 pool_cache_put(&mbpool_cache, m);  
         }  
   
         splx(s);  
         return (rv);  
 }  
   
 static void  
 soloanfree(struct mbuf *m, caddr_t buf, u_int size, void *arg)  
 {  
         struct socket *so = arg;  
         int s;  
   
         if (m == NULL) {  
                 sodoloanfree(buf, size);  
                 return;  
         }  
   
         s = splvm();  
         m->m_next = so->so_pendfree;  
         so->so_pendfree = m;  
         splx(s);  
         if (sokvawaiters)  
                 wakeup(&socurkva);  
 }  
   
 static long  
 sosend_loan(struct socket *so, struct uio *uio, struct mbuf *m, long space)  
 {  
         struct iovec *iov = uio->uio_iov;  
         vaddr_t sva, eva;  
         vsize_t len;  
         struct vm_page **pgs;  
         vaddr_t lva, va;  
         int npgs, s, i, error;  
   
         if (uio->uio_segflg != UIO_USERSPACE)  
                 return (0);  
   
         if (iov->iov_len < (size_t) space)  
                 space = iov->iov_len;  
         if (space > SOCK_LOAN_CHUNK)  
                 space = SOCK_LOAN_CHUNK;  
   
         eva = round_page((vaddr_t) iov->iov_base + space);  
         sva = trunc_page((vaddr_t) iov->iov_base);  
         len = eva - sva;  
         npgs = len >> PAGE_SHIFT;  
   
         while (socurkva + len > somaxkva) {  
                 if (sodopendfree(so))  
                         continue;  
                 SOSEND_COUNTER_INCR(&sosend_kvalimit);  
                 s = splvm();  
                 sokvawaiters++;  
                 (void) tsleep(&socurkva, PVM, "sokva", 0);  
                 sokvawaiters--;  
                 splx(s);  
         }  
   
         lva = uvm_km_valloc_wait(kernel_map, len);  
         if (lva == 0)  
                 return (0);  
         socurkva += len;  
   
         pgs = alloca(npgs * sizeof(*pgs));  
   
         error = uvm_loan(&uio->uio_procp->p_vmspace->vm_map, sva, len,  
             pgs, UVM_LOAN_TOPAGE);  
         if (error) {  
                 uvm_km_free(kernel_map, lva, len);  
                 socurkva -= len;  
                 return (0);  
         }  
   
         for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE)  
                 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pgs[i]), VM_PROT_READ);  
         pmap_update(pmap_kernel());  
   
         lva += (vaddr_t) iov->iov_base & PAGE_MASK;  
   
         MEXTADD(m, (caddr_t) lva, space, M_MBUF, soloanfree, so);  
   
         uio->uio_resid -= space;  
         /* uio_offset not updated, not set/used for write(2) */  
         uio->uio_iov->iov_base = (caddr_t) uio->uio_iov->iov_base + space;  
         uio->uio_iov->iov_len -= space;  
         if (uio->uio_iov->iov_len == 0) {  
                 uio->uio_iov++;  
                 uio->uio_iovcnt--;  
         }  
   
         return (space);  
 }  }
   
 /*  /*
Line 352  socreate(int dom, struct socket **aso, i
Line 109  socreate(int dom, struct socket **aso, i
                 splx(s);                  splx(s);
                 return (error);                  return (error);
         }          }
   #ifdef COMPAT_SUNOS
           {
                   extern struct emul emul_sunos;
                   if (p->p_emul == &emul_sunos && type == SOCK_DGRAM)
                           so->so_options |= SO_BROADCAST;
           }
   #endif
         splx(s);          splx(s);
         *aso = so;          *aso = so;
         return (0);          return (0);
Line 381  solisten(struct socket *so, int backlog)
Line 145  solisten(struct socket *so, int backlog)
                 splx(s);                  splx(s);
                 return (error);                  return (error);
         }          }
         if (TAILQ_EMPTY(&so->so_q))          if (so->so_q.tqh_first == NULL)
                 so->so_options |= SO_ACCEPTCONN;                  so->so_options |= SO_ACCEPTCONN;
         if (backlog < 0)          if (backlog < 0)
                 backlog = 0;                  backlog = 0;
Line 393  solisten(struct socket *so, int backlog)
Line 157  solisten(struct socket *so, int backlog)
 void  void
 sofree(struct socket *so)  sofree(struct socket *so)
 {  {
         struct mbuf *m;  
   
         if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)          if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
                 return;                  return;
Line 408  sofree(struct socket *so)
Line 171  sofree(struct socket *so)
         }          }
         sbrelease(&so->so_snd);          sbrelease(&so->so_snd);
         sorflush(so);          sorflush(so);
         while ((m = so->so_pendfree) != NULL) {  
                 so->so_pendfree = m->m_next;  
                 m->m_next = so_pendfree;  
                 so_pendfree = m;  
         }  
         pool_put(&socket_pool, so);          pool_put(&socket_pool, so);
 }  }
   
Line 430  soclose(struct socket *so)
Line 188  soclose(struct socket *so)
         error = 0;          error = 0;
         s = splsoftnet();               /* conservative */          s = splsoftnet();               /* conservative */
         if (so->so_options & SO_ACCEPTCONN) {          if (so->so_options & SO_ACCEPTCONN) {
                 while ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {                  while ((so2 = so->so_q0.tqh_first) != 0) {
                         (void) soqremque(so2, 0);                          (void) soqremque(so2, 0);
                         (void) soabort(so2);                          (void) soabort(so2);
                 }                  }
                 while ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {                  while ((so2 = so->so_q.tqh_first) != 0) {
                         (void) soqremque(so2, 1);                          (void) soqremque(so2, 1);
                         (void) soabort(so2);                          (void) soabort(so2);
                 }                  }
Line 568  sodisconnect(struct socket *so)
Line 326  sodisconnect(struct socket *so)
             (struct proc *)0);              (struct proc *)0);
  bad:   bad:
         splx(s);          splx(s);
         sodopendfree(so);  
         return (error);          return (error);
 }  }
   
Line 596  sosend(struct socket *so, struct mbuf *a
Line 353  sosend(struct socket *so, struct mbuf *a
 {  {
         struct proc     *p;          struct proc     *p;
         struct mbuf     **mp, *m;          struct mbuf     **mp, *m;
         long            space, len, resid, clen, mlen;          long            space, len, resid;
         int             error, s, dontroute, atomic;          int             clen, error, s, dontroute, mlen, atomic;
   
         sodopendfree(so);  
   
         p = curproc;            /* XXX */          p = curproc;            /* XXX */
         clen = 0;          clen = 0;
Line 686  sosend(struct socket *so, struct mbuf *a
Line 441  sosend(struct socket *so, struct mbuf *a
                                         MGET(m, M_WAIT, MT_DATA);                                          MGET(m, M_WAIT, MT_DATA);
                                         mlen = MLEN;                                          mlen = MLEN;
                                 }                                  }
                                 if (use_sosend_loan &&  
                                     uio->uio_iov->iov_len >= SOCK_LOAN_THRESH &&  
                                     space >= SOCK_LOAN_THRESH &&  
                                     (len = sosend_loan(so, uio, m,  
                                                        space)) != 0) {  
                                         SOSEND_COUNTER_INCR(&sosend_loan_big);  
                                         space -= len;  
                                         goto have_data;  
                                 }  
                                 if (resid >= MINCLSIZE && space >= MCLBYTES) {                                  if (resid >= MINCLSIZE && space >= MCLBYTES) {
                                         SOSEND_COUNTER_INCR(&sosend_copy_big);  
                                         MCLGET(m, M_WAIT);                                          MCLGET(m, M_WAIT);
                                         if ((m->m_flags & M_EXT) == 0)                                          if ((m->m_flags & M_EXT) == 0)
                                                 goto nopages;                                                  goto nopages;
                                         mlen = MCLBYTES;                                          mlen = MCLBYTES;
   #ifdef  MAPPED_MBUFS
                                           len = min(MCLBYTES, resid);
   #else
                                         if (atomic && top == 0) {                                          if (atomic && top == 0) {
                                                 len = lmin(MCLBYTES - max_hdr,                                                  len = min(MCLBYTES - max_hdr,
                                                     resid);                                                      resid);
                                                 m->m_data += max_hdr;                                                  m->m_data += max_hdr;
                                         } else                                          } else
                                                 len = lmin(MCLBYTES, resid);                                                  len = min(MCLBYTES, resid);
   #endif
                                         space -= len;                                          space -= len;
                                 } else {                                  } else {
  nopages:  nopages:
                                         SOSEND_COUNTER_INCR(&sosend_copy_small);                                          len = min(min(mlen, resid), space);
                                         len = lmin(lmin(mlen, resid), space);  
                                         space -= len;                                          space -= len;
                                         /*                                          /*
                                          * For datagram protocols, leave room                                           * For datagram protocols, leave room
Line 722  sosend(struct socket *so, struct mbuf *a
Line 470  sosend(struct socket *so, struct mbuf *a
                                 }                                  }
                                 error = uiomove(mtod(m, caddr_t), (int)len,                                  error = uiomove(mtod(m, caddr_t), (int)len,
                                     uio);                                      uio);
  have_data:  
                                 resid = uio->uio_resid;                                  resid = uio->uio_resid;
                                 m->m_len = len;                                  m->m_len = len;
                                 *mp = m;                                  *mp = m;
Line 798  soreceive(struct socket *so, struct mbuf
Line 545  soreceive(struct socket *so, struct mbuf
         int             flags, len, error, s, offset, moff, type, orig_resid;          int             flags, len, error, s, offset, moff, type, orig_resid;
         struct protosw  *pr;          struct protosw  *pr;
         struct mbuf     *nextrecord;          struct mbuf     *nextrecord;
         int             mbuf_removed = 0;  
   
         pr = so->so_proto;          pr = so->so_proto;
         mp = mp0;          mp = mp0;
Line 812  soreceive(struct socket *so, struct mbuf
Line 558  soreceive(struct socket *so, struct mbuf
                 flags = *flagsp &~ MSG_EOR;                  flags = *flagsp &~ MSG_EOR;
         else          else
                 flags = 0;                  flags = 0;
   
         if ((flags & MSG_DONTWAIT) == 0)  
                 sodopendfree(so);  
   
         if (flags & MSG_OOB) {          if (flags & MSG_OOB) {
                 m = m_get(M_WAIT, MT_DATA);                  m = m_get(M_WAIT, MT_DATA);
                 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,                  error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
Line 895  soreceive(struct socket *so, struct mbuf
Line 637  soreceive(struct socket *so, struct mbuf
                         error = EWOULDBLOCK;                          error = EWOULDBLOCK;
                         goto release;                          goto release;
                 }                  }
                 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");  
                 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");  
                 sbunlock(&so->so_rcv);                  sbunlock(&so->so_rcv);
                 error = sbwait(&so->so_rcv);                  error = sbwait(&so->so_rcv);
                 splx(s);                  splx(s);
Line 905  soreceive(struct socket *so, struct mbuf
Line 645  soreceive(struct socket *so, struct mbuf
                 goto restart;                  goto restart;
         }          }
  dontblock:   dontblock:
         /*  
          * On entry here, m points to the first record of the socket buffer.  
          * While we process the initial mbufs containing address and control  
          * info, we save a copy of m->m_nextpkt into nextrecord.  
          */  
 #ifdef notyet /* XXXX */  #ifdef notyet /* XXXX */
         if (uio->uio_procp)          if (uio->uio_procp)
                 uio->uio_procp->p_stats->p_ru.ru_msgrcv++;                  uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
 #endif  #endif
         KASSERT(m == so->so_rcv.sb_mb);  
         SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");  
         SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");  
         nextrecord = m->m_nextpkt;          nextrecord = m->m_nextpkt;
         if (pr->pr_flags & PR_ADDR) {          if (pr->pr_flags & PR_ADDR) {
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
Line 930  soreceive(struct socket *so, struct mbuf
Line 662  soreceive(struct socket *so, struct mbuf
                         m = m->m_next;                          m = m->m_next;
                 } else {                  } else {
                         sbfree(&so->so_rcv, m);                          sbfree(&so->so_rcv, m);
                         mbuf_removed = 1;  
                         if (paddr) {                          if (paddr) {
                                 *paddr = m;                                  *paddr = m;
                                 so->so_rcv.sb_mb = m->m_next;                                  so->so_rcv.sb_mb = m->m_next;
Line 949  soreceive(struct socket *so, struct mbuf
Line 680  soreceive(struct socket *so, struct mbuf
                         m = m->m_next;                          m = m->m_next;
                 } else {                  } else {
                         sbfree(&so->so_rcv, m);                          sbfree(&so->so_rcv, m);
                         mbuf_removed = 1;  
                         if (controlp) {                          if (controlp) {
                                 if (pr->pr_domain->dom_externalize &&                                  if (pr->pr_domain->dom_externalize &&
                                     mtod(m, struct cmsghdr *)->cmsg_type ==                                      mtod(m, struct cmsghdr *)->cmsg_type ==
Line 969  soreceive(struct socket *so, struct mbuf
Line 699  soreceive(struct socket *so, struct mbuf
                         controlp = &(*controlp)->m_next;                          controlp = &(*controlp)->m_next;
                 }                  }
         }          }
   
         /*  
          * If m is non-NULL, we have some data to read.  From now on,  
          * make sure to keep sb_lastrecord consistent when working on  
          * the last packet on the chain (nextrecord == NULL) and we  
          * change m->m_nextpkt.  
          */  
         if (m) {          if (m) {
                 if ((flags & MSG_PEEK) == 0) {                  if ((flags & MSG_PEEK) == 0)
                         m->m_nextpkt = nextrecord;                          m->m_nextpkt = nextrecord;
                         /*  
                          * If nextrecord == NULL (this is a single chain),  
                          * then sb_lastrecord may not be valid here if m  
                          * was changed earlier.  
                          */  
                         if (nextrecord == NULL) {  
                                 KASSERT(so->so_rcv.sb_mb == m);  
                                 so->so_rcv.sb_lastrecord = m;  
                         }  
                 }  
                 type = m->m_type;                  type = m->m_type;
                 if (type == MT_OOBDATA)                  if (type == MT_OOBDATA)
                         flags |= MSG_OOB;                          flags |= MSG_OOB;
         } else {  
                 if ((flags & MSG_PEEK) == 0) {  
                         KASSERT(so->so_rcv.sb_mb == m);  
                         so->so_rcv.sb_mb = nextrecord;  
                         SB_EMPTY_FIXUP(&so->so_rcv);  
                 }  
         }          }
         SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");  
         SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");  
   
         moff = 0;          moff = 0;
         offset = 0;          offset = 0;
         while (m && uio->uio_resid > 0 && error == 0) {          while (m && uio->uio_resid > 0 && error == 0) {
Line 1029  soreceive(struct socket *so, struct mbuf
Line 733  soreceive(struct socket *so, struct mbuf
                  * block interrupts again.                   * block interrupts again.
                  */                   */
                 if (mp == 0) {                  if (mp == 0) {
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");  
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");  
                         splx(s);                          splx(s);
                         error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);                          error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
                         s = splsoftnet();                          s = splsoftnet();
                         if (error) {  
                                 /*  
                                  * If any part of the record has been removed  
                                  * (such as the MT_SONAME mbuf, which will  
                                  * happen when PR_ADDR, and thus also  
                                  * PR_ATOMIC, is set), then drop the entire  
                                  * record to maintain the atomicity of the  
                                  * receive operation.  
                                  *  
                                  * This avoids a later panic("receive 1a")  
                                  * when compiled with DIAGNOSTIC.  
                                  */  
                                 if (m && mbuf_removed  
                                     && (pr->pr_flags & PR_ATOMIC))  
                                         (void) sbdroprecord(&so->so_rcv);  
   
                                 goto release;  
                         }  
                 } else                  } else
                         uio->uio_resid -= len;                          uio->uio_resid -= len;
                 if (len == m->m_len - moff) {                  if (len == m->m_len - moff) {
Line 1072  soreceive(struct socket *so, struct mbuf
Line 756  soreceive(struct socket *so, struct mbuf
                                         MFREE(m, so->so_rcv.sb_mb);                                          MFREE(m, so->so_rcv.sb_mb);
                                         m = so->so_rcv.sb_mb;                                          m = so->so_rcv.sb_mb;
                                 }                                  }
                                 /*                                  if (m)
                                  * If m != NULL, we also know that  
                                  * so->so_rcv.sb_mb != NULL.  
                                  */  
                                 KASSERT(so->so_rcv.sb_mb == m);  
                                 if (m) {  
                                         m->m_nextpkt = nextrecord;                                          m->m_nextpkt = nextrecord;
                                         if (nextrecord == NULL)  
                                                 so->so_rcv.sb_lastrecord = m;  
                                 } else {  
                                         so->so_rcv.sb_mb = nextrecord;  
                                         SB_EMPTY_FIXUP(&so->so_rcv);  
                                 }  
                                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 3");  
                                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 3");  
                         }                          }
                 } else {                  } else {
                         if (flags & MSG_PEEK)                          if (flags & MSG_PEEK)
Line 1125  soreceive(struct socket *so, struct mbuf
Line 796  soreceive(struct socket *so, struct mbuf
                     !sosendallatonce(so) && !nextrecord) {                      !sosendallatonce(so) && !nextrecord) {
                         if (so->so_error || so->so_state & SS_CANTRCVMORE)                          if (so->so_error || so->so_state & SS_CANTRCVMORE)
                                 break;                                  break;
                         /*  
                          * If we are peeking and the socket receive buffer is  
                          * full, stop since we can't get more data to peek at.  
                          */  
                         if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0)  
                                 break;  
                         /*  
                          * If we've drained the socket buffer, tell the  
                          * protocol in case it needs to do something to  
                          * get it filled again.  
                          */  
                         if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)  
                                 (*pr->pr_usrreq)(so, PRU_RCVD,  
                                     (struct mbuf *)0,  
                                     (struct mbuf *)(long)flags,  
                                     (struct mbuf *)0,  
                                     (struct proc *)0);  
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");  
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");  
                         error = sbwait(&so->so_rcv);                          error = sbwait(&so->so_rcv);
                         if (error) {                          if (error) {
                                 sbunlock(&so->so_rcv);                                  sbunlock(&so->so_rcv);
Line 1161  soreceive(struct socket *so, struct mbuf
Line 813  soreceive(struct socket *so, struct mbuf
                         (void) sbdroprecord(&so->so_rcv);                          (void) sbdroprecord(&so->so_rcv);
         }          }
         if ((flags & MSG_PEEK) == 0) {          if ((flags & MSG_PEEK) == 0) {
                 if (m == 0) {                  if (m == 0)
                         /*  
                          * First part is an inline SB_EMPTY_FIXUP().  Second  
                          * part makes sure sb_lastrecord is up-to-date if  
                          * there is still data in the socket buffer.  
                          */  
                         so->so_rcv.sb_mb = nextrecord;                          so->so_rcv.sb_mb = nextrecord;
                         if (so->so_rcv.sb_mb == NULL) {  
                                 so->so_rcv.sb_mbtail = NULL;  
                                 so->so_rcv.sb_lastrecord = NULL;  
                         } else if (nextrecord->m_nextpkt == NULL)  
                                 so->so_rcv.sb_lastrecord = nextrecord;  
                 }  
                 SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");  
                 SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");  
                 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)                  if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
                         (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,                          (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
                             (struct mbuf *)(long)flags, (struct mbuf *)0,                              (struct mbuf *)(long)flags, (struct mbuf *)0,
Line 1224  sorflush(struct socket *so)
Line 863  sorflush(struct socket *so)
         pr = so->so_proto;          pr = so->so_proto;
         sb->sb_flags |= SB_NOINTR;          sb->sb_flags |= SB_NOINTR;
         (void) sblock(sb, M_WAITOK);          (void) sblock(sb, M_WAITOK);
         s = splnet();          s = splimp();
         socantrcvmore(so);          socantrcvmore(so);
         sbunlock(sb);          sbunlock(sb);
         asb = *sb;          asb = *sb;
Line 1341  sosetopt(struct socket *so, int level, i
Line 980  sosetopt(struct socket *so, int level, i
                                 goto bad;                                  goto bad;
                         }                          }
                         tv = mtod(m, struct timeval *);                          tv = mtod(m, struct timeval *);
                         if (tv->tv_sec > (SHRT_MAX - tv->tv_usec / tick) / hz) {                          if (tv->tv_sec * hz + tv->tv_usec / tick > SHRT_MAX) {
                                 error = EDOM;                                  error = EDOM;
                                 goto bad;                                  goto bad;
                         }                          }
                         val = tv->tv_sec * hz + tv->tv_usec / tick;                          val = tv->tv_sec * hz + tv->tv_usec / tick;
                         if (val == 0 && tv->tv_usec != 0)  
                                 val = 1;  
   
                         switch (optname) {                          switch (optname) {
   
Line 1471  sohasoutofband(struct socket *so)
Line 1108  sohasoutofband(struct socket *so)
                 psignal(p, SIGURG);                  psignal(p, SIGURG);
         selwakeup(&so->so_rcv.sb_sel);          selwakeup(&so->so_rcv.sb_sel);
 }  }
   
 static void  
 filt_sordetach(struct knote *kn)  
 {  
         struct socket   *so;  
   
         so = (struct socket *)kn->kn_fp->f_data;  
         SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext);  
         if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist))  
                 so->so_rcv.sb_flags &= ~SB_KNOTE;  
 }  
   
 /*ARGSUSED*/  
 static int  
 filt_soread(struct knote *kn, long hint)  
 {  
         struct socket   *so;  
   
         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;  
                 kn->kn_fflags = so->so_error;  
                 return (1);  
         }  
         if (so->so_error)       /* temporary udp error */  
                 return (1);  
         if (kn->kn_sfflags & NOTE_LOWAT)  
                 return (kn->kn_data >= kn->kn_sdata);  
         return (kn->kn_data >= so->so_rcv.sb_lowat);  
 }  
   
 static void  
 filt_sowdetach(struct knote *kn)  
 {  
         struct socket   *so;  
   
         so = (struct socket *)kn->kn_fp->f_data;  
         SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext);  
         if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist))  
                 so->so_snd.sb_flags &= ~SB_KNOTE;  
 }  
   
 /*ARGSUSED*/  
 static int  
 filt_sowrite(struct knote *kn, long hint)  
 {  
         struct socket   *so;  
   
         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;  
                 kn->kn_fflags = so->so_error;  
                 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);  
         if (kn->kn_sfflags & NOTE_LOWAT)  
                 return (kn->kn_data >= kn->kn_sdata);  
         return (kn->kn_data >= so->so_snd.sb_lowat);  
 }  
   
 /*ARGSUSED*/  
 static int  
 filt_solisten(struct knote *kn, long hint)  
 {  
         struct socket   *so;  
   
         so = (struct socket *)kn->kn_fp->f_data;  
   
         /*  
          * Set kn_data to number of incoming connections, not  
          * counting partial (incomplete) connections.  
          */  
         kn->kn_data = so->so_qlen;  
         return (kn->kn_data > 0);  
 }  
   
 static const struct filterops solisten_filtops =  
         { 1, NULL, filt_sordetach, filt_solisten };  
 static const struct filterops soread_filtops =  
         { 1, NULL, filt_sordetach, filt_soread };  
 static const struct filterops sowrite_filtops =  
         { 1, NULL, filt_sowdetach, filt_sowrite };  
   
 int  
 soo_kqfilter(struct file *fp, struct knote *kn)  
 {  
         struct socket   *so;  
         struct sockbuf  *sb;  
   
         so = (struct socket *)kn->kn_fp->f_data;  
         switch (kn->kn_filter) {  
         case EVFILT_READ:  
                 if (so->so_options & SO_ACCEPTCONN)  
                         kn->kn_fop = &solisten_filtops;  
                 else  
                         kn->kn_fop = &soread_filtops;  
                 sb = &so->so_rcv;  
                 break;  
         case EVFILT_WRITE:  
                 kn->kn_fop = &sowrite_filtops;  
                 sb = &so->so_snd;  
                 break;  
         default:  
                 return (1);  
         }  
         SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, kn, kn_selnext);  
         sb->sb_flags |= SB_KNOTE;  
         return (0);  
 }  
   

Legend:
Removed from v.1.54.2.18  
changed lines
  Added in v.1.55

CVSweb <webmaster@jp.NetBSD.org>