--- //depot/vendor/freebsd/src/sys/kern/kern_descrip.c	2004/06/11 11:20:57
+++ //depot/user/rwatson/netperf_merge/sys/kern/kern_descrip.c	2004/06/12 19:29:02
@@ -2024,7 +2024,9 @@
 		*spp = fp->f_data;
 		if (fflagp)
 			*fflagp = fp->f_flag;
+		SOCK_LOCK(*spp);
 		soref(*spp);
+		SOCK_UNLOCK(*spp);
 	}
 	FILEDESC_UNLOCK(td->td_proc->p_fd);
 	return (error);
@@ -2039,6 +2041,7 @@
 {
 
 	NET_ASSERT_GIANT();
+	SOCK_LOCK(so);
 	sorele(so);
 }
 
--- //depot/vendor/freebsd/src/sys/kern/uipc_socket.c	2004/06/12 16:11:33
+++ //depot/user/rwatson/netperf_merge/sys/kern/uipc_socket.c	2004/06/12 19:29:02
@@ -201,9 +201,12 @@
 #ifdef MAC
 	mac_create_socket(cred, so);
 #endif
+	SOCK_LOCK(so);
 	soref(so);
+	SOCK_UNLOCK(so);
 	error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
 	if (error) {
+		SOCK_LOCK(so);
 		so->so_state |= SS_NOFDREF;
 		sorele(so);
 		return (error);
@@ -292,10 +295,14 @@
 	int s;
 
 	KASSERT(so->so_count == 0, ("socket %p so_count not 0", so));
+	SOCK_LOCK_ASSERT(so);
 
-	if (so->so_pcb != NULL || (so->so_state & SS_NOFDREF) == 0)
+	if (so->so_pcb != NULL || (so->so_state & SS_NOFDREF) == 0) {
+		SOCK_UNLOCK(so);
 		return;
+	}
 
+	SOCK_UNLOCK(so);
 	ACCEPT_LOCK();
 	head = so->so_head;
 	if (head != NULL) {
@@ -409,6 +416,7 @@
 			error = error2;
 	}
 discard:
+	SOCK_LOCK(so);
 	if (so->so_state & SS_NOFDREF)
 		panic("soclose: NOFDREF");
 	so->so_state |= SS_NOFDREF;
@@ -428,6 +436,7 @@
 
 	error = (*so->so_proto->pr_usrreqs->pru_abort)(so);
 	if (error) {
+		SOCK_LOCK(so);
 		sotryfree(so);	/* note: does not decrement the ref count */
 		return error;
 	}
--- //depot/vendor/freebsd/src/sys/kern/uipc_syscalls.c	2004/06/11 11:20:57
+++ //depot/user/rwatson/netperf_merge/sys/kern/uipc_syscalls.c	2004/06/12 19:29:02
@@ -309,7 +309,14 @@
 	KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
 	KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
 
+        /*
+         * Before changing the flags on the socket, we have to bump the
+	 * reference count.  Otherwise, if the protocol calls sofree(),
+         * the socket will be released due to a zero refcount.
+         */
+	SOCK_LOCK(so);
 	soref(so);			/* file descriptor reference */
+	SOCK_UNLOCK(so);
 	
 	TAILQ_REMOVE(&head->so_comp, so, so_list);
 	head->so_qlen--;
--- //depot/vendor/freebsd/src/sys/kern/uipc_usrreq.c	2004/06/10 21:35:45
+++ //depot/user/rwatson/netperf_merge/sys/kern/uipc_usrreq.c	2004/06/12 19:29:02
@@ -114,6 +114,7 @@
 	UNP_LOCK();
 	unp_drop(unp, ECONNABORTED);
 	unp_detach(unp);	/* NB: unlocks */
+	SOCK_LOCK(so);
 	sotryfree(so);
 	return (0);
 }
--- //depot/vendor/freebsd/src/sys/net/raw_cb.c	2004/06/11 03:55:35
+++ //depot/user/rwatson/netperf_merge/sys/net/raw_cb.c	2004/06/12 20:30:39
@@ -32,7 +32,9 @@
 
 #include <sys/param.h>
 #include <sys/domain.h>
+#include <sys/lock.h>
 #include <sys/malloc.h>
+#include <sys/mutex.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
@@ -93,6 +95,7 @@
 {
 	struct socket *so = rp->rcb_socket;
 
+	SOCK_LOCK(so);
 	so->so_pcb = 0;
 	sotryfree(so);
 	LIST_REMOVE(rp, list);
--- //depot/vendor/freebsd/src/sys/net/raw_usrreq.c	2004/04/07 20:52:05
+++ //depot/user/rwatson/netperf_merge/sys/net/raw_usrreq.c	2004/06/12 20:30:39
@@ -34,6 +34,7 @@
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
+#include <sys/mutex.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -139,8 +140,9 @@
 	if (rp == 0)
 		return EINVAL;
 	raw_disconnect(rp);
+	soisdisconnected(so);
+	SOCK_LOCK(so);
 	sotryfree(so);
-	soisdisconnected(so);	/* XXX huh? called after the sofree()? */
 	return 0;
 }
 
--- //depot/vendor/freebsd/src/sys/netatalk/ddp_pcb.c	2004/03/22 04:56:26
+++ //depot/user/rwatson/netperf_merge/sys/netatalk/ddp_pcb.c	2004/06/12 19:29:02
@@ -253,6 +253,7 @@
 at_pcbdetach(struct socket *so, struct ddpcb *ddp)
 {
     soisdisconnected(so);
+    SOCK_LOCK(so);
     so->so_pcb = NULL;
     sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/netatm/atm_socket.c	2003/10/31 18:36:05
+++ //depot/user/rwatson/netperf_merge/sys/netatm/atm_socket.c	2004/06/12 19:29:02
@@ -173,6 +173,7 @@
 	/*
 	 * Break links and free control blocks
 	 */
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c	2004/05/29 00:56:26
+++ //depot/user/rwatson/netperf_merge/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c	2004/06/12 19:29:02
@@ -1417,6 +1417,7 @@
 	bzero(pcb, sizeof(*pcb));
 	FREE(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW);
 
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c	2004/05/29 00:56:26
+++ //depot/user/rwatson/netperf_merge/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c	2004/06/12 19:29:02
@@ -1804,6 +1804,7 @@
 				FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP);
 
 				soisdisconnected(so);
+				SOCK_LOCK(so);
 				so->so_pcb = NULL;
 				sotryfree(so);
 
@@ -2346,6 +2347,7 @@
 	FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP);
 
 	soisdisconnected(so);
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c	2004/05/29 00:56:26
+++ //depot/user/rwatson/netperf_merge/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c	2004/06/12 19:29:02
@@ -1129,6 +1129,7 @@
 	bzero(pcb, sizeof(*pcb));
 	FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP_RAW);
 
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c	2004/06/02 04:20:47
+++ //depot/user/rwatson/netperf_merge/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c	2004/06/12 19:29:02
@@ -724,6 +724,7 @@
 	FREE(pcb, M_NETGRAPH_BTSOCKET_RFCOMM);
 
 	soisdisconnected(so);
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	sotryfree(so);
 
@@ -1370,8 +1371,10 @@
 	s0->l2so->so_qlen --;
 	l2so->so_qstate &= ~SQ_COMP;
 	l2so->so_head = NULL;
+	SOCK_LOCK(l2so);
 	soref(l2so);
 	l2so->so_state |= SS_NBIO;
+	SOCK_UNLOCK(l2so);
 	ACCEPT_UNLOCK();
 
 	error = soaccept(l2so, (struct sockaddr **) &l2sa);
--- //depot/vendor/freebsd/src/sys/netgraph/ng_ksocket.c	2004/06/02 04:20:47
+++ //depot/user/rwatson/netperf_merge/sys/netgraph/ng_ksocket.c	2004/06/12 19:29:02
@@ -1205,8 +1205,10 @@
 	head->so_qlen--;
 	so->so_qstate &= ~SQ_COMP;
 	so->so_head = NULL;
+	SOCK_LOCK(so);
 	soref(so);
 	so->so_state |= SS_NBIO;
+	SOCK_UNLOCK(so);
 	ACCEPT_UNLOCK();
 
 	/* XXX KNOTE(&head->so_rcv.sb_sel.si_note, 0); */
--- //depot/vendor/freebsd/src/sys/netinet/in_pcb.c	2004/05/20 06:35:28
+++ //depot/user/rwatson/netperf_merge/sys/netinet/in_pcb.c	2004/06/12 19:29:02
@@ -690,6 +690,7 @@
 	inp->inp_gencnt = ++ipi->ipi_gencnt;
 	in_pcbremlists(inp);
 	if (so) {
+		SOCK_LOCK(so);
 		so->so_pcb = 0;
 		sotryfree(so);
 	}
--- //depot/vendor/freebsd/src/sys/netinet/tcp_subr.c	2004/05/04 02:15:32
+++ //depot/user/rwatson/netperf_merge/sys/netinet/tcp_subr.c	2004/06/12 19:29:02
@@ -1657,13 +1657,14 @@
 	}
 	tcp_discardcb(tp);
 	so = inp->inp_socket;
+	SOCK_LOCK(so);
 	so->so_pcb = NULL;
 	tw->tw_cred = crhold(so->so_cred);
 	tw->tw_so_options = so->so_options;
+	sotryfree(so);
+	inp->inp_socket = NULL;
 	if (acknow)
 		tcp_twrespond(tw, TH_ACK);
-	sotryfree(so);
-	inp->inp_socket = NULL;
 	inp->inp_ppcb = (caddr_t)tw;
 	inp->inp_vflag |= INP_TIMEWAIT;
 	tcp_timer_2msl_reset(tw, tw_time);
--- //depot/vendor/freebsd/src/sys/netinet6/in6_pcb.c	2004/04/07 20:52:05
+++ //depot/user/rwatson/netperf_merge/sys/netinet6/in6_pcb.c	2004/06/12 19:29:02
@@ -438,6 +438,7 @@
 	in_pcbremlists(inp);
 
 	if (so) {
+		SOCK_LOCK(so);
 		so->so_pcb = NULL;
 		sotryfree(so);
 	}
--- //depot/vendor/freebsd/src/sys/netipx/ipx_pcb.c	2004/03/01 03:15:33
+++ //depot/user/rwatson/netperf_merge/sys/netipx/ipx_pcb.c	2004/06/12 19:29:02
@@ -268,6 +268,7 @@
 {
 	struct socket *so = ipxp->ipxp_socket;
 
+	SOCK_LOCK(so);
 	so->so_pcb = 0;
 	sotryfree(so);
 	if (ipxp->ipxp_route.ro_rt != NULL)
--- //depot/vendor/freebsd/src/sys/netipx/ipx_usrreq.c	2003/11/18 00:40:43
+++ //depot/user/rwatson/netperf_merge/sys/netipx/ipx_usrreq.c	2004/06/12 19:29:02
@@ -423,8 +423,9 @@
 	s = splnet();
 	ipx_pcbdetach(ipxp);
 	splx(s);
+	soisdisconnected(so);
+	SOCK_LOCK(so);
 	sotryfree(so);
-	soisdisconnected(so);
 	return (0);
 }
 
--- //depot/vendor/freebsd/src/sys/netnatm/natm.c	2004/03/01 03:15:33
+++ //depot/user/rwatson/netperf_merge/sys/netnatm/natm.c	2004/06/12 19:29:02
@@ -135,6 +135,7 @@
      * we turn on 'drain' *before* we sofree.
      */
     npcb_free(npcb, NPCB_DESTROY);	/* drain */
+    SOCK_LOCK(so);
     so->so_pcb = NULL;
     sotryfree(so);
  out:
@@ -463,6 +464,7 @@
        */
 
       npcb_free(npcb, NPCB_DESTROY);	/* drain */
+      SOCK_LOCK(so);
       so->so_pcb = NULL;
       sotryfree(so);
 
--- //depot/vendor/freebsd/src/sys/sys/socketvar.h	2004/06/12 18:38:10
+++ //depot/user/rwatson/netperf_merge/sys/sys/socketvar.h	2004/06/12 19:29:02
@@ -57,7 +57,7 @@
  * (g) used only as a sleep/wakeup address, no value.
  */
 struct socket {
-	int	so_count;		/* reference count */
+	int	so_count;		/* (b) reference count */
 	short	so_type;		/* (a) generic type, see socket.h */
 	short	so_options;		/* from socket call, see socket.h */
 	short	so_linger;		/* time to linger while closing */
@@ -316,19 +316,26 @@
  * the structure.
  */
 #define	soref(so) do {							\
+	SOCK_LOCK_ASSERT(so);						\
 	++(so)->so_count;						\
 } while (0)
 
 #define	sorele(so) do {							\
+	SOCK_LOCK_ASSERT(so);						\
 	if ((so)->so_count <= 0)					\
 		panic("sorele");					\
 	if (--(so)->so_count == 0)					\
 		sofree(so);						\
+	else								\
+		SOCK_UNLOCK(so);					\
 } while (0)
 
 #define	sotryfree(so) do {						\
+	SOCK_LOCK_ASSERT(so);						\
 	if ((so)->so_count == 0)					\
 		sofree(so);						\
+	else								\
+		SOCK_UNLOCK(so);					\
 } while(0)
 
 #define	sorwakeup(so) do {						\
