+ if (space <= rlen ||
+ (atomic && space < uio->uio_resid + rlen) ||
+ (uio->uio_resid >= MCLBYTES && space < MCLBYTES &&
+ so->so_snd.sb_cc >= MCLBYTES &&
+ (so->so_state & SS_NBIO) == 0)) {
+ if (so->so_state & SS_NBIO) {
+ if (first)
+ error = EWOULDBLOCK;
+ splx(s);
+ goto release;
+ }
+ sbunlock(&so->so_snd);
+ sbwait(&so->so_snd);
+ splx(s);
+ goto restart;
+ }
+ }
+ splx(s);
+ mp = ⊤
+ space -= rlen;
+ do {
+ do {
+ if (top == 0) {
+ MGETHDR(m, M_WAIT, MT_DATA);
+ mlen = MHLEN;
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+ } else {
+ MGET(m, M_WAIT, MT_DATA);
+ mlen = MLEN;
+ }
+ if (uio->uio_resid >= MINCLSIZE && space >= MCLBYTES) {
+ MCLGET(m, M_WAIT);
+ if ((m->m_flags & M_EXT) == 0)
+ goto nopages;
+ mlen = MCLBYTES;
+#ifdef MAPPED_MBUFS
+ len = min(MCLBYTES, uio->uio_resid);
+ if (len < mlen - max_hdr)
+ m->m_data += max_hdr;
+#else
+ len = min(MCLBYTES - max_hdr, uio->uio_resid);
+ m->m_data += max_hdr;
+#endif
+ space -= MCLBYTES;
+ } else {
+nopages:
+ len = min(min(mlen, uio->uio_resid), space);
+ space -= len;
+ /*
+ * For datagram protocols, leave room
+ * for protocol headers in first mbuf.
+ */
+ if (atomic && top == 0 && len < mlen)
+ MH_ALIGN(m, len);
+ }
+ error = uiomove(mtod(m, caddr_t), len, uio);
+ m->m_len = len;
+ *mp = m;
+ top->m_pkthdr.len += len;
+ if (error)
+ goto release;
+ mp = &m->m_next;
+ if (uio->uio_resid <= 0) {
+ if ((flags & MSG_EOR) && top)
+ top->m_flags |= M_EOR;
+ break;
+ }
+ } while (space > 0 && atomic);
+ if (dontroute)
+ so->so_options |= SO_DONTROUTE;
+ s = splnet(); /* XXX */
+ error = (*so->so_proto->pr_usrreq)(so,
+ (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
+ top, (caddr_t)nam, rights, control);
+ splx(s);
+ if (dontroute)
+ so->so_options &= ~SO_DONTROUTE;
+ rights = 0;
+ rlen = 0;
+ top = 0;
+ mp = ⊤
+ first = 0;
+ if (error)
+ goto release;
+ } while (uio->uio_resid && space > 0);
+ } while (uio->uio_resid);