[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.159 and 1.159.2.1

version 1.159, 2008/04/14 15:42:20 version 1.159.2.1, 2008/05/18 12:35:11
Line 15 
Line 15 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    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   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Line 91  __KERNEL_RCSID(0, "$NetBSD$");
Line 84  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/socketvar.h>  #include <sys/socketvar.h>
 #include <sys/signalvar.h>  #include <sys/signalvar.h>
 #include <sys/resourcevar.h>  #include <sys/resourcevar.h>
 #include <sys/pool.h>  
 #include <sys/event.h>  #include <sys/event.h>
 #include <sys/poll.h>  #include <sys/poll.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
Line 100  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
   
 POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL,  
     IPL_SOFTNET);  
   
 MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");  MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
 MALLOC_DEFINE(M_SONAME, "soname", "socket name");  MALLOC_DEFINE(M_SONAME, "soname", "socket name");
   
Line 110  extern const struct fileops socketops;
Line 99  extern const struct fileops socketops;
   
 extern int      somaxconn;                      /* patchable (XXX sysctl) */  extern int      somaxconn;                      /* patchable (XXX sysctl) */
 int             somaxconn = SOMAXCONN;  int             somaxconn = SOMAXCONN;
   kmutex_t        *softnet_lock;
   
 #ifdef SOSEND_COUNTERS  #ifdef SOSEND_COUNTERS
 #include <sys/device.h>  #include <sys/device.h>
Line 277  sodopendfree(void)
Line 267  sodopendfree(void)
 {  {
         size_t rv;          size_t rv;
   
           if (__predict_true(so_pendfree == NULL))
                   return 0;
   
         mutex_enter(&so_pendfree_lock);          mutex_enter(&so_pendfree_lock);
         rv = sodopendfreel();          rv = sodopendfreel();
         mutex_exit(&so_pendfree_lock);          mutex_exit(&so_pendfree_lock);
Line 365  sosend_loan(struct socket *so, struct ui
Line 358  sosend_loan(struct socket *so, struct ui
         len = eva - sva;          len = eva - sva;
         npgs = len >> PAGE_SHIFT;          npgs = len >> PAGE_SHIFT;
   
         /* XXX KDASSERT */  
         KASSERT(npgs <= M_EXT_MAXPAGES);          KASSERT(npgs <= M_EXT_MAXPAGES);
   
         lva = sokvaalloc(len, so);          lva = sokvaalloc(len, so);
Line 441  soinit(void)
Line 433  soinit(void)
 {  {
   
         mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM);          mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM);
           softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
         cv_init(&socurkva_cv, "sokva");          cv_init(&socurkva_cv, "sokva");
   
         /* Set the initial adjusted socket buffer size. */          /* Set the initial adjusted socket buffer size. */
Line 460  soinit(void)
Line 453  soinit(void)
  */   */
 /*ARGSUSED*/  /*ARGSUSED*/
 int  int
 socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l)  socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l,
            struct socket *lockso)
 {  {
         const struct protosw    *prp;          const struct protosw    *prp;
         struct socket   *so;          struct socket   *so;
         uid_t           uid;          uid_t           uid;
         int             error, s;          int             error;
           kmutex_t        *lock;
   
         error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,          error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,
             KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type),              KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type),
Line 490  socreate(int dom, struct socket **aso, i
Line 485  socreate(int dom, struct socket **aso, i
                 return EPROTONOSUPPORT;                  return EPROTONOSUPPORT;
         if (prp->pr_type != type)          if (prp->pr_type != type)
                 return EPROTOTYPE;                  return EPROTOTYPE;
         s = splsoftnet();  
         so = pool_get(&socket_pool, PR_WAITOK);          so = soget(true);
         memset(so, 0, sizeof(*so));  
         TAILQ_INIT(&so->so_q0);  
         TAILQ_INIT(&so->so_q);  
         so->so_type = type;          so->so_type = type;
         so->so_proto = prp;          so->so_proto = prp;
         so->so_send = sosend;          so->so_send = sosend;
Line 504  socreate(int dom, struct socket **aso, i
Line 496  socreate(int dom, struct socket **aso, i
         so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;          so->so_snd.sb_mowner = &prp->pr_domain->dom_mowner;
         so->so_mowner = &prp->pr_domain->dom_mowner;          so->so_mowner = &prp->pr_domain->dom_mowner;
 #endif  #endif
         selinit(&so->so_rcv.sb_sel);  
         selinit(&so->so_snd.sb_sel);  
         uid = kauth_cred_geteuid(l->l_cred);          uid = kauth_cred_geteuid(l->l_cred);
         so->so_uidinfo = uid_find(uid);          so->so_uidinfo = uid_find(uid);
           if (lockso != NULL) {
                   /* Caller wants us to share a lock. */
                   lock = lockso->so_lock;
                   so->so_lock = lock;
                   mutex_obj_hold(lock);
                   mutex_enter(lock);
           } else {
                   /* Lock assigned and taken during PRU_ATTACH. */
           }
         error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,          error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL,
             (struct mbuf *)(long)proto, NULL, l);              (struct mbuf *)(long)proto, NULL, l);
           KASSERT(solocked(so));
         if (error != 0) {          if (error != 0) {
                 so->so_state |= SS_NOFDREF;                  so->so_state |= SS_NOFDREF;
                 sofree(so);                  sofree(so);
                 splx(s);  
                 return error;                  return error;
         }          }
         splx(s);          sounlock(so);
         *aso = so;          *aso = so;
         return 0;          return 0;
 }  }
Line 537  fsocreate(int domain, struct socket **so
Line 536  fsocreate(int domain, struct socket **so
         fp->f_flag = FREAD|FWRITE;          fp->f_flag = FREAD|FWRITE;
         fp->f_type = DTYPE_SOCKET;          fp->f_type = DTYPE_SOCKET;
         fp->f_ops = &socketops;          fp->f_ops = &socketops;
         error = socreate(domain, &so, type, protocol, l);          error = socreate(domain, &so, type, protocol, l, NULL);
         if (error != 0) {          if (error != 0) {
                 fd_abort(curproc, fp, fd);                  fd_abort(curproc, fp, fd);
         } else {          } else {
Line 553  fsocreate(int domain, struct socket **so
Line 552  fsocreate(int domain, struct socket **so
 int  int
 sobind(struct socket *so, struct mbuf *nam, struct lwp *l)  sobind(struct socket *so, struct mbuf *nam, struct lwp *l)
 {  {
         int     s, error;          int     error;
   
         s = splsoftnet();          solock(so);
         error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, l);          error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, NULL, nam, NULL, l);
         splx(s);          sounlock(so);
         return error;          return error;
 }  }
   
 int  int
 solisten(struct socket *so, int backlog, struct lwp *l)  solisten(struct socket *so, int backlog, struct lwp *l)
 {  {
         int     s, error;          int     error;
   
         s = splsoftnet();          solock(so);
         if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING |          if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING |
             SS_ISDISCONNECTING)) != 0)              SS_ISDISCONNECTING)) != 0) {
                   sounlock(so);
                 return (EOPNOTSUPP);                  return (EOPNOTSUPP);
           }
         error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL,          error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL,
             NULL, NULL, l);              NULL, NULL, l);
         if (error != 0) {          if (error != 0) {
                 splx(s);                  sounlock(so);
                 return error;                  return error;
         }          }
         if (TAILQ_EMPTY(&so->so_q))          if (TAILQ_EMPTY(&so->so_q))
Line 581  solisten(struct socket *so, int backlog,
Line 582  solisten(struct socket *so, int backlog,
         if (backlog < 0)          if (backlog < 0)
                 backlog = 0;                  backlog = 0;
         so->so_qlimit = min(backlog, somaxconn);          so->so_qlimit = min(backlog, somaxconn);
         splx(s);          sounlock(so);
         return 0;          return 0;
 }  }
   
 void  void
 sofree(struct socket *so)  sofree(struct socket *so)
 {  {
           u_int refs;
   
         if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)          KASSERT(solocked(so));
   
           if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) {
                   sounlock(so);
                 return;                  return;
           }
         if (so->so_head) {          if (so->so_head) {
                 /*                  /*
                  * We must not decommission a socket that's on the accept(2)                   * We must not decommission a socket that's on the accept(2)
                  * queue.  If we do, then accept(2) may hang after select(2)                   * queue.  If we do, then accept(2) may hang after select(2)
                  * indicated that the listening socket was ready.                   * indicated that the listening socket was ready.
                  */                   */
                 if (!soqremque(so, 0))                  if (!soqremque(so, 0)) {
                           sounlock(so);
                         return;                          return;
                   }
         }          }
         if (so->so_rcv.sb_hiwat)          if (so->so_rcv.sb_hiwat)
                 (void)chgsbsize(so->so_uidinfo, &so->so_rcv.sb_hiwat, 0,                  (void)chgsbsize(so->so_uidinfo, &so->so_rcv.sb_hiwat, 0,
Line 607  sofree(struct socket *so)
Line 615  sofree(struct socket *so)
                 (void)chgsbsize(so->so_uidinfo, &so->so_snd.sb_hiwat, 0,                  (void)chgsbsize(so->so_uidinfo, &so->so_snd.sb_hiwat, 0,
                     RLIM_INFINITY);                      RLIM_INFINITY);
         sbrelease(&so->so_snd, so);          sbrelease(&so->so_snd, so);
           KASSERT(!cv_has_waiters(&so->so_cv));
           KASSERT(!cv_has_waiters(&so->so_rcv.sb_cv));
           KASSERT(!cv_has_waiters(&so->so_snd.sb_cv));
         sorflush(so);          sorflush(so);
         seldestroy(&so->so_rcv.sb_sel);          refs = so->so_aborting; /* XXX */
         seldestroy(&so->so_snd.sb_sel);          sounlock(so);
         pool_put(&socket_pool, so);          if (refs == 0)          /* XXX */
                   soput(so);
 }  }
   
 /*  /*
Line 622  int
Line 634  int
 soclose(struct socket *so)  soclose(struct socket *so)
 {  {
         struct socket   *so2;          struct socket   *so2;
         int             s, error;          int             error;
           int             error2;
   
         error = 0;          error = 0;
         s = splsoftnet();               /* conservative */          solock(so);
         if (so->so_options & SO_ACCEPTCONN) {          if (so->so_options & SO_ACCEPTCONN) {
                 while ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {                  do {
                         (void) soqremque(so2, 0);                          if ((so2 = TAILQ_FIRST(&so->so_q0)) != 0) {
                         (void) soabort(so2);                                  KASSERT(solocked2(so, so2));
                 }                                  (void) soqremque(so2, 0);
                 while ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {                                  /* soabort drops the lock. */
                         (void) soqremque(so2, 1);                                  (void) soabort(so2);
                         (void) soabort(so2);                                  solock(so);
                 }                                  continue;
                           }
                           if ((so2 = TAILQ_FIRST(&so->so_q)) != 0) {
                                   KASSERT(solocked2(so, so2));
                                   (void) soqremque(so2, 1);
                                   /* soabort drops the lock. */
                                   (void) soabort(so2);
                                   solock(so);
                                   continue;
                           }
                   } while (0);
         }          }
         if (so->so_pcb == 0)          if (so->so_pcb == 0)
                 goto discard;                  goto discard;
Line 648  soclose(struct socket *so)
Line 671  soclose(struct socket *so)
                         if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio)                          if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio)
                                 goto drop;                                  goto drop;
                         while (so->so_state & SS_ISCONNECTED) {                          while (so->so_state & SS_ISCONNECTED) {
                                 error = tsleep((void *)&so->so_timeo,                                  error = sowait(so, so->so_linger * hz);
                                                PSOCK | PCATCH, netcls,  
                                                so->so_linger * hz);  
                                 if (error)                                  if (error)
                                         break;                                          break;
                         }                          }
Line 658  soclose(struct socket *so)
Line 679  soclose(struct socket *so)
         }          }
  drop:   drop:
         if (so->so_pcb) {          if (so->so_pcb) {
                 int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,                  error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
                     NULL, NULL, NULL, NULL);                      NULL, NULL, NULL, NULL);
                 if (error == 0)                  if (error == 0)
                         error = error2;                          error = error2;
Line 668  soclose(struct socket *so)
Line 689  soclose(struct socket *so)
                 panic("soclose: NOFDREF");                  panic("soclose: NOFDREF");
         so->so_state |= SS_NOFDREF;          so->so_state |= SS_NOFDREF;
         sofree(so);          sofree(so);
         splx(s);  
         return (error);          return (error);
 }  }
   
 /*  /*
  * Must be called at splsoftnet...   * Must be called with the socket locked..  Will return with it unlocked.
  */   */
 int  int
 soabort(struct socket *so)  soabort(struct socket *so)
 {  {
           u_int refs;
         int error;          int error;
   
           KASSERT(solocked(so));
         KASSERT(so->so_head == NULL);          KASSERT(so->so_head == NULL);
   
           so->so_aborting++;              /* XXX */
         error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL,          error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, NULL,
             NULL, NULL, NULL);              NULL, NULL, NULL);
         if (error) {          refs = --so->so_aborting;       /* XXX */
           if (error || (refs == 0)) {
                 sofree(so);                  sofree(so);
           } else {
                   sounlock(so);
         }          }
         return error;          return error;
 }  }
Line 692  soabort(struct socket *so)
Line 719  soabort(struct socket *so)
 int  int
 soaccept(struct socket *so, struct mbuf *nam)  soaccept(struct socket *so, struct mbuf *nam)
 {  {
         int     s, error;          int     error;
   
           KASSERT(solocked(so));
   
         error = 0;          error = 0;
         s = splsoftnet();  
         if ((so->so_state & SS_NOFDREF) == 0)          if ((so->so_state & SS_NOFDREF) == 0)
                 panic("soaccept: !NOFDREF");                  panic("soaccept: !NOFDREF");
         so->so_state &= ~SS_NOFDREF;          so->so_state &= ~SS_NOFDREF;
Line 706  soaccept(struct socket *so, struct mbuf 
Line 734  soaccept(struct socket *so, struct mbuf 
         else          else
                 error = ECONNABORTED;                  error = ECONNABORTED;
   
         splx(s);  
         return (error);          return (error);
 }  }
   
 int  int
 soconnect(struct socket *so, struct mbuf *nam, struct lwp *l)  soconnect(struct socket *so, struct mbuf *nam, struct lwp *l)
 {  {
         int             s, error;          int             error;
   
           KASSERT(solocked(so));
   
         if (so->so_options & SO_ACCEPTCONN)          if (so->so_options & SO_ACCEPTCONN)
                 return (EOPNOTSUPP);                  return (EOPNOTSUPP);
         s = splsoftnet();  
         /*          /*
          * If protocol is connection-based, can only connect once.           * If protocol is connection-based, can only connect once.
          * Otherwise, if connected, try to disconnect first.           * Otherwise, if connected, try to disconnect first.
Line 731  soconnect(struct socket *so, struct mbuf
Line 759  soconnect(struct socket *so, struct mbuf
         else          else
                 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,                  error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
                     NULL, nam, NULL, l);                      NULL, nam, NULL, l);
         splx(s);  
         return (error);          return (error);
 }  }
   
 int  int
 soconnect2(struct socket *so1, struct socket *so2)  soconnect2(struct socket *so1, struct socket *so2)
 {  {
         int     s, error;          int     error;
   
           KASSERT(solocked2(so1, so2));
   
         s = splsoftnet();  
         error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,          error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
             NULL, (struct mbuf *)so2, NULL, NULL);              NULL, (struct mbuf *)so2, NULL, NULL);
         splx(s);  
         return (error);          return (error);
 }  }
   
 int  int
 sodisconnect(struct socket *so)  sodisconnect(struct socket *so)
 {  {
         int     s, error;          int     error;
   
           KASSERT(solocked(so));
   
         s = splsoftnet();  
         if ((so->so_state & SS_ISCONNECTED) == 0) {          if ((so->so_state & SS_ISCONNECTED) == 0) {
                 error = ENOTCONN;                  error = ENOTCONN;
                 goto bad;          } else if (so->so_state & SS_ISDISCONNECTING) {
         }  
         if (so->so_state & SS_ISDISCONNECTING) {  
                 error = EALREADY;                  error = EALREADY;
                 goto bad;          } else {
                   error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
                       NULL, NULL, NULL, NULL);
         }          }
         error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,  
             NULL, NULL, NULL, NULL);  
  bad:  
         splx(s);  
         sodopendfree();          sodopendfree();
         return (error);          return (error);
 }  }
Line 798  sosend(struct socket *so, struct mbuf *a
Line 822  sosend(struct socket *so, struct mbuf *a
   
         p = l->l_proc;          p = l->l_proc;
         sodopendfree();          sodopendfree();
   
         clen = 0;          clen = 0;
   
           /*
            * solock() provides atomicity of access.  splsoftnet() prevents
            * protocol processing soft interrupts from interrupting us and
            * blocking (expensive).
            */
           s = splsoftnet();
           solock(so);
         atomic = sosendallatonce(so) || top;          atomic = sosendallatonce(so) || top;
         if (uio)          if (uio)
                 resid = uio->uio_resid;                  resid = uio->uio_resid;
Line 823  sosend(struct socket *so, struct mbuf *a
Line 854  sosend(struct socket *so, struct mbuf *a
                 l->l_ru.ru_msgsnd++;                  l->l_ru.ru_msgsnd++;
         if (control)          if (control)
                 clen = control->m_len;                  clen = control->m_len;
 #define snderr(errno)   { error = errno; splx(s); goto release; }  
   
  restart:   restart:
         if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)          if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
                 goto out;                  goto out;
         do {          do {
                 s = splsoftnet();                  if (so->so_state & SS_CANTSENDMORE) {
                 if (so->so_state & SS_CANTSENDMORE)                          error = EPIPE;
                         snderr(EPIPE);                          goto release;
                   }
                 if (so->so_error) {                  if (so->so_error) {
                         error = so->so_error;                          error = so->so_error;
                         so->so_error = 0;                          so->so_error = 0;
                         splx(s);  
                         goto release;                          goto release;
                 }                  }
                 if ((so->so_state & SS_ISCONNECTED) == 0) {                  if ((so->so_state & SS_ISCONNECTED) == 0) {
                         if (so->so_proto->pr_flags & PR_CONNREQUIRED) {                          if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
                                 if ((so->so_state & SS_ISCONFIRMING) == 0 &&                                  if ((so->so_state & SS_ISCONFIRMING) == 0 &&
                                     !(resid == 0 && clen != 0))                                      !(resid == 0 && clen != 0)) {
                                         snderr(ENOTCONN);                                          error = ENOTCONN;
                         } else if (addr == 0)                                          goto release;
                                 snderr(EDESTADDRREQ);                                  }
                           } else if (addr == 0) {
                                   error = EDESTADDRREQ;
                                   goto release;
                           }
                 }                  }
                 space = sbspace(&so->so_snd);                  space = sbspace(&so->so_snd);
                 if (flags & MSG_OOB)                  if (flags & MSG_OOB)
                         space += 1024;                          space += 1024;
                 if ((atomic && resid > so->so_snd.sb_hiwat) ||                  if ((atomic && resid > so->so_snd.sb_hiwat) ||
                     clen > so->so_snd.sb_hiwat)                      clen > so->so_snd.sb_hiwat) {
                         snderr(EMSGSIZE);                          error = EMSGSIZE;
                           goto release;
                   }
                 if (space < resid + clen &&                  if (space < resid + clen &&
                     (atomic || space < so->so_snd.sb_lowat || space < clen)) {                      (atomic || space < so->so_snd.sb_lowat || space < clen)) {
                         if (so->so_nbio)                          if (so->so_nbio) {
                                 snderr(EWOULDBLOCK);                                  error = EWOULDBLOCK;
                                   goto release;
                           }
                         sbunlock(&so->so_snd);                          sbunlock(&so->so_snd);
                         error = sbwait(&so->so_snd);                          error = sbwait(&so->so_snd);
                         splx(s);  
                         if (error)                          if (error)
                                 goto out;                                  goto out;
                         goto restart;                          goto restart;
                 }                  }
                 splx(s);  
                 mp = &top;                  mp = &top;
                 space -= clen;                  space -= clen;
                 do {                  do {
Line 875  sosend(struct socket *so, struct mbuf *a
Line 910  sosend(struct socket *so, struct mbuf *a
                                 if (flags & MSG_EOR)                                  if (flags & MSG_EOR)
                                         top->m_flags |= M_EOR;                                          top->m_flags |= M_EOR;
                         } else do {                          } else do {
                                   sounlock(so);
                                   splx(s);
                                 if (top == NULL) {                                  if (top == NULL) {
                                         m = m_gethdr(M_WAIT, MT_DATA);                                          m = m_gethdr(M_WAIT, MT_DATA);
                                         mlen = MHLEN;                                          mlen = MHLEN;
Line 925  sosend(struct socket *so, struct mbuf *a
Line 962  sosend(struct socket *so, struct mbuf *a
                                 m->m_len = len;                                  m->m_len = len;
                                 *mp = m;                                  *mp = m;
                                 top->m_pkthdr.len += len;                                  top->m_pkthdr.len += len;
                                   s = splsoftnet();
                                   solock(so);
                                 if (error != 0)                                  if (error != 0)
                                         goto release;                                          goto release;
                                 mp = &m->m_next;                                  mp = &m->m_next;
Line 935  sosend(struct socket *so, struct mbuf *a
Line 974  sosend(struct socket *so, struct mbuf *a
                                 }                                  }
                         } while (space > 0 && atomic);                          } while (space > 0 && atomic);
   
                         s = splsoftnet();                          if (so->so_state & SS_CANTSENDMORE) {
                                   error = EPIPE;
                         if (so->so_state & SS_CANTSENDMORE)                                  goto release;
                                 snderr(EPIPE);                          }
   
                         if (dontroute)                          if (dontroute)
                                 so->so_options |= SO_DONTROUTE;                                  so->so_options |= SO_DONTROUTE;
                         if (resid > 0)                          if (resid > 0)
                                 so->so_state |= SS_MORETOCOME;                                  so->so_state |= SS_MORETOCOME;
                         error = (*so->so_proto->pr_usrreq)(so,                          error = (*so->so_proto->pr_usrreq)(so,
                             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,                              (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
                             top, addr, control, curlwp);        /* XXX */                              top, addr, control, curlwp);
                         if (dontroute)                          if (dontroute)
                                 so->so_options &= ~SO_DONTROUTE;                                  so->so_options &= ~SO_DONTROUTE;
                         if (resid > 0)                          if (resid > 0)
                                 so->so_state &= ~SS_MORETOCOME;                                  so->so_state &= ~SS_MORETOCOME;
                         splx(s);  
   
                         clen = 0;                          clen = 0;
                         control = NULL;                          control = NULL;
                         top = NULL;                          top = NULL;
Line 965  sosend(struct socket *so, struct mbuf *a
Line 1001  sosend(struct socket *so, struct mbuf *a
  release:   release:
         sbunlock(&so->so_snd);          sbunlock(&so->so_snd);
  out:   out:
           sounlock(so);
           splx(s);
         if (top)          if (top)
                 m_freem(top);                  m_freem(top);
         if (control)          if (control)
Line 984  static void
Line 1022  static void
 sbsync(struct sockbuf *sb, struct mbuf *nextrecord)  sbsync(struct sockbuf *sb, struct mbuf *nextrecord)
 {  {
   
           KASSERT(solocked(sb->sb_so));
   
         /*          /*
          * First, update for the new value of nextrecord.  If necessary,           * First, update for the new value of nextrecord.  If necessary,
          * make it the first record.           * make it the first record.
Line 1028  soreceive(struct socket *so, struct mbuf
Line 1068  soreceive(struct socket *so, struct mbuf
         struct mbuf **mp0, struct mbuf **controlp, int *flagsp)          struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
 {  {
         struct lwp *l = curlwp;          struct lwp *l = curlwp;
         struct mbuf     *m, **mp;          struct mbuf     *m, **mp, *mt;
         int atomic, flags, len, error, s, offset, moff, type, orig_resid;          int atomic, flags, len, error, s, offset, moff, type, orig_resid;
         const struct protosw    *pr;          const struct protosw    *pr;
         struct mbuf     *nextrecord;          struct mbuf     *nextrecord;
Line 1056  soreceive(struct socket *so, struct mbuf
Line 1096  soreceive(struct socket *so, struct mbuf
   
         if (flags & MSG_OOB) {          if (flags & MSG_OOB) {
                 m = m_get(M_WAIT, MT_DATA);                  m = m_get(M_WAIT, MT_DATA);
                   solock(so);
                 error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,                  error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
                     (struct mbuf *)(long)(flags & MSG_PEEK), NULL, l);                      (struct mbuf *)(long)(flags & MSG_PEEK), NULL, l);
                   sounlock(so);
                 if (error)                  if (error)
                         goto bad;                          goto bad;
                 do {                  do {
Line 1072  soreceive(struct socket *so, struct mbuf
Line 1114  soreceive(struct socket *so, struct mbuf
         }          }
         if (mp != NULL)          if (mp != NULL)
                 *mp = NULL;                  *mp = NULL;
   
           /*
            * solock() provides atomicity of access.  splsoftnet() prevents
            * protocol processing soft interrupts from interrupting us and
            * blocking (expensive).
            */
           s = splsoftnet();
           solock(so);
         if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)          if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
                 (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l);                  (*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l);
   
  restart:   restart:
         if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)          if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) {
                   sounlock(so);
                   splx(s);
                 return error;                  return error;
         s = splsoftnet();          }
   
         m = so->so_rcv.sb_mb;          m = so->so_rcv.sb_mb;
         /*          /*
Line 1137  soreceive(struct socket *so, struct mbuf
Line 1189  soreceive(struct socket *so, struct mbuf
                 SBLASTMBUFCHK(&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);                  if (error != 0) {
                 if (error != 0)                          sounlock(so);
                           splx(s);
                         return error;                          return error;
                   }
                 goto restart;                  goto restart;
         }          }
  dontblock:   dontblock:
Line 1149  soreceive(struct socket *so, struct mbuf
Line 1203  soreceive(struct socket *so, struct mbuf
          * pointer to the next record in the socket buffer.  We must keep the           * pointer to the next record in the socket buffer.  We must keep the
          * various socket buffer pointers and local stack versions of the           * various socket buffer pointers and local stack versions of the
          * pointers in sync, pushing out modifications before dropping the           * pointers in sync, pushing out modifications before dropping the
          * IPL, and re-reading them when picking it up.           * socket lock, and re-reading them when picking it up.
          *           *
          * Otherwise, we will race with the network stack appending new data           * Otherwise, we will race with the network stack appending new data
          * or records onto the socket buffer by using inconsistent/stale           * or records onto the socket buffer by using inconsistent/stale
Line 1226  soreceive(struct socket *so, struct mbuf
Line 1280  soreceive(struct socket *so, struct mbuf
                         if (controlp != NULL) {                          if (controlp != NULL) {
                                 if (dom->dom_externalize != NULL &&                                  if (dom->dom_externalize != NULL &&
                                     type == SCM_RIGHTS) {                                      type == SCM_RIGHTS) {
                                           sounlock(so);
                                         splx(s);                                          splx(s);
                                         error = (*dom->dom_externalize)(cm, l);                                          error = (*dom->dom_externalize)(cm, l);
                                         s = splsoftnet();                                          s = splsoftnet();
                                           solock(so);
                                 }                                  }
                                 *controlp = cm;                                  *controlp = cm;
                                 while (*controlp != NULL)                                  while (*controlp != NULL)
Line 1240  soreceive(struct socket *so, struct mbuf
Line 1296  soreceive(struct socket *so, struct mbuf
                                  */                                   */
                                 if (dom->dom_dispose != NULL &&                                  if (dom->dom_dispose != NULL &&
                                     type == SCM_RIGHTS) {                                      type == SCM_RIGHTS) {
                                         splx(s);                                          sounlock(so);
                                         (*dom->dom_dispose)(cm);                                          (*dom->dom_dispose)(cm);
                                         s = splsoftnet();                                          solock(so);
                                 }                                  }
                                 m_freem(cm);                                  m_freem(cm);
                         }                          }
Line 1292  soreceive(struct socket *so, struct mbuf
Line 1348  soreceive(struct socket *so, struct mbuf
                 if (mp == NULL) {                  if (mp == NULL) {
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
                           sounlock(so);
                         splx(s);                          splx(s);
                         error = uiomove(mtod(m, char *) + moff, (int)len, uio);                          error = uiomove(mtod(m, char *) + moff, (int)len, uio);
                         s = splsoftnet();                          s = splsoftnet();
                           solock(so);
                         if (error != 0) {                          if (error != 0) {
                                 /*                                  /*
                                  * If any part of the record has been removed                                   * If any part of the record has been removed
Line 1351  soreceive(struct socket *so, struct mbuf
Line 1409  soreceive(struct socket *so, struct mbuf
                 } else if (flags & MSG_PEEK)                  } else if (flags & MSG_PEEK)
                         moff += len;                          moff += len;
                 else {                  else {
                         if (mp != NULL)                          if (mp != NULL) {
                                 *mp = m_copym(m, 0, len, M_WAIT);                                  mt = m_copym(m, 0, len, M_NOWAIT);
                                   if (__predict_false(mt == NULL)) {
                                           sounlock(so);
                                           mt = m_copym(m, 0, len, M_WAIT);
                                           solock(so);
                                   }
                                   *mp = mt;
                           }
                         m->m_data += len;                          m->m_data += len;
                         m->m_len -= len;                          m->m_len -= len;
                         so->so_rcv.sb_cc -= len;                          so->so_rcv.sb_cc -= len;
Line 1402  soreceive(struct socket *so, struct mbuf
Line 1467  soreceive(struct socket *so, struct mbuf
                         error = sbwait(&so->so_rcv);                          error = sbwait(&so->so_rcv);
                         if (error != 0) {                          if (error != 0) {
                                 sbunlock(&so->so_rcv);                                  sbunlock(&so->so_rcv);
                                   sounlock(so);
                                 splx(s);                                  splx(s);
                                 return 0;                                  return 0;
                         }                          }
Line 1438  soreceive(struct socket *so, struct mbuf
Line 1504  soreceive(struct socket *so, struct mbuf
         if (orig_resid == uio->uio_resid && orig_resid &&          if (orig_resid == uio->uio_resid && orig_resid &&
             (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {              (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
                 sbunlock(&so->so_rcv);                  sbunlock(&so->so_rcv);
                 splx(s);  
                 goto restart;                  goto restart;
         }          }
   
Line 1446  soreceive(struct socket *so, struct mbuf
Line 1511  soreceive(struct socket *so, struct mbuf
                 *flagsp |= flags;                  *flagsp |= flags;
  release:   release:
         sbunlock(&so->so_rcv);          sbunlock(&so->so_rcv);
           sounlock(so);
         splx(s);          splx(s);
         return error;          return error;
 }  }
Line 1454  int
Line 1520  int
 soshutdown(struct socket *so, int how)  soshutdown(struct socket *so, int how)
 {  {
         const struct protosw    *pr;          const struct protosw    *pr;
           int     error;
   
           KASSERT(solocked(so));
   
         pr = so->so_proto;          pr = so->so_proto;
         if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))          if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
                 return (EINVAL);                  return (EINVAL);
   
         if (how == SHUT_RD || how == SHUT_RDWR)          if (how == SHUT_RD || how == SHUT_RDWR) {
                 sorflush(so);                  sorflush(so);
                   error = 0;
           }
         if (how == SHUT_WR || how == SHUT_RDWR)          if (how == SHUT_WR || how == SHUT_RDWR)
                 return (*pr->pr_usrreq)(so, PRU_SHUTDOWN, NULL,                  error = (*pr->pr_usrreq)(so, PRU_SHUTDOWN, NULL,
                     NULL, NULL, NULL);                      NULL, NULL, NULL);
         return 0;  
           return error;
 }  }
   
 void  void
Line 1472  sorflush(struct socket *so)
Line 1544  sorflush(struct socket *so)
 {  {
         struct sockbuf  *sb, asb;          struct sockbuf  *sb, asb;
         const struct protosw    *pr;          const struct protosw    *pr;
         int             s;  
           KASSERT(solocked(so));
   
         sb = &so->so_rcv;          sb = &so->so_rcv;
         pr = so->so_proto;          pr = so->so_proto;
         sb->sb_flags |= SB_NOINTR;  
         (void) sblock(sb, M_WAITOK);  
         s = splnet();  
         socantrcvmore(so);          socantrcvmore(so);
           sb->sb_flags |= SB_NOINTR;
           (void )sblock(sb, M_WAITOK);
         sbunlock(sb);          sbunlock(sb);
         asb = *sb;          asb = *sb;
         /*          /*
Line 1488  sorflush(struct socket *so)
Line 1560  sorflush(struct socket *so)
          */           */
         memset(&sb->sb_startzero, 0,          memset(&sb->sb_startzero, 0,
             sizeof(*sb) - offsetof(struct sockbuf, sb_startzero));              sizeof(*sb) - offsetof(struct sockbuf, sb_startzero));
         splx(s);          if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) {
         if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)                  sounlock(so);
                 (*pr->pr_domain->dom_dispose)(asb.sb_mb);                  (*pr->pr_domain->dom_dispose)(asb.sb_mb);
                   solock(so);
           }
         sbrelease(&asb, so);          sbrelease(&asb, so);
 }  }
   
Line 1611  sosetopt(struct socket *so, int level, i
Line 1685  sosetopt(struct socket *so, int level, i
 {  {
         int error, prerr;          int error, prerr;
   
           solock(so);
         if (level == SOL_SOCKET)          if (level == SOL_SOCKET)
                 error = sosetopt1(so, level, optname, m);                  error = sosetopt1(so, level, optname, m);
         else          else
Line 1627  sosetopt(struct socket *so, int level, i
Line 1702  sosetopt(struct socket *so, int level, i
                         error = prerr;                          error = prerr;
         } else if (m != NULL)          } else if (m != NULL)
                 (void)m_free(m);                  (void)m_free(m);
           sounlock(so);
         return error;          return error;
 }  }
   
Line 1634  int
Line 1710  int
 sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)  sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
 {  {
         struct mbuf     *m;          struct mbuf     *m;
           int             error;
   
           solock(so);
         if (level != SOL_SOCKET) {          if (level != SOL_SOCKET) {
                 if (so->so_proto && so->so_proto->pr_ctloutput) {                  if (so->so_proto && so->so_proto->pr_ctloutput) {
                         return ((*so->so_proto->pr_ctloutput)                          error = ((*so->so_proto->pr_ctloutput)
                                   (PRCO_GETOPT, so, level, optname, mp));                                    (PRCO_GETOPT, so, level, optname, mp));
                 } else                  } else
                         return (ENOPROTOOPT);                          error = (ENOPROTOOPT);
         } else {          } else {
                 m = m_get(M_WAIT, MT_SOOPTS);                  m = m_get(M_WAIT, MT_SOOPTS);
                 m->m_len = sizeof(int);                  m->m_len = sizeof(int);
Line 1709  sogetopt(struct socket *so, int level, i
Line 1787  sogetopt(struct socket *so, int level, i
                         break;                          break;
   
                 default:                  default:
                           sounlock(so);
                         (void)m_free(m);                          (void)m_free(m);
                         return (ENOPROTOOPT);                          return (ENOPROTOOPT);
                 }                  }
                 *mp = m;                  *mp = m;
                 return (0);                  error = 0;
         }          }
   
           sounlock(so);
           return (error);
 }  }
   
 void  void
Line 1731  filt_sordetach(struct knote *kn)
Line 1813  filt_sordetach(struct knote *kn)
         struct socket   *so;          struct socket   *so;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
           solock(so);
         SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext);          SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext);
         if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist))          if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist))
                 so->so_rcv.sb_flags &= ~SB_KNOTE;                  so->so_rcv.sb_flags &= ~SB_KNOTE;
           sounlock(so);
 }  }
   
 /*ARGSUSED*/  /*ARGSUSED*/
Line 1741  static int
Line 1825  static int
 filt_soread(struct knote *kn, long hint)  filt_soread(struct knote *kn, long hint)
 {  {
         struct socket   *so;          struct socket   *so;
           int rv;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
           if (hint != NOTE_SUBMIT)
                   solock(so);
         kn->kn_data = so->so_rcv.sb_cc;          kn->kn_data = so->so_rcv.sb_cc;
         if (so->so_state & SS_CANTRCVMORE) {          if (so->so_state & SS_CANTRCVMORE) {
                 kn->kn_flags |= EV_EOF;                  kn->kn_flags |= EV_EOF;
                 kn->kn_fflags = so->so_error;                  kn->kn_fflags = so->so_error;
                 return (1);                  rv = 1;
         }          } else if (so->so_error)        /* temporary udp error */
         if (so->so_error)       /* temporary udp error */                  rv = 1;
                 return (1);          else if (kn->kn_sfflags & NOTE_LOWAT)
         if (kn->kn_sfflags & NOTE_LOWAT)                  rv = (kn->kn_data >= kn->kn_sdata);
                 return (kn->kn_data >= kn->kn_sdata);          else
         return (kn->kn_data >= so->so_rcv.sb_lowat);                  rv = (kn->kn_data >= so->so_rcv.sb_lowat);
           if (hint != NOTE_SUBMIT)
                   sounlock(so);
           return rv;
 }  }
   
 static void  static void
Line 1762  filt_sowdetach(struct knote *kn)
Line 1852  filt_sowdetach(struct knote *kn)
         struct socket   *so;          struct socket   *so;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
           solock(so);
         SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext);          SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext);
         if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist))          if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist))
                 so->so_snd.sb_flags &= ~SB_KNOTE;                  so->so_snd.sb_flags &= ~SB_KNOTE;
           sounlock(so);
 }  }
   
 /*ARGSUSED*/  /*ARGSUSED*/
Line 1772  static int
Line 1864  static int
 filt_sowrite(struct knote *kn, long hint)  filt_sowrite(struct knote *kn, long hint)
 {  {
         struct socket   *so;          struct socket   *so;
           int rv;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
           if (hint != NOTE_SUBMIT)
                   solock(so);
         kn->kn_data = sbspace(&so->so_snd);          kn->kn_data = sbspace(&so->so_snd);
         if (so->so_state & SS_CANTSENDMORE) {          if (so->so_state & SS_CANTSENDMORE) {
                 kn->kn_flags |= EV_EOF;                  kn->kn_flags |= EV_EOF;
                 kn->kn_fflags = so->so_error;                  kn->kn_fflags = so->so_error;
                 return (1);                  rv = 1;
         }          } else if (so->so_error)        /* temporary udp error */
         if (so->so_error)       /* temporary udp error */                  rv = 1;
                 return (1);          else if (((so->so_state & SS_ISCONNECTED) == 0) &&
         if (((so->so_state & SS_ISCONNECTED) == 0) &&  
             (so->so_proto->pr_flags & PR_CONNREQUIRED))              (so->so_proto->pr_flags & PR_CONNREQUIRED))
                 return (0);                  rv = 0;
         if (kn->kn_sfflags & NOTE_LOWAT)          else if (kn->kn_sfflags & NOTE_LOWAT)
                 return (kn->kn_data >= kn->kn_sdata);                  rv = (kn->kn_data >= kn->kn_sdata);
         return (kn->kn_data >= so->so_snd.sb_lowat);          else
                   rv = (kn->kn_data >= so->so_snd.sb_lowat);
           if (hint != NOTE_SUBMIT)
                   sounlock(so);
           return rv;
 }  }
   
 /*ARGSUSED*/  /*ARGSUSED*/
Line 1795  static int
Line 1893  static int
 filt_solisten(struct knote *kn, long hint)  filt_solisten(struct knote *kn, long hint)
 {  {
         struct socket   *so;          struct socket   *so;
           int rv;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
   
Line 1802  filt_solisten(struct knote *kn, long hin
Line 1901  filt_solisten(struct knote *kn, long hin
          * Set kn_data to number of incoming connections, not           * Set kn_data to number of incoming connections, not
          * counting partial (incomplete) connections.           * counting partial (incomplete) connections.
          */           */
           if (hint != NOTE_SUBMIT)
                   solock(so);
         kn->kn_data = so->so_qlen;          kn->kn_data = so->so_qlen;
         return (kn->kn_data > 0);          rv = (kn->kn_data > 0);
           if (hint != NOTE_SUBMIT)
                   sounlock(so);
           return rv;
 }  }
   
 static const struct filterops solisten_filtops =  static const struct filterops solisten_filtops =
Line 1820  soo_kqfilter(struct file *fp, struct kno
Line 1924  soo_kqfilter(struct file *fp, struct kno
         struct sockbuf  *sb;          struct sockbuf  *sb;
   
         so = ((file_t *)kn->kn_obj)->f_data;          so = ((file_t *)kn->kn_obj)->f_data;
           solock(so);
         switch (kn->kn_filter) {          switch (kn->kn_filter) {
         case EVFILT_READ:          case EVFILT_READ:
                 if (so->so_options & SO_ACCEPTCONN)                  if (so->so_options & SO_ACCEPTCONN)
Line 1833  soo_kqfilter(struct file *fp, struct kno
Line 1938  soo_kqfilter(struct file *fp, struct kno
                 sb = &so->so_snd;                  sb = &so->so_snd;
                 break;                  break;
         default:          default:
                   sounlock(so);
                 return (EINVAL);                  return (EINVAL);
         }          }
         SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, kn, kn_selnext);          SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, kn, kn_selnext);
         sb->sb_flags |= SB_KNOTE;          sb->sb_flags |= SB_KNOTE;
           sounlock(so);
         return (0);          return (0);
 }  }
   
Line 1866  int
Line 1973  int
 sopoll(struct socket *so, int events)  sopoll(struct socket *so, int events)
 {  {
         int revents = 0;          int revents = 0;
         int s;  
   
   #ifndef DIAGNOSTIC
           /*
            * Do a quick, unlocked check in expectation that the socket
            * will be ready for I/O.  Don't do this check if DIAGNOSTIC,
            * as the solocked() assertions will fail.
            */
         if ((revents = sodopoll(so, events)) != 0)          if ((revents = sodopoll(so, events)) != 0)
                 return revents;                  return revents;
   #endif
   
         KERNEL_LOCK(1, curlwp);          solock(so);
         s = splsoftnet();  
   
         if ((revents = sodopoll(so, events)) == 0) {          if ((revents = sodopoll(so, events)) == 0) {
                 if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {                  if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
                         selrecord(curlwp, &so->so_rcv.sb_sel);                          selrecord(curlwp, &so->so_rcv.sb_sel);
                         so->so_rcv.sb_flags |= SB_SEL;                          so->so_rcv.sb_flags |= SB_NOTIFY;
                 }                  }
   
                 if (events & (POLLOUT | POLLWRNORM)) {                  if (events & (POLLOUT | POLLWRNORM)) {
                         selrecord(curlwp, &so->so_snd.sb_sel);                          selrecord(curlwp, &so->so_snd.sb_sel);
                         so->so_snd.sb_flags |= SB_SEL;                          so->so_snd.sb_flags |= SB_NOTIFY;
                 }                  }
         }          }
           sounlock(so);
         splx(s);  
         KERNEL_UNLOCK_ONE(curlwp);  
   
         return revents;          return revents;
 }  }

Legend:
Removed from v.1.159  
changed lines
  Added in v.1.159.2.1

CVSweb <webmaster@jp.NetBSD.org>