--- //depot/vendor/freebsd/src/sys/kern/uipc_sockbuf.c 2006/07/24 16:26:14 +++ //depot/user/rwatson/sockref/src/sys/kern/uipc_sockbuf.c 2006/07/31 11:16:47 @@ -64,6 +64,10 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */ +static void sbdrop_internal(register struct sockbuf *sb, register int len); +static void sbflush_internal(register struct sockbuf *sb); +static void sbrelease_internal(struct sockbuf *sb, struct socket *so); + /* * Socantsendmore indicates that no more data will be sent on the * socket; it would normally be applied to a socket when the user @@ -331,6 +335,18 @@ /* * Free mbufs held by a socket, and reserved mbuf space. */ +static void +sbrelease_internal(sb, so) + struct sockbuf *sb; + struct socket *so; +{ + + sbflush_internal(sb); + (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, + RLIM_INFINITY); + sb->sb_mbmax = 0; +} + void sbrelease_locked(sb, so) struct sockbuf *sb; @@ -339,10 +355,7 @@ SOCKBUF_LOCK_ASSERT(sb); - sbflush_locked(sb); - (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, - RLIM_INFINITY); - sb->sb_mbmax = 0; + sbrelease_internal(sb, so); } void @@ -355,6 +368,17 @@ sbrelease_locked(sb, so); SOCKBUF_UNLOCK(sb); } + +void +sbdestroy(sb, so) + struct sockbuf *sb; + struct socket *so; +{ + + sbrelease_internal(sb, so); +} + + /* * Routines to add and remove * data from an mbuf queue. @@ -823,13 +847,11 @@ * Free all mbufs in a sockbuf. * Check that all resources are reclaimed. */ -void -sbflush_locked(sb) +static void +sbflush_internal(sb) register struct sockbuf *sb; { - SOCKBUF_LOCK_ASSERT(sb); - if (sb->sb_flags & SB_LOCK) panic("sbflush_locked: locked"); while (sb->sb_mbcnt) { @@ -839,13 +861,22 @@ */ if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len)) break; - sbdrop_locked(sb, (int)sb->sb_cc); + sbdrop_internal(sb, (int)sb->sb_cc); } if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt) panic("sbflush_locked: cc %u || mb %p || mbcnt %u", sb->sb_cc, (void *)sb->sb_mb, sb->sb_mbcnt); } void +sbflush_locked(sb) + register struct sockbuf *sb; +{ + + SOCKBUF_LOCK_ASSERT(sb); + sbflush_internal(sb); +} + +void sbflush(sb) register struct sockbuf *sb; { @@ -858,16 +889,14 @@ /* * Drop data from (the front of) a sockbuf. */ -void -sbdrop_locked(sb, len) +static void +sbdrop_internal(sb, len) register struct sockbuf *sb; register int len; { register struct mbuf *m; struct mbuf *next; - SOCKBUF_LOCK_ASSERT(sb); - next = (m = sb->sb_mb) ? m->m_nextpkt : 0; while (len > 0) { if (m == 0) { @@ -916,6 +945,17 @@ * Drop data from (the front of) a sockbuf. */ void +sbdrop_locked(sb, len) + register struct sockbuf *sb; + register int len; +{ + + SOCKBUF_LOCK_ASSERT(sb); + + sbdrop_internal(sb, len); +} + +void sbdrop(sb, len) register struct sockbuf *sb; register int len; --- //depot/vendor/freebsd/src/sys/kern/uipc_socket.c 2006/07/24 15:22:01 +++ //depot/user/rwatson/sockref/src/sys/kern/uipc_socket.c 2006/07/31 10:45:45 @@ -555,6 +555,7 @@ sofree(so) struct socket *so; { + struct protosw *pr = so->so_proto; struct socket *head; ACCEPT_LOCK_ASSERT(); @@ -588,24 +589,26 @@ 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. + * From this point on, we assume that no other references to this + * socket exist anywhere else in the stack. Therefore, no locks need + * to be acquired or held. + * + * XXXRW: We used to do a lot of socket buffer and socket locking + * here, as well as invoke sorflush() and perform wakeups. The + * direct call to dom_dispose() and sbrelease_internal() are an + * inlining of what was necessary from sorflush(). */ - 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); + KASSERT((so->so_snd.sb_flags & SB_LOCK) == 0, ("sofree: snd sblock")); + KASSERT((so->so_rcv.sb_flags & SB_LOCK) == 0, ("sofree: rcv sblock")); + sbdestroy(&so->so_snd, so); + if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL) + (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb); + sbdestroy(&so->so_rcv, so); knlist_destroy(&so->so_rcv.sb_sel.si_note); knlist_destroy(&so->so_snd.sb_sel.si_note); - if (so->so_proto->pr_usrreqs->pru_detach != NULL) - (*so->so_proto->pr_usrreqs->pru_detach)(so); + if (pr->pr_usrreqs->pru_detach != NULL) + (*pr->pr_usrreqs->pru_detach)(so); sodealloc(so); } --- //depot/vendor/freebsd/src/sys/sys/socketvar.h 2006/07/24 15:22:01 +++ //depot/user/rwatson/sockref/src/sys/sys/socketvar.h 2006/07/31 10:45:45 @@ -477,6 +477,7 @@ void sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n); struct mbuf * sbcreatecontrol(caddr_t p, int size, int type, int level); +void sbdestroy(struct sockbuf *sb, struct socket *so); void sbdrop(struct sockbuf *sb, int len); void sbdrop_locked(struct sockbuf *sb, int len); void sbdroprecord(struct sockbuf *sb);