--- //depot/vendor/freebsd/src/sys/fs/fifofs/fifo_vnops.c 2006/03/15 10:18:13 +++ //depot/user/rwatson/resock/src/sys/fs/fifofs/fifo_vnops.c 2006/06/06 08:06:38 @@ -203,9 +203,9 @@ } fip->fi_readers = fip->fi_writers = 0; wso->so_snd.sb_lowat = PIPE_BUF; - SOCKBUF_LOCK(&rso->so_rcv); + SOCK_LOCK(rso); rso->so_rcv.sb_state |= SBS_CANTRCVMORE; - SOCKBUF_UNLOCK(&rso->so_rcv); + SOCK_UNLOCK(rso); KASSERT(vp->v_fifoinfo == NULL, ("fifo_open: v_fifoinfo race")); vp->v_fifoinfo = fip; @@ -225,9 +225,12 @@ if (ap->a_mode & FREAD) { fip->fi_readers++; if (fip->fi_readers == 1) { - SOCKBUF_LOCK(&fip->fi_writesock->so_snd); + /* + * XXXRW: Coalesce locking to include sowwakeip()? + */ + SOCK_LOCK(fip->fi_writesock); fip->fi_writesock->so_snd.sb_state &= ~SBS_CANTSENDMORE; - SOCKBUF_UNLOCK(&fip->fi_writesock->so_snd); + SOCK_UNLOCK(fip->fi_writesock); if (fip->fi_writers > 0) { wakeup(&fip->fi_writers); sowwakeup(fip->fi_writesock); @@ -241,9 +244,12 @@ } fip->fi_writers++; if (fip->fi_writers == 1) { - SOCKBUF_LOCK(&fip->fi_readsock->so_rcv); + /* + * XXXRW: Coalesce locking to include sowwakeip()? + */ + SOCK_LOCK(fip->fi_readsock); fip->fi_readsock->so_rcv.sb_state &= ~SBS_CANTRCVMORE; - SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv); + SOCK_UNLOCK(fip->fi_readsock); if (fip->fi_readers > 0) { wakeup(&fip->fi_readers); sorwakeup(fip->fi_readsock); @@ -342,11 +348,11 @@ { struct socket *so = (struct socket *)kn->kn_hook; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1); if (knlist_empty(&so->so_rcv.sb_sel.si_note)) so->so_rcv.sb_flags &= ~SB_KNOTE; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); } static int @@ -354,7 +360,7 @@ { struct socket *so = (struct socket *)kn->kn_hook; - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); kn->kn_data = so->so_rcv.sb_cc; if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; @@ -370,11 +376,11 @@ { struct socket *so = (struct socket *)kn->kn_hook; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1); if (knlist_empty(&so->so_snd.sb_sel.si_note)) so->so_snd.sb_flags &= ~SB_KNOTE; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); } static int @@ -382,7 +388,7 @@ { struct socket *so = (struct socket *)kn->kn_hook; - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); kn->kn_data = sbspace(&so->so_snd); if (so->so_snd.sb_state & SBS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; @@ -646,10 +652,10 @@ kn->kn_hook = (caddr_t)so; - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); knlist_add(&sb->sb_sel.si_note, kn, 1); sb->sb_flags |= SB_KNOTE; - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); return (0); } --- //depot/vendor/freebsd/src/sys/fs/portalfs/portal_vnops.c 2005/03/28 09:35:18 +++ //depot/user/rwatson/resock/src/sys/fs/portalfs/portal_vnops.c 2005/06/06 04:37:59 @@ -298,15 +298,12 @@ /* * Set miscellaneous flags */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_timeo = 0; so->so_rcv.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_timeo = 0; so->so_snd.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_snd); - + SOCK_UNLOCK(so); pcred.pcr_flag = ap->a_mode; pcred.pcr_uid = ap->a_cred->cr_uid; --- //depot/vendor/freebsd/src/sys/kern/sys_socket.c 2005/04/16 18:50:30 +++ //depot/user/rwatson/resock/src/sys/kern/sys_socket.c 2005/06/06 04:37:59 @@ -150,32 +150,18 @@ break; case FIOASYNC: - /* - * XXXRW: This code separately acquires SOCK_LOCK(so) - * and SOCKBUF_LOCK(&so->so_rcv) even though they are - * the same mutex to avoid introducing the assumption - * that they are the same. - */ if (*(int *)data) { SOCK_LOCK(so); so->so_state |= SS_ASYNC; - SOCK_UNLOCK(so); - SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_ASYNC; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_ASYNC; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); } else { SOCK_LOCK(so); so->so_state &= ~SS_ASYNC; - SOCK_UNLOCK(so); - SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags &= ~SB_ASYNC; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags &= ~SB_ASYNC; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); } break; @@ -263,11 +249,11 @@ bzero((caddr_t)ub, sizeof (*ub)); ub->st_mode = S_IFSOCK; NET_LOCK_GIANT(); + SOCK_LOCK(so); #ifdef MAC - SOCK_LOCK(so); error = mac_check_socket_stat(active_cred, so); - SOCK_UNLOCK(so); if (error) { + SOCK_UNLOCK(so); NET_UNLOCK_GIANT(); return (error); } @@ -275,11 +261,7 @@ /* * If SBS_CANTRCVMORE is set, but there's still data left in the * receive buffer, the socket is still readable. - * - * XXXRW: perhaps should lock socket buffer so st_size result - * is consistent. */ - /* Unlocked read. */ if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0 || so->so_rcv.sb_cc != 0) ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH; @@ -288,6 +270,7 @@ ub->st_size = so->so_rcv.sb_cc - so->so_rcv.sb_ctl; ub->st_uid = so->so_cred->cr_uid; ub->st_gid = so->so_cred->cr_gid; + SOCK_UNLOCK(so); error = (*so->so_proto->pr_usrreqs->pru_sense)(so, ub); NET_UNLOCK_GIANT(); return (error); --- //depot/vendor/freebsd/src/sys/kern/uipc_socket.c 2006/04/23 18:17:36 +++ //depot/user/rwatson/resock/src/sys/kern/uipc_socket.c 2006/06/06 08:06:38 @@ -217,8 +217,7 @@ return (NULL); } #endif - SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd"); - SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv"); + SOCK_LOCK_INIT(so); TAILQ_INIT(&so->so_aiojobq); mtx_lock(&so_global_mtx); so->so_gencnt = ++so_gencnt; @@ -275,9 +274,9 @@ #ifdef MAC mac_create_socket(cred, so); #endif - knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv), + knlist_init(&so->so_rcv.sb_sel.si_note, SOCK_MTX(so), NULL, NULL, NULL); - knlist_init(&so->so_snd.sb_sel.si_note, SOCKBUF_MTX(&so->so_snd), + knlist_init(&so->so_snd.sb_sel.si_note, SOCK_MTX(so), NULL, NULL, NULL); so->so_count = 1; error = (*prp->pr_usrreqs->pru_attach)(so, proto, td); @@ -327,8 +326,7 @@ mac_destroy_socket(so); #endif crfree(so->so_cred); - SOCKBUF_LOCK_DESTROY(&so->so_snd); - SOCKBUF_LOCK_DESTROY(&so->so_rcv); + SOCK_LOCK_DESTROY(so); uma_zfree(socket_zone, so); mtx_lock(&so_global_mtx); --numopensockets; @@ -438,23 +436,14 @@ (so->so_qstate & SQ_INCOMP) == 0, ("sofree: so_head == NULL, but still SQ_COMP(%d) or SQ_INCOMP(%d)", so->so_qstate & SQ_COMP, so->so_qstate & SQ_INCOMP)); - SOCK_UNLOCK(so); ACCEPT_UNLOCK(); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_NOINTR; (void)sblock(&so->so_snd, M_WAITOK); - /* - * socantsendmore_locked() drops the socket buffer mutex so that it - * can safely perform wakeups. Re-acquire the mutex before - * continuing. - */ socantsendmore_locked(so); - SOCKBUF_LOCK(&so->so_snd); sbunlock(&so->so_snd); sbrelease_locked(&so->so_snd, so); - SOCKBUF_UNLOCK(&so->so_snd); - sorflush(so); + sorflush_locked(so); knlist_destroy(&so->so_rcv.sb_sel.si_note); knlist_destroy(&so->so_snd.sb_sel.si_note); sodealloc(so); @@ -501,6 +490,7 @@ } ACCEPT_UNLOCK(); } + /* XXXRW: Can we now hold SOCK_LOCK() over all of the below? */ if (so->so_state & SS_ISCONNECTED) { if ((so->so_state & SS_ISDISCONNECTING) == 0) { error = sodisconnect(so); @@ -577,6 +567,10 @@ { int error; + /* + * XXXRW: Should this state transition be generated by pru_accept() + * and a call to soaccept_proto()? + */ SOCK_LOCK(so); KASSERT((so->so_state & SS_NOFDREF) != 0, ("soaccept: !NOFDREF")); so->so_state &= ~SS_NOFDREF; @@ -593,8 +587,14 @@ { int error; + /* + * XXXRW: Should this state transition be driven by the protocol layer + * using a soconnect_proto() so that SOCK_LOCK() can be held over all + * of this? + */ if (so->so_options & SO_ACCEPTCONN) return (EOPNOTSUPP); + /* * If protocol is connection-based, can only connect once. * Otherwise, if connected, try to disconnect first. @@ -632,6 +632,10 @@ { int error; + /* + * XXXRW: Should these checks be done using a sodisconnect_proto() so + * that SOCK_LOCK() can be held over them? + */ if ((so->so_state & SS_ISCONNECTED) == 0) return (ENOTCONN); if (so->so_state & SS_ISDISCONNECTING) @@ -826,16 +830,16 @@ if (control != NULL) clen = control->m_len; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); if (so->so_snd.sb_state & SBS_CANTSENDMORE) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = EPIPE; goto out; } if (so->so_error) { error = so->so_error; so->so_error = 0; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto out; } if ((so->so_state & SS_ISCONNECTED) == 0) { @@ -849,7 +853,7 @@ (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) { if ((so->so_state & SS_ISCONFIRMING) == 0 && !(resid == 0 && clen != 0)) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = ENOTCONN; goto out; } @@ -858,7 +862,7 @@ error = ENOTCONN; else error = EDESTADDRREQ; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto out; } } @@ -875,7 +879,7 @@ error = EMSGSIZE; goto out; } - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); if (uio == NULL) { resid = 0; if (flags & MSG_EOR) @@ -994,14 +998,14 @@ if (control != NULL) clen = control->m_len; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); restart: - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); error = sblock(&so->so_snd, SBLOCKWAIT(flags)); if (error) goto out_locked; do { - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); if (so->so_snd.sb_state & SBS_CANTSENDMORE) snderr(EPIPE); if (so->so_error) { @@ -1041,7 +1045,7 @@ goto out_locked; goto restart; } - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); space -= clen; do { if (uio == NULL) { @@ -1052,7 +1056,7 @@ error = sosend_copyin(uio, &top, atomic, &space, flags); if (error != 0) { - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); goto release; } resid = uio->uio_resid; @@ -1094,19 +1098,19 @@ control = NULL; top = NULL; if (error) { - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); goto release; } } while (resid && space > 0); - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); } while (resid); release: - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); sbunlock(&so->so_snd); out_locked: - SOCKBUF_LOCK_ASSERT(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_LOCK_ASSERT(so); + SOCK_UNLOCK(so); out: if (top != NULL) m_freem(top); @@ -1181,6 +1185,7 @@ { SOCKBUF_LOCK_ASSERT(sb); + /* * First, update for the new value of nextrecord. If necessary, make * it the first record. @@ -1253,9 +1258,9 @@ && uio->uio_resid) (*pr->pr_usrreqs->pru_rcvd)(so, 0); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); restart: - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); error = sblock(&so->so_rcv, SBLOCKWAIT(flags)); if (error) goto out; @@ -1288,7 +1293,7 @@ so->so_error = 0; goto release; } - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { if (m) goto dontblock; @@ -1336,7 +1341,7 @@ * By holding the high-level sblock(), we prevent simultaneous * readers from pulling off the front of the socket buffer. */ - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (uio->uio_td) uio->uio_td->td_proc->p_stats->p_ru.ru_msgrcv++; KASSERT(m == so->so_rcv.sb_mb, ("soreceive: m != so->so_rcv.sb_mb")); @@ -1392,10 +1397,10 @@ cmn = cm->m_next; cm->m_next = NULL; if (pr->pr_domain->dom_externalize != NULL) { - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); error = (*pr->pr_domain->dom_externalize) (cm, controlp); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); } else if (controlp != NULL) *controlp = cm; else @@ -1437,7 +1442,7 @@ } } } - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); SBLASTRECORDCHK(&so->so_rcv); SBLASTMBUFCHK(&so->so_rcv); @@ -1456,7 +1461,7 @@ * If the type of mbuf has changed since the last mbuf * examined ('type'), end the receive operation. */ - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (m->m_type == MT_OOBDATA) { if (type != MT_OOBDATA) break; @@ -1480,10 +1485,10 @@ * block interrupts again. */ if (mp == NULL) { - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); SBLASTRECORDCHK(&so->so_rcv); SBLASTMBUFCHK(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); #ifdef ZERO_COPY_SOCKETS if (so_zero_copy_receive) { int disposable; @@ -1500,12 +1505,12 @@ } else #endif /* ZERO_COPY_SOCKETS */ error = uiomove(mtod(m, char *) + moff, (int)len, uio); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (error) goto release; } else uio->uio_resid -= len; - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (len == m->m_len - moff) { if (m->m_flags & M_EOR) flags |= MSG_EOR; @@ -1540,10 +1545,10 @@ else copy_flag = M_TRYWAIT; if (copy_flag == M_TRYWAIT) - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); *mp = m_copym(m, 0, len, copy_flag); if (copy_flag == M_TRYWAIT) - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (*mp == NULL) { /* * m_copym() couldn't allocate an mbuf. @@ -1560,7 +1565,7 @@ so->so_rcv.sb_cc -= len; } } - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (so->so_oobmark) { if ((flags & MSG_PEEK) == 0) { so->so_oobmark -= len; @@ -1585,7 +1590,7 @@ */ while (flags & MSG_WAITALL && m == NULL && uio->uio_resid > 0 && !sosendallatonce(so) && nextrecord == NULL) { - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE) break; /* @@ -1593,9 +1598,9 @@ * drained before blocking. */ if (pr->pr_flags & PR_WANTRCVD) { - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); (*pr->pr_usrreqs->pru_rcvd)(so, flags); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); } SBLASTRECORDCHK(&so->so_rcv); SBLASTMBUFCHK(&so->so_rcv); @@ -1608,7 +1613,7 @@ } } - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (m != NULL && pr->pr_flags & PR_ATOMIC) { flags |= MSG_TRUNC; if ((flags & MSG_PEEK) == 0) @@ -1637,12 +1642,12 @@ */ if (!(flags & MSG_SOCALLBCK) && (pr->pr_flags & PR_WANTRCVD)) { - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); (*pr->pr_usrreqs->pru_rcvd)(so, flags); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); } } - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0) { sbunlock(&so->so_rcv); @@ -1652,11 +1657,11 @@ if (flagsp != NULL) *flagsp |= flags; release: - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); sbunlock(&so->so_rcv); out: - SOCKBUF_LOCK_ASSERT(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_LOCK_ASSERT(so); + SOCK_UNLOCK(so); return (error); } @@ -1678,31 +1683,26 @@ } void -sorflush(so) +sorflush_locked(so) struct socket *so; { struct sockbuf *sb = &so->so_rcv; struct protosw *pr = so->so_proto; struct sockbuf asb; + SOCK_LOCK_ASSERT(so); + /* - * XXXRW: This is quite ugly. Previously, this code made a copy of - * the socket buffer, then zero'd the original to clear the buffer - * fields. However, with mutexes in the socket buffer, this causes - * problems. We only clear the zeroable bits of the original; - * however, we have to initialize and destroy the mutex in the copy - * so that dom_dispose() and sbrelease() can lock t as needed. + * XXXRW: This is quite ugly -- we create a stack-local socket buffer + * so that we can release the lock on the socket's copy of the buffer, + * as dom_dispose() may block (among other things). It's a bit + * cleaner with a single socket mutex than with socket buffer mutexes, + * as we don't have to mock up a socket buffer mutex for the benefit + * of sbrelease(). */ - SOCKBUF_LOCK(sb); sb->sb_flags |= SB_NOINTR; (void) sblock(sb, M_WAITOK); - /* - * socantrcvmore_locked() drops the socket buffer mutex so that it - * can safely perform wakeups. Re-acquire the mutex before - * continuing. - */ socantrcvmore_locked(so); - SOCKBUF_LOCK(sb); sbunlock(sb); /* * Invalidate/clear most of the sockbuf structure, but leave @@ -1713,13 +1713,22 @@ sizeof(*sb) - offsetof(struct sockbuf, sb_startzero)); bzero(&sb->sb_startzero, sizeof(*sb) - offsetof(struct sockbuf, sb_startzero)); - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); - SOCKBUF_LOCK_INIT(&asb, "so_rcv"); + asb.sb_somtxp = NULL; if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL) (*pr->pr_domain->dom_dispose)(asb.sb_mb); sbrelease(&asb, so); - SOCKBUF_LOCK_DESTROY(&asb); +} + +void +sorflush(so) + struct socket *so; +{ + + SOCK_LOCK(so); + sorflush_locked(so); + SOCK_UNLOCK_ASSERT(so); } /* @@ -1874,18 +1883,18 @@ * the high-water. */ case SO_SNDLOWAT: - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); so->so_snd.sb_lowat = (optval > so->so_snd.sb_hiwat) ? so->so_snd.sb_hiwat : optval; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); break; case SO_RCVLOWAT: - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_lowat = (optval > so->so_rcv.sb_hiwat) ? so->so_rcv.sb_hiwat : optval; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); break; } break; @@ -2041,32 +2050,40 @@ break; case SO_TYPE: + /* Lockless read. */ optval = so->so_type; goto integer; case SO_ERROR: + SOCK_LOCK(so); optval = so->so_error; so->so_error = 0; + SOCK_UNLOCK(so); goto integer; case SO_SNDBUF: + /* Lockless read. */ optval = so->so_snd.sb_hiwat; goto integer; case SO_RCVBUF: + /* Lockless read. */ optval = so->so_rcv.sb_hiwat; goto integer; case SO_SNDLOWAT: + /* Lockless read. */ optval = so->so_snd.sb_lowat; goto integer; case SO_RCVLOWAT: + /* Lockless read. */ optval = so->so_rcv.sb_lowat; goto integer; case SO_SNDTIMEO: case SO_RCVTIMEO: + /* Lockless read. */ optval = (sopt->sopt_name == SO_SNDTIMEO ? so->so_snd.sb_timeo : so->so_rcv.sb_timeo); @@ -2264,8 +2281,7 @@ { int revents = 0; - SOCKBUF_LOCK(&so->so_snd); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (events & (POLLIN | POLLRDNORM)) if (soreadable(so)) revents |= events & (POLLIN | POLLRDNORM); @@ -2296,9 +2312,8 @@ so->so_snd.sb_flags |= SB_SEL; } } + SOCK_UNLOCK(so); - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_snd); return (revents); } @@ -2324,10 +2339,10 @@ return (EINVAL); } - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); knlist_add(&sb->sb_sel.si_note, kn, 1); sb->sb_flags |= SB_KNOTE; - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); return (0); } @@ -2336,11 +2351,11 @@ { struct socket *so = kn->kn_fp->f_data; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1); if (knlist_empty(&so->so_rcv.sb_sel.si_note)) so->so_rcv.sb_flags &= ~SB_KNOTE; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); } /*ARGSUSED*/ @@ -2350,7 +2365,7 @@ struct socket *so; so = kn->kn_fp->f_data; - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); kn->kn_data = so->so_rcv.sb_cc - so->so_rcv.sb_ctl; if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { @@ -2370,11 +2385,11 @@ { struct socket *so = kn->kn_fp->f_data; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1); if (knlist_empty(&so->so_snd.sb_sel.si_note)) so->so_snd.sb_flags &= ~SB_KNOTE; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); } /*ARGSUSED*/ @@ -2384,7 +2399,8 @@ struct socket *so; so = kn->kn_fp->f_data; - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); + kn->kn_data = sbspace(&so->so_snd); if (so->so_snd.sb_state & SBS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; --- //depot/vendor/freebsd/src/sys/kern/uipc_socket2.c 2006/04/21 10:18:17 +++ //depot/user/rwatson/resock/src/sys/kern/uipc_socket2.c 2006/06/06 08:06:38 @@ -166,18 +166,17 @@ { /* - * XXXRW: This code assumes that SOCK_LOCK(so) and - * SOCKBUF_LOCK(&so->so_rcv) are the same. + * XXXRW: Set all flags before any upcalls? */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_state &= ~SS_ISCONNECTING; so->so_state |= SS_ISDISCONNECTING; so->so_rcv.sb_state |= SBS_CANTRCVMORE; sorwakeup_locked(so); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_state |= SBS_CANTSENDMORE; sowwakeup_locked(so); wakeup(&so->so_timeo); + SOCK_UNLOCK(so); } void @@ -186,19 +185,18 @@ { /* - * XXXRW: This code assumes that SOCK_LOCK(so) and - * SOCKBUF_LOCK(&so->so_rcv) are the same. + * XXXRW: Set all flags before any upcalls? */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); so->so_state |= SS_ISDISCONNECTED; so->so_rcv.sb_state |= SBS_CANTRCVMORE; sorwakeup_locked(so); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_state |= SBS_CANTSENDMORE; sbdrop_locked(&so->so_snd, so->so_snd.sb_cc); sowwakeup_locked(so); wakeup(&so->so_timeo); + SOCK_UNLOCK(so); } /* @@ -246,10 +244,10 @@ mac_create_socket_from_socket(head, so); SOCK_UNLOCK(head); #endif - knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv), - NULL, NULL, NULL); - knlist_init(&so->so_snd.sb_sel.si_note, SOCKBUF_MTX(&so->so_snd), - NULL, NULL, NULL); + knlist_init(&so->so_rcv.sb_sel.si_note, SOCK_MTX(so), NULL, NULL, + NULL); + knlist_init(&so->so_snd.sb_sel.si_note, SOCK_MTX(so), NULL, NULL, + NULL); if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) || (*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) { sodealloc(so); @@ -306,11 +304,11 @@ struct socket *so; { - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); so->so_snd.sb_state |= SBS_CANTSENDMORE; sowwakeup_locked(so); - mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); + /* XXXRW: Note, used turn return the buffer unlocked. */ } void @@ -318,9 +316,9 @@ struct socket *so; { - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); socantsendmore_locked(so); - mtx_assert(SOCKBUF_MTX(&so->so_snd), MA_NOTOWNED); + SOCK_UNLOCK(so); } void @@ -328,11 +326,11 @@ struct socket *so; { - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + SOCK_LOCK_ASSERT(so); so->so_rcv.sb_state |= SBS_CANTRCVMORE; sorwakeup_locked(so); - mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); + /* XXXRW: Note, used turn return the buffer unlocked. */ } void @@ -340,9 +338,9 @@ struct socket *so; { - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); socantrcvmore_locked(so); - mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED); + SOCK_UNLOCK(so); } /* @@ -356,7 +354,7 @@ SOCKBUF_LOCK_ASSERT(sb); sb->sb_flags |= SB_WAIT; - return (msleep(&sb->sb_cc, &sb->sb_mtx, + return (msleep(&sb->sb_cc, SOCKBUF_MTX(sb), (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait", sb->sb_timeo)); } @@ -375,7 +373,7 @@ while (sb->sb_flags & SB_LOCK) { sb->sb_flags |= SB_WANT; - error = msleep(&sb->sb_flags, &sb->sb_mtx, + error = msleep(&sb->sb_flags, SOCKBUF_MTX(sb), (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH, "sblock", 0); if (error) @@ -389,13 +387,8 @@ * Wakeup processes waiting on a socket buffer. Do asynchronous * notification via SIGIO if the socket has the SS_ASYNC flag set. * - * Called with the socket buffer lock held; will release the lock by the end - * of the function. This allows the caller to acquire the socket buffer lock - * while testing for the need for various sorts of wakeup and hold it through - * to the point where it's no longer required. We currently hold the lock - * through calls out to other subsystems (with the exception of kqueue), and - * then release it to avoid lock order issues. It's not clear that's - * correct. + * XXXRW: Note: sowakeup() used to return unlocked, now returns locked. This + * is almost certainly an improvement. */ void sowakeup(so, sb) @@ -403,7 +396,7 @@ register struct sockbuf *sb; { - SOCKBUF_LOCK_ASSERT(sb); + SOCK_LOCK_ASSERT(so); selwakeuppri(&sb->sb_sel, PSOCK); sb->sb_flags &= ~SB_SEL; @@ -412,14 +405,12 @@ wakeup(&sb->sb_cc); } KNOTE_LOCKED(&sb->sb_sel.si_note, 0); - SOCKBUF_UNLOCK(sb); if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) pgsigio(&so->so_sigio, SIGIO, 0); if (sb->sb_flags & SB_UPCALL) (*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT); if (sb->sb_flags & SB_AIO) aio_swake(so, sb); - mtx_assert(SOCKBUF_MTX(sb), MA_NOTOWNED); } /* @@ -452,8 +443,10 @@ * some of the available buffer space in the system buffer pool for the * socket (currently, it does nothing but enforce limits). The space * should be released by calling sbrelease() when the socket is destroyed. + * + * XXXRW: Would it make sense to assert the lock and let the caller acquire + * it? */ - int soreserve(so, sndcc, rcvcc) register struct socket *so; @@ -461,8 +454,7 @@ { struct thread *td = curthread; - SOCKBUF_LOCK(&so->so_snd); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (sbreserve_locked(&so->so_snd, sndcc, so, td) == 0) goto bad; if (sbreserve_locked(&so->so_rcv, rcvcc, so, td) == 0) @@ -473,14 +465,12 @@ so->so_snd.sb_lowat = MCLBYTES; if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); return (0); bad2: sbrelease_locked(&so->so_snd, so); bad: - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); return (ENOBUFS); } @@ -518,7 +508,7 @@ { rlim_t sbsize_limit; - SOCKBUF_LOCK_ASSERT(sb); + SOCK_LOCK_ASSERT(so); /* * td will only be NULL when we're in an interrupt @@ -550,9 +540,9 @@ { int error; - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); error = sbreserve_locked(sb, cc, so, td); - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); return (error); } @@ -565,7 +555,7 @@ struct socket *so; { - SOCKBUF_LOCK_ASSERT(sb); + SOCK_LOCK_ASSERT(so); sbflush_locked(sb); (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, @@ -579,9 +569,9 @@ struct socket *so; { - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); sbrelease_locked(sb, so); - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); } /* * Routines to add and remove @@ -1459,6 +1449,9 @@ void sotoxsocket(struct socket *so, struct xsocket *xso) { + + SOCK_LOCK_ASSERT(so); + xso->xso_len = sizeof *xso; xso->xso_so = so; xso->so_type = so->so_type; @@ -1489,6 +1482,9 @@ void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb) { + + SOCKBUF_LOCK_ASSERT(sb); + xsb->sb_cc = sb->sb_cc; xsb->sb_hiwat = sb->sb_hiwat; xsb->sb_mbcnt = sb->sb_mbcnt; --- //depot/vendor/freebsd/src/sys/kern/uipc_syscalls.c 2006/05/25 15:12:37 +++ //depot/user/rwatson/resock/src/sys/kern/uipc_syscalls.c 2006/06/06 08:06:38 @@ -286,6 +286,10 @@ /* * accept1() * MPSAFE + * + * XXXRW: Would it make sense to hold both the accept and socket mutex for the + * 'head' socket here, in order to avoid repeated lockless reads of fields + * like so_error? */ static int accept1(td, uap, compat) @@ -336,12 +340,15 @@ if (error) goto done; ACCEPT_LOCK(); + /* Lockless read. */ if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) { ACCEPT_UNLOCK(); error = EWOULDBLOCK; goto noconnection; } + /* Lockless read. */ while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) { + /* Lockless read. */ if (head->so_rcv.sb_state & SBS_CANTRCVMORE) { head->so_error = ECONNABORTED; break; @@ -353,6 +360,7 @@ goto noconnection; } } + /* Lockless read. */ if (head->so_error) { error = head->so_error; head->so_error = 0; @@ -533,18 +541,19 @@ #ifdef MAC SOCK_LOCK(so); error = mac_check_socket_connect(td->td_ucred, so, sa); - SOCK_UNLOCK(so); if (error) goto bad; + SOCK_UNLOCK(so); #endif error = soconnect(so, sa, td); + SOCK_LOCK(so); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { + SOCK_UNLOCK(so); error = EINPROGRESS; goto done1; } - SOCK_LOCK(so); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH, "connec", 0); @@ -558,10 +567,10 @@ error = so->so_error; so->so_error = 0; } - SOCK_UNLOCK(so); bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; + SOCK_UNLOCK(so); if (error == ERESTART) error = EINTR; done1: @@ -1559,6 +1568,7 @@ if (error) goto done2; so = fp->f_data; + /* XXXRW: Lockless read -- check at wrong layer? */ if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { error = ENOTCONN; goto done1; @@ -1890,9 +1900,9 @@ /* * Protect against multiple writers to the socket. */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); (void) sblock(&so->so_snd, M_WAITOK); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); /* * Loop through the pages in the file, starting with the requested @@ -1924,7 +1934,7 @@ if (m_header != NULL) { m = m_header; m_header = NULL; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); goto retry_space; } else break; @@ -1933,17 +1943,17 @@ * Optimize the non-blocking case by looking at the socket space * before going to the extra work of constituting the sf_buf. */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) { if (so->so_snd.sb_state & SBS_CANTSENDMORE) error = EPIPE; else error = EAGAIN; sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); VM_OBJECT_LOCK(obj); /* * Attempt to look up the page. @@ -2032,9 +2042,9 @@ } vm_page_unlock_queues(); VM_OBJECT_UNLOCK(obj); - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } vm_page_unlock_queues(); @@ -2050,9 +2060,9 @@ if (pg->wire_count == 0 && pg->object == NULL) vm_page_free(pg); vm_page_unlock_queues(); - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = EINTR; goto done; } @@ -2067,9 +2077,9 @@ if (m == NULL) { error = ENOBUFS; sf_buf_mext((void *)sf_buf_kva(sf), sf); - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } /* @@ -2089,8 +2099,11 @@ /* * Add the buffer to the socket buffer chain. + * + * XXXRW: Seems like a shame to lock the socket at this layer + * just to unlock it and relock it the next layer down. */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); retry_space: /* * Make sure that the socket is still able to take more data. @@ -2103,7 +2116,7 @@ * blocks before the pru_send (or more accurately, any blocking * results in a loop back to here to re-check). */ - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); if ((so->so_snd.sb_state & SBS_CANTSENDMORE) || so->so_error) { if (so->so_snd.sb_state & SBS_CANTSENDMORE) { error = EPIPE; @@ -2113,7 +2126,7 @@ } m_freem(m); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } /* @@ -2125,7 +2138,7 @@ if (so->so_state & SS_NBIO) { m_freem(m); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = EAGAIN; goto done; } @@ -2138,24 +2151,24 @@ if (error) { m_freem(m); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } goto retry_space; } - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td); if (error) { - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); goto done; } headersent = 1; } - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); sbunlock(&so->so_snd); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); /* * Send trailers. Wimp out and use writev(2). --- //depot/vendor/freebsd/src/sys/kern/uipc_usrreq.c 2006/04/24 19:10:17 +++ //depot/user/rwatson/resock/src/sys/kern/uipc_usrreq.c 2006/06/06 08:06:38 @@ -316,11 +316,22 @@ if (unp->unp_conn == NULL) break; so2 = unp->unp_conn->unp_socket; - SOCKBUF_LOCK(&so2->so_snd); - SOCKBUF_LOCK(&so->so_rcv); + /* + * XXXRW: No lock order is defined between socket locks in the + * general case. + * + * We rely on the UNIX domain socket global lock to serialize + * acquisition of socket locks across multiple UNIX domain + * sockets. + */ + SOCK_LOCK(so2); + SOCK_LOCK(so); /* - * Adjust backpressure on sender - * and wakeup any waiting to write. + * Adjust backpressure on sender and wakeup any waiting to + * write. + * + * XXXRW: Copy the two 'so' fields to local variables rather + * than hold both locks? */ so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt; unp->unp_mbcnt = so->so_rcv.sb_mbcnt; @@ -329,8 +340,9 @@ (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); unp->unp_cc = so->so_rcv.sb_cc; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); sowwakeup_locked(so2); + SOCK_UNLOCK(so2); break; default: @@ -388,15 +400,14 @@ from = &sun_noname; if (unp->unp_conn->unp_flags & UNP_WANTCRED) control = unp_addsockcred(td, control); - SOCKBUF_LOCK(&so2->so_rcv); + SOCK_LOCK(so2); if (sbappendaddr_locked(&so2->so_rcv, from, m, control)) { sorwakeup_locked(so2); m = NULL; control = NULL; - } else { - SOCKBUF_UNLOCK(&so2->so_rcv); + } else error = ENOBUFS; - } + SOCK_UNLOCK(so2); if (nam != NULL) unp_disconnect(unp); break; @@ -407,6 +418,8 @@ /* * Note: A better implementation would complain * if not equal to the peer's address. + * + * XXXRW: Lockless read. */ if ((so->so_state & SS_ISCONNECTED) == 0) { if (nam != NULL) { @@ -419,16 +432,24 @@ } } - SOCKBUF_LOCK(&so->so_snd); + /* + * XXXRW: No lock order is defined between socket locks in the + * general case. + * + * We rely on the UNIX domain socket global lock to serialize + * acquisition of socket locks across multiple UNIX domain + * sockets. + */ + SOCK_LOCK(so); if (so->so_snd.sb_state & SBS_CANTSENDMORE) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = EPIPE; break; } if (unp->unp_conn == NULL) panic("uipc_send connected but no connection?"); so2 = unp->unp_conn->unp_socket; - SOCKBUF_LOCK(&so2->so_rcv); + mtx_lock_flags(SOCK_MTX(so2), MTX_DUPOK); if (unp->unp_conn->unp_flags & UNP_WANTCRED) { /* * Credentials are passed only once on @@ -455,9 +476,10 @@ (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; sorwakeup_locked(so2); + SOCK_UNLOCK(so2); m = NULL; break; @@ -1635,9 +1657,9 @@ * message buffers. Follow those links and mark them * as accessible too. */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); unp_scan(so->so_rcv.sb_mb, unp_mark); - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); } } while (unp_defer); sx_sunlock(&filelist_lock); --- //depot/vendor/freebsd/src/sys/kern/vfs_aio.c 2006/06/02 17:46:22 +++ //depot/user/rwatson/resock/src/sys/kern/vfs_aio.c 2006/06/06 08:06:38 @@ -1296,7 +1296,7 @@ else opcode = LIO_READ; - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); sb->sb_flags &= ~SB_AIO; mtx_lock(&aio_job_mtx); TAILQ_FOREACH_SAFE(cb, &so->so_aiojobq, list, cbn) { @@ -1314,7 +1314,7 @@ } } mtx_unlock(&aio_job_mtx); - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); } /* @@ -1506,7 +1506,7 @@ */ so = fp->f_data; sb = (opcode == LIO_READ) ? &so->so_rcv : &so->so_snd; - SOCKBUF_LOCK(sb); + SOCK_LOCK(so); if (((opcode == LIO_READ) && (!soreadable(so))) || ((opcode == LIO_WRITE) && (!sowriteable(so)))) { sb->sb_flags |= SB_AIO; @@ -1523,12 +1523,12 @@ if (lj) lj->lioj_count++; AIO_UNLOCK(ki); - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); atomic_add_int(&num_queue_count, 1); error = 0; goto done; } - SOCKBUF_UNLOCK(sb); + SOCK_UNLOCK(so); } if ((error = aio_qphysio(p, aiocbe)) == 0) --- //depot/vendor/freebsd/src/sys/netatalk/ddp_input.c 2005/01/07 02:37:15 +++ //depot/user/rwatson/resock/src/sys/netatalk/ddp_input.c 2005/06/06 04:37:59 @@ -421,10 +421,10 @@ /* * If we found one, deliver the packet to the socket */ - SOCKBUF_LOCK(&ddp->ddp_socket->so_rcv); + SOCK_LOCK(ddp->ddp_socket); if (sbappendaddr_locked(&ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, m, NULL) == 0) { - SOCKBUF_UNLOCK(&ddp->ddp_socket->so_rcv); + SOCK_UNLOCK(ddp->ddp_socket); /* * If the socket is full (or similar error) dump the packet. */ @@ -435,6 +435,7 @@ * And wake up whatever might be waiting for it */ sorwakeup_locked(ddp->ddp_socket); + SOCK_UNLOCK(ddp->ddp_socket); m = NULL; out: DDP_LIST_SUNLOCK(); --- //depot/vendor/freebsd/src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c 2006/04/01 15:45:41 +++ //depot/user/rwatson/resock/src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c 2006/06/06 08:06:38 @@ -1000,12 +1000,10 @@ /* Close L2CAP socket */ s->l2so->so_upcallarg = NULL; s->l2so->so_upcall = NULL; - SOCKBUF_LOCK(&s->l2so->so_rcv); + SOCK_LOCK(s->l2so); s->l2so->so_rcv.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&s->l2so->so_rcv); - SOCKBUF_LOCK(&s->l2so->so_snd); s->l2so->so_snd.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&s->l2so->so_snd); + SOCK_UNLOCK(s->l2so); soclose(s->l2so); mtx_unlock(&s->session_mtx); @@ -1244,13 +1242,11 @@ /* Prepare L2CAP socket */ l2so->so_upcallarg = NULL; l2so->so_upcall = ng_btsocket_rfcomm_upcall; - SOCKBUF_LOCK(&l2so->so_rcv); + SOCK_LOCK(l2so); l2so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&l2so->so_rcv); - SOCKBUF_LOCK(&l2so->so_snd); l2so->so_snd.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&l2so->so_snd); l2so->so_state |= SS_NBIO; + SOCK_UNLOCK(l2so); s->l2so = l2so; mtx_lock(&s->session_mtx); @@ -1326,15 +1322,13 @@ mtx_unlock(&s->session_mtx); /* Return L2CAP socket back to its original state */ + SOCK_LOCK(l2so); l2so->so_upcallarg = NULL; l2so->so_upcall = NULL; - SOCKBUF_LOCK(&l2so->so_rcv); l2so->so_rcv.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&l2so->so_rcv); - SOCKBUF_LOCK(&l2so->so_snd); l2so->so_snd.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&l2so->so_snd); l2so->so_state &= ~SS_NBIO; + SOCK_UNLOCK(l2so); mtx_destroy(&s->session_mtx); bzero(s, sizeof(*s)); --- //depot/vendor/freebsd/src/sys/netgraph/ng_ksocket.c 2006/02/21 13:08:33 +++ //depot/user/rwatson/resock/src/sys/netgraph/ng_ksocket.c 2006/06/06 08:06:38 @@ -615,15 +615,11 @@ struct socket *const so = priv->so; /* Add our hook for incoming data and other events */ + SOCK_LOCK(priv->so); priv->so->so_upcallarg = (caddr_t)node; priv->so->so_upcall = ng_ksocket_incoming; - SOCKBUF_LOCK(&priv->so->so_rcv); priv->so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&priv->so->so_rcv); - SOCKBUF_LOCK(&priv->so->so_snd); priv->so->so_snd.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&priv->so->so_snd); - SOCK_LOCK(priv->so); priv->so->so_state |= SS_NBIO; SOCK_UNLOCK(priv->so); /* @@ -936,13 +932,11 @@ /* Close our socket (if any) */ if (priv->so != NULL) { + SOCK_LOCK(priv->so); priv->so->so_upcall = NULL; - SOCKBUF_LOCK(&priv->so->so_rcv); priv->so->so_rcv.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&priv->so->so_rcv); - SOCKBUF_LOCK(&priv->so->so_snd); priv->so->so_snd.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&priv->so->so_snd); + SOCK_UNLOCK(priv->so); soclose(priv->so); priv->so = NULL; } @@ -1262,14 +1256,12 @@ */ LIST_INSERT_HEAD(&priv->embryos, priv2, siblings); + SOCK_LOCK(so); so->so_upcallarg = (caddr_t)node; so->so_upcall = ng_ksocket_incoming; - SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); /* Fill in the response data and send it or return it to the caller */ resp_data = (struct ng_ksocket_accept *)resp->data; --- //depot/vendor/freebsd/src/sys/netinet/ip_divert.c 2006/04/21 10:18:17 +++ //depot/user/rwatson/resock/src/sys/netinet/ip_divert.c 2006/06/06 08:06:38 @@ -250,14 +250,14 @@ /* XXX why does only one socket match? */ if (inp->inp_lport == nport) { sa = inp->inp_socket; - SOCKBUF_LOCK(&sa->so_rcv); + SOCK_LOCK(sa); if (sbappendaddr_locked(&sa->so_rcv, (struct sockaddr *)&divsrc, m, - (struct mbuf *)0) == 0) { - SOCKBUF_UNLOCK(&sa->so_rcv); + (struct mbuf *)0) == 0) sa = NULL; /* force mbuf reclaim below */ - } else + else sorwakeup_locked(sa); + SOCK_UNLOCK(sa); INP_UNLOCK(inp); break; } --- //depot/vendor/freebsd/src/sys/netinet/ip_mroute.c 2006/05/18 19:55:58 +++ //depot/user/rwatson/resock/src/sys/netinet/ip_mroute.c 2006/06/06 08:06:38 @@ -1353,13 +1353,14 @@ socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in *src) { if (s) { - SOCKBUF_LOCK(&s->so_rcv); + SOCK_LOCK(s); if (sbappendaddr_locked(&s->so_rcv, (struct sockaddr *)src, mm, NULL) != 0) { sorwakeup_locked(s); + SOCK_UNLOCK(s); return 0; } - SOCKBUF_UNLOCK(&s->so_rcv); + SOCK_UNLOCK(s); } m_freem(mm); return -1; --- //depot/vendor/freebsd/src/sys/netinet/raw_ip.c 2006/05/21 19:30:34 +++ //depot/user/rwatson/resock/src/sys/netinet/raw_ip.c 2006/06/06 08:06:38 @@ -177,16 +177,16 @@ if ((last->inp_flags & INP_CONTROLOPTS) || (so->so_options & (SO_TIMESTAMP | SO_BINTIME))) ip_savecontrol(last, &opts, ip, n); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&ripsrc, n, opts) == 0) { /* should notify about lost packet */ m_freem(n); if (opts) m_freem(opts); - SOCKBUF_UNLOCK(&so->so_rcv); } else sorwakeup_locked(so); + SOCK_UNLOCK(so); } else m_freem(n); return policyfail; --- //depot/vendor/freebsd/src/sys/netinet/tcp_input.c 2006/04/21 10:18:17 +++ //depot/user/rwatson/resock/src/sys/netinet/tcp_input.c 2006/06/06 08:06:38 @@ -371,7 +371,7 @@ q = LIST_FIRST(&tp->t_segq); if (!q || q->tqe_th->th_seq != tp->rcv_nxt) return (0); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); do { tp->rcv_nxt += q->tqe_len; flags = q->tqe_th->th_flags & TH_FIN; @@ -388,6 +388,7 @@ } while (q && q->tqe_th->th_seq == tp->rcv_nxt); ND6_HINT(tp); sorwakeup_locked(so); + SOCK_UNLOCK(so); return (flags); } @@ -1299,7 +1300,7 @@ #endif * Add data to socket buffer. */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { m_freem(m); } else { @@ -1307,6 +1308,7 @@ sbappendstream_locked(&so->so_rcv, m); } sorwakeup_locked(so); + SOCK_UNLOCK(so); if (DELAY_ACK(tp)) { tp->t_flags |= TF_DELACK; } else { @@ -2139,7 +2141,7 @@ incr = incr * incr / cw; tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<snd_scale); } - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); if (acked > so->so_snd.sb_cc) { tp->snd_wnd -= so->so_snd.sb_cc; sbdrop_locked(&so->so_snd, (int)so->so_snd.sb_cc); @@ -2150,6 +2152,7 @@ ourfinisacked = 0; } sowwakeup_locked(so); + SOCK_UNLOCK(so); /* detect una wraparound */ if ((tcp_do_newreno || tp->sack_enable) && !IN_FASTRECOVERY(tp) && @@ -2277,11 +2280,11 @@ * soreceive. It's hard to imagine someone * actually wanting to send this much urgent data. */ - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (th->th_urp + so->so_rcv.sb_cc > sb_max) { th->th_urp = 0; /* XXX */ thflags &= ~TH_URG; /* XXX */ - SOCKBUF_UNLOCK(&so->so_rcv); /* XXX */ + SOCK_UNLOCK(so); /* XXX */ goto dodata; /* XXX */ } /* @@ -2307,7 +2310,7 @@ sohasoutofband(so); tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA); } - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); /* * Remove out of band data so doesn't get presented to user. * This can happen independent of advancing the URG pointer, @@ -2369,12 +2372,13 @@ tcpstat.tcps_rcvpack++; tcpstat.tcps_rcvbyte += tlen; ND6_HINT(tp); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (so->so_rcv.sb_state & SBS_CANTRCVMORE) m_freem(m); else sbappendstream_locked(&so->so_rcv, m); sorwakeup_locked(so); + SOCK_UNLOCK(so); } else { thflags = tcp_reass(tp, th, &tlen, m); tp->t_flags |= TF_ACKNOW; @@ -2969,7 +2973,7 @@ * Make the socket buffers an integral number of mss units; * if the mss is larger than the socket buffer, decrease the mss. */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); if ((so->so_snd.sb_hiwat == tcp_sendspace) && metrics.rmx_sendpipe) bufsize = metrics.rmx_sendpipe; else @@ -2983,10 +2987,8 @@ if (bufsize > so->so_snd.sb_hiwat) (void)sbreserve_locked(&so->so_snd, bufsize, so, NULL); } - SOCKBUF_UNLOCK(&so->so_snd); tp->t_maxseg = mss; - SOCKBUF_LOCK(&so->so_rcv); if ((so->so_rcv.sb_hiwat == tcp_recvspace) && metrics.rmx_recvpipe) bufsize = metrics.rmx_recvpipe; else @@ -2998,7 +3000,7 @@ if (bufsize > so->so_rcv.sb_hiwat) (void)sbreserve_locked(&so->so_rcv, bufsize, so, NULL); } - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); /* * While we're here, check the others too */ --- //depot/vendor/freebsd/src/sys/netinet/tcp_output.c 2006/02/23 21:15:18 +++ //depot/user/rwatson/resock/src/sys/netinet/tcp_output.c 2006/06/06 08:06:38 @@ -251,7 +251,7 @@ if (tp->t_flags & TF_NEEDSYN) flags |= TH_SYN; - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); /* * If in persist timeout with window of 0, send 1 byte. * Otherwise, if window is small but nonzero @@ -516,11 +516,11 @@ * No reason to send a segment, just return. */ just_return: - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); return (0); send: - SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCK_LOCK_ASSERT(so); /* * Before ESTABLISHED, force sending of initial options * unless TCP set not to do any options. @@ -739,7 +739,7 @@ #ifdef notyet if ((m = m_copypack(so->so_snd.sb_mb, off, (int)len, max_linkhdr + hdrlen)) == 0) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = ENOBUFS; goto out; } @@ -751,7 +751,7 @@ #else MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = ENOBUFS; goto out; } @@ -759,7 +759,7 @@ if (MHLEN < hdrlen + max_linkhdr) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); m_freem(m); error = ENOBUFS; goto out; @@ -775,7 +775,7 @@ } else { m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); if (m->m_next == 0) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); (void) m_free(m); error = ENOBUFS; goto out; @@ -790,9 +790,9 @@ */ if (off + len == so->so_snd.sb_cc) flags |= TH_PUSH; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); } else { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); if (tp->t_flags & TF_ACKNOW) tcpstat.tcps_sndacks++; else if (flags & (TH_SYN|TH_FIN|TH_RST)) @@ -816,7 +816,7 @@ m->m_data += max_linkhdr; m->m_len = hdrlen; } - SOCKBUF_UNLOCK_ASSERT(&so->so_snd); + SOCK_UNLOCK_ASSERT(so); m->m_pkthdr.rcvif = (struct ifnet *)0; #ifdef MAC mac_create_mbuf_from_inpcb(tp->t_inpcb, m); @@ -1108,7 +1108,7 @@ } out: - SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */ + SOCK_UNLOCK_ASSERT(so); /* Check gotos. */ if (error == ENOBUFS) { if (!callout_active(tp->tt_rexmt) && !callout_active(tp->tt_persist)) --- //depot/vendor/freebsd/src/sys/netinet/tcp_usrreq.c 2006/06/04 09:36:00 +++ //depot/user/rwatson/resock/src/sys/netinet/tcp_usrreq.c 2006/06/06 08:06:38 @@ -872,9 +872,9 @@ /* * XXXRW: PRUS_EOF not implemented with PRUS_OOB? */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); if (sbspace(&so->so_snd) < -512) { - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); m_freem(m); error = ENOBUFS; goto out; @@ -888,7 +888,7 @@ * Otherwise, snd_up should be one lower. */ sbappendstream_locked(&so->so_snd, m); - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); if (nam && tp->t_state < TCPS_SYN_SENT) { /* * Do implied connect if not yet connected, --- //depot/vendor/freebsd/src/sys/netinet/udp_usrreq.c 2006/06/03 19:30:35 +++ //depot/user/rwatson/resock/src/sys/netinet/udp_usrreq.c 2006/06/06 19:25:16 @@ -498,15 +498,15 @@ m_adj(n, off); so = inp->inp_socket; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { m_freem(n); if (opts) m_freem(opts); udpstat.udps_fullsock++; - SOCKBUF_UNLOCK(&so->so_rcv); } else sorwakeup_locked(so); + SOCK_UNLOCK(so); } /* --- //depot/vendor/freebsd/src/sys/netinet6/udp6_usrreq.c 2006/05/20 13:30:39 +++ //depot/user/rwatson/resock/src/sys/netinet6/udp6_usrreq.c 2006/06/07 11:21:27 @@ -148,16 +148,16 @@ m_adj(n, off + sizeof(struct udphdr)); so = in6p->inp_socket; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)fromsa, n, opts) == 0) { - SOCKBUF_UNLOCK(&so->so_rcv); m_freem(n); if (opts) m_freem(opts); udpstat.udps_fullsock++; } else sorwakeup_locked(so); + SOCK_UNLOCK(so); } int --- //depot/vendor/freebsd/src/sys/netipx/spx_usrreq.c 2006/04/01 15:45:41 +++ //depot/user/rwatson/resock/src/sys/netipx/spx_usrreq.c 2006/06/06 08:06:38 @@ -523,7 +523,7 @@ /* * Trim Acked data from output queue. */ - SOCKBUF_LOCK(&so->so_snd); + SOCK_LOCK(so); while ((m = so->so_snd.sb_mb) != NULL) { if (SSEQ_LT((mtod(m, struct spx *))->si_seq, si->si_ack)) sbdroprecord_locked(&so->so_snd); @@ -531,6 +531,7 @@ break; } sowwakeup_locked(so); + SOCK_UNLOCK(so); cb->s_rack = si->si_ack; update_window: if (SSEQ_LT(cb->s_snxt, cb->s_rack)) @@ -631,7 +632,7 @@ } present: #define SPINC sizeof(struct spxhdr) - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); /* * Loop through all packets queued up to update acknowledge number, @@ -705,8 +706,7 @@ } if (wakeup) sorwakeup_locked(so); - else - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); return (0); } @@ -1650,16 +1650,16 @@ error = EINVAL; goto out; } - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK)) { - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); m->m_len = 1; *mtod(m, caddr_t) = cb->s_iobc; error = 0; goto out; } - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); error = EINVAL; out: IPX_UNLOCK(ipxp); --- //depot/vendor/freebsd/src/sys/netsmb/smb_trantcp.c 2005/01/07 01:52:23 +++ //depot/user/rwatson/resock/src/sys/netsmb/smb_trantcp.c 2005/06/06 04:37:59 @@ -236,44 +236,45 @@ if (error) return error; nbp->nbp_tso = so; + SOCK_LOCK(so); so->so_upcallarg = (caddr_t)nbp; so->so_upcall = nb_upcall; - SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); so->so_rcv.sb_timeo = (5 * hz); so->so_snd.sb_timeo = (5 * hz); + SOCK_UNLOCK(so); error = soreserve(so, nbp->nbp_sndbuf, nbp->nbp_rcvbuf); if (error) goto bad; nb_setsockopt_int(so, SOL_SOCKET, SO_KEEPALIVE, 1); nb_setsockopt_int(so, IPPROTO_TCP, TCP_NODELAY, 1); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_flags &= ~SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags &= ~SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); error = soconnect(so, (struct sockaddr*)to, td); if (error) goto bad; - s = splnet(); + /* + * XXXRW: Move to a properly inter-locked sleep here. + */ + SOCK_LOCK(so); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - tsleep(&so->so_timeo, PSOCK, "nbcon", 2 * hz); + msleep(&so->so_timeo, SOCK_MTX(so), PSOCK, "nbcon", 2 * hz); if ((so->so_state & SS_ISCONNECTING) && so->so_error == 0 && (error = nb_intr(nbp, td->td_proc)) != 0) { so->so_state &= ~SS_ISCONNECTING; - splx(s); + SOCK_UNLOCK(so); goto bad; } } if (so->so_error) { error = so->so_error; so->so_error = 0; - splx(s); + SOCK_UNLOCK(so); goto bad; } - splx(s); + SOCK_UNLOCK(so); return 0; bad: smb_nbst_disconnect(nbp->nbp_vc, td); --- //depot/vendor/freebsd/src/sys/nfsclient/nfs_socket.c 2006/05/23 18:35:58 +++ //depot/user/rwatson/resock/src/sys/nfsclient/nfs_socket.c 2006/06/06 08:06:38 @@ -436,7 +436,7 @@ error = soreserve(so, sndreserve, rcvreserve); if (error) goto bad; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_flags |= SB_NOINTR; so->so_upcallarg = (caddr_t)nmp; if (so->so_type == SOCK_STREAM) @@ -444,10 +444,8 @@ else so->so_upcall = nfs_clnt_udp_soupcall; so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); mtx_lock(&nmp->nm_mtx); /* Initialize other non-zero congestion variables */ @@ -538,11 +536,11 @@ so = nmp->nm_so; nmp->nm_so = NULL; mtx_unlock(&nmp->nm_mtx); - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_upcallarg = NULL; so->so_upcall = NULL; so->so_rcv.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); soshutdown(so, SHUT_WR); soclose(so); } else @@ -883,12 +881,12 @@ nfstcp_readable(struct socket *so, int bytes) { int retval; - - SOCKBUF_LOCK(&so->so_rcv); + + SOCK_LOCK(so); retval = (so->so_rcv.sb_cc >= (bytes) || (so->so_rcv.sb_state & SBS_CANTRCVMORE) || so->so_error); - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); return (retval); } --- //depot/vendor/freebsd/src/sys/nfsserver/nfs_syscalls.c 2006/01/28 19:25:17 +++ //depot/user/rwatson/resock/src/sys/nfsserver/nfs_syscalls.c 2006/06/06 08:06:38 @@ -198,7 +198,7 @@ int siz; struct nfssvc_sock *slp; struct socket *so; - int error, s; + int error; NET_ASSERT_GIANT(); @@ -263,14 +263,12 @@ val = 1; sosetopt(so, &sopt); } - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_flags &= ~SB_NOINTR; so->so_rcv.sb_timeo = 0; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags &= ~SB_NOINTR; so->so_snd.sb_timeo = 0; - SOCKBUF_UNLOCK(&so->so_snd); + SOCK_UNLOCK(so); slp = (struct nfssvc_sock *) malloc(sizeof (struct nfssvc_sock), M_NFSSVC, @@ -286,15 +284,13 @@ /* * XXXRW: Socket locking here? */ - s = splnet(); + SOCK_LOCK(so); so->so_upcallarg = (caddr_t)slp; so->so_upcall = nfsrv_rcv; - SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); + SOCK_UNLOCK(so); slp->ns_flag = (SLP_VALID | SLP_NEEDQ); nfsrv_wakenfsd(slp); - splx(s); NFSD_UNLOCK(); return (0); } @@ -614,11 +610,11 @@ NFSD_UNLOCK(); slp->ns_fp = NULL; so = slp->ns_so; - SOCKBUF_LOCK(&so->so_rcv); + SOCK_LOCK(so); so->so_rcv.sb_flags &= ~SB_UPCALL; - SOCKBUF_UNLOCK(&so->so_rcv); so->so_upcall = NULL; so->so_upcallarg = NULL; + SOCK_UNLOCK(so); soshutdown(so, SHUT_RDWR); closef(fp, NULL); NFSD_LOCK(); --- //depot/vendor/freebsd/src/sys/sys/socketvar.h 2006/04/01 10:59:50 +++ //depot/user/rwatson/resock/src/sys/sys/socketvar.h 2006/06/06 19:25:16 @@ -50,8 +50,6 @@ * Locking key to struct socket: * (a) constant after allocation, no locking required. * (b) locked by SOCK_LOCK(so). - * (c) locked by SOCKBUF_LOCK(&so->so_rcv). - * (d) locked by SOCKBUF_LOCK(&so->so_snd). * (e) locked by ACCEPT_LOCK(). * (f) not locked since integer reads/writes are atomic. * (g) used only as a sleep/wakeup address, no value. @@ -89,28 +87,29 @@ u_short so_error; /* (f) error affecting connection */ struct sigio *so_sigio; /* [sg] information for async I/O or out of band data (SIGURG) */ - u_long so_oobmark; /* (c) chars to oob mark */ + u_long so_oobmark; /* (b) chars to oob mark */ TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */ + struct mtx so_mtx; /* (a) socket mutex */ /* * Variables for socket buffering. */ struct sockbuf { struct selinfo sb_sel; /* process selecting read/write */ - struct mtx sb_mtx; /* sockbuf lock */ - short sb_state; /* (c/d) socket state on sockbuf */ + struct mtx *sb_somtxp; /* (a) pointer to socket mutex */ + short sb_state; /* (b) socket state on sockbuf */ #define sb_startzero sb_mb - struct mbuf *sb_mb; /* (c/d) the mbuf chain */ - struct mbuf *sb_mbtail; /* (c/d) the last mbuf in the chain */ + struct mbuf *sb_mb; /* (b) the mbuf chain */ + struct mbuf *sb_mbtail; /* (b) the last mbuf in the chain */ struct mbuf *sb_lastrecord; /* (c/d) first mbuf of last * record in socket buffer */ - u_int sb_cc; /* (c/d) actual chars in buffer */ - u_int sb_hiwat; /* (c/d) max actual char count */ - u_int sb_mbcnt; /* (c/d) chars of mbufs used */ - u_int sb_mbmax; /* (c/d) max chars of mbufs to use */ - u_int sb_ctl; /* (c/d) non-data chars in buffer */ - int sb_lowat; /* (c/d) low water mark */ - int sb_timeo; /* (c/d) timeout for read/write */ - short sb_flags; /* (c/d) flags, see below */ + u_int sb_cc; /* (b) actual chars in buffer */ + u_int sb_hiwat; /* (b) max actual char count */ + u_int sb_mbcnt; /* (b) chars of mbufs used */ + u_int sb_mbmax; /* (b) max chars of mbufs to use */ + u_int sb_ctl; /* (b) non-data chars in buffer */ + int sb_lowat; /* (b) low water mark */ + int sb_timeo; /* (b) timeout for read/write */ + short sb_flags; /* (b) flags, see below */ } so_rcv, so_snd; /* * Constants for sb_flags field of struct sockbuf. @@ -164,29 +163,47 @@ #define ACCEPT_UNLOCK() mtx_unlock(&accept_mtx) /* - * Per-socket buffer mutex used to protect most fields in the socket - * buffer. + * Per-socket mutex: we use a single mutex to cover the entire socket, + * including both socket buffers. In earlier versions of this code, we used + * separate send and receive mutexes, which allowed greater parallelism but + * also resulted in substantial locking complexity and overhead. For now, + * return to a single mutex to reduce locking costs. Back-pointers from the + * socket buffer allow the lock to be frobbed when only a socket buffer + * reference is available. */ -#define SOCKBUF_MTX(_sb) (&(_sb)->sb_mtx) -#define SOCKBUF_LOCK_INIT(_sb, _name) \ - mtx_init(SOCKBUF_MTX(_sb), _name, NULL, MTX_DEF) -#define SOCKBUF_LOCK_DESTROY(_sb) mtx_destroy(SOCKBUF_MTX(_sb)) -#define SOCKBUF_LOCK(_sb) mtx_lock(SOCKBUF_MTX(_sb)) -#define SOCKBUF_OWNED(_sb) mtx_owned(SOCKBUF_MTX(_sb)) -#define SOCKBUF_UNLOCK(_sb) mtx_unlock(SOCKBUF_MTX(_sb)) -#define SOCKBUF_LOCK_ASSERT(_sb) mtx_assert(SOCKBUF_MTX(_sb), MA_OWNED) -#define SOCKBUF_UNLOCK_ASSERT(_sb) mtx_assert(SOCKBUF_MTX(_sb), MA_NOTOWNED) +#define SOCK_MTX(_so) (&(_so)->so_mtx) +#define SOCK_LOCK_INIT(_so) do { \ + mtx_init(SOCK_MTX(_so), "socket", NULL, MTX_DEF | MTX_RECURSE); \ + (_so)->so_rcv.sb_somtxp = SOCK_MTX(_so); \ + (_so)->so_snd.sb_somtxp = SOCK_MTX(_so); \ +} while (0) +#define SOCK_LOCK_DESTROY(_so) mtx_destroy(SOCK_MTX(_so)) +#define SOCK_LOCK(_so) mtx_lock(SOCK_MTX(_so)) +#define SOCK_UNLOCK(_so) mtx_unlock(SOCK_MTX(_so)) +#define SOCK_OWNED(_so) mtx_owned(SOCK_MTX(_so)) +#define SOCK_LOCK_ASSERT(_so) mtx_assert(SOCK_MTX(_so), MA_OWNED) +#define SOCK_UNLOCK_ASSERT(_so) mtx_assert(SOCK_MTX(_so), MA_NOTOWNED) + +#define SOCKBUF_MTX(_sb) ((_sb)->sb_somtxp) +#define SOCKBUF_LOCK(_sb) do { \ + if (SOCKBUF_MTX(_sb) != NULL) \ + mtx_lock(SOCKBUF_MTX(_sb)); \ +} while (0) + +#define SOCKBUF_UNLOCK(_sb) do { \ + if (SOCKBUF_MTX(_sb) != NULL) \ + mtx_unlock(SOCKBUF_MTX(_sb)); \ +} while (0) + +#define SOCKBUF_LOCK_ASSERT(_sb) do { \ + if (SOCKBUF_MTX(_sb) != NULL) \ + mtx_assert(SOCKBUF_MTX(_sb), MA_OWNED); \ +} while (0) -/* - * Per-socket mutex: we reuse the receive socket buffer mutex for space - * efficiency. This decision should probably be revisited as we optimize - * locking for the socket code. - */ -#define SOCK_MTX(_so) SOCKBUF_MTX(&(_so)->so_rcv) -#define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) -#define SOCK_OWNED(_so) SOCKBUF_OWNED(&(_so)->so_rcv) -#define SOCK_UNLOCK(_so) SOCKBUF_UNLOCK(&(_so)->so_rcv) -#define SOCK_LOCK_ASSERT(_so) SOCKBUF_LOCK_ASSERT(&(_so)->so_rcv) +#define SOCKBUF_UNLOCK_ASSERT(_sb) do { \ + if (SOCKBUF_MTX(_sb) != NULL) \ + mtx_assert(SOCKBUF_MTX(_sb), MA_NOTOWNED); \ +} while (0) /* * Socket state bits. @@ -376,37 +393,33 @@ } while(0) /* - * In sorwakeup() and sowwakeup(), acquire the socket buffer lock to - * avoid a non-atomic test-and-wakeup. However, sowakeup is - * responsible for releasing the lock if it is called. We unlock only - * if we don't call into sowakeup. If any code is introduced that - * directly invokes the underlying sowakeup() primitives, it must - * maintain the same semantics. + * In sorwakeup() and sowwakeup(), acquire the socket lock to avoid a + * non-atomic test-and-wakeup. + * + * XXXRW: The _locked() macros used to release the lock on return. */ #define sorwakeup_locked(so) do { \ - SOCKBUF_LOCK_ASSERT(&(so)->so_rcv); \ + SOCK_LOCK_ASSERT(so); \ if (sb_notify(&(so)->so_rcv)) \ sowakeup((so), &(so)->so_rcv); \ - else \ - SOCKBUF_UNLOCK(&(so)->so_rcv); \ } while (0) #define sorwakeup(so) do { \ - SOCKBUF_LOCK(&(so)->so_rcv); \ + SOCK_LOCK(so); \ sorwakeup_locked(so); \ + SOCK_UNLOCK(so); \ } while (0) #define sowwakeup_locked(so) do { \ - SOCKBUF_LOCK_ASSERT(&(so)->so_snd); \ + SOCK_LOCK_ASSERT(so); \ if (sb_notify(&(so)->so_snd)) \ sowakeup((so), &(so)->so_snd); \ - else \ - SOCKBUF_UNLOCK(&(so)->so_snd); \ } while (0) #define sowwakeup(so) do { \ - SOCKBUF_LOCK(&(so)->so_snd); \ + SOCK_LOCK(so); \ sowwakeup_locked(so); \ + SOCK_UNLOCK(so); \ } while (0) /* @@ -537,6 +550,7 @@ int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp); int soreserve(struct socket *so, u_long sndcc, u_long rcvcc); +void sorflush_locked(struct socket *so); void sorflush(struct socket *so); int sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags,