summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-11-17 03:07:11 +0000
committerdillon <dillon@FreeBSD.org>2001-11-17 03:07:11 +0000
commit86ed17d675cb503ddb3f71f8b6f7c3af530bb29a (patch)
treed5160b5791cda1a8cfbbcd3f5e1bd7ea97561c8f /sys/kern/uipc_socket.c
parentfe91520d395f7879be049a289cbac3389fed1749 (diff)
downloadFreeBSD-src-86ed17d675cb503ddb3f71f8b6f7c3af530bb29a.zip
FreeBSD-src-86ed17d675cb503ddb3f71f8b6f7c3af530bb29a.tar.gz
Give struct socket structures a ref counting interface similar to
vnodes. This will hopefully serve as a base from which we can expand the MP code. We currently do not attempt to obtain any mutex or SX locks, but the door is open to add them when we nail down exactly how that part of it is going to work.
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 10c8585..caae630c 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -91,6 +91,10 @@ SYSCTL_DECL(_kern_ipc);
static int somaxconn = SOMAXCONN;
SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW,
&somaxconn, 0, "Maximum pending socket connection queue size");
+static int numopensockets;
+SYSCTL_INT(_kern_ipc, OID_AUTO, numopensockets, CTLFLAG_RD,
+ &numopensockets, 0, "Number of open sockets");
+
/*
* Socket operation routines.
@@ -106,6 +110,8 @@ SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW,
* Note that it would probably be better to allocate socket
* and PCB at the same time, but I'm not convinced that all
* the protocols can be easily modified to do this.
+ *
+ * soalloc() returns a socket with a ref count of 0.
*/
struct socket *
soalloc(waitok)
@@ -119,11 +125,17 @@ soalloc(waitok)
bzero(so, sizeof *so);
so->so_gencnt = ++so_gencnt;
so->so_zone = socket_zone;
+ /* sx_init(&so->so_sxlock, "socket sxlock"); */
TAILQ_INIT(&so->so_aiojobq);
+ ++numopensockets;
}
return so;
}
+/*
+ * socreate returns a socket with a ref count of 1. The socket should be
+ * closed with soclose().
+ */
int
socreate(dom, aso, type, proto, td)
int dom;
@@ -162,10 +174,11 @@ socreate(dom, aso, type, proto, td)
so->so_type = type;
so->so_cred = crhold(td->td_proc->p_ucred);
so->so_proto = prp;
+ soref(so);
error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
if (error) {
so->so_state |= SS_NOFDREF;
- sofree(so);
+ sorele(so);
return (error);
}
*aso = so;
@@ -186,11 +199,11 @@ sobind(so, nam, td)
return (error);
}
-void
-sodealloc(so)
- struct socket *so;
+static void
+sodealloc(struct socket *so)
{
+ KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count));
so->so_gencnt = ++so_gencnt;
if (so->so_rcv.sb_hiwat)
(void)chgsbsize(so->so_cred->cr_uidinfo,
@@ -210,7 +223,9 @@ sodealloc(so)
}
#endif
crfree(so->so_cred);
+ /* sx_destroy(&so->so_sxlock); */
zfree(so->so_zone, so);
+ --numopensockets;
}
int
@@ -242,6 +257,8 @@ sofree(so)
{
struct socket *head = so->so_head;
+ KASSERT(so->so_count == 0, ("socket %p so_count not 0", so));
+
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
return;
if (head != NULL) {
@@ -272,6 +289,10 @@ sofree(so)
* Close a socket on last file table reference removal.
* Initiate disconnect if connected.
* Free socket when disconnect complete.
+ *
+ * This function will sorele() the socket. Note that soclose() may be
+ * called prior to the ref count reaching zero. The actual socket
+ * structure will not be freed until the ref count reaches zero.
*/
int
soclose(so)
@@ -329,7 +350,7 @@ discard:
if (so->so_state & SS_NOFDREF)
panic("soclose: NOFDREF");
so->so_state |= SS_NOFDREF;
- sofree(so);
+ sorele(so);
splx(s);
return (error);
}
@@ -345,7 +366,7 @@ soabort(so)
error = (*so->so_proto->pr_usrreqs->pru_abort)(so);
if (error) {
- sofree(so);
+ sotryfree(so); /* note: does not decrement the ref count */
return error;
}
return (0);
OpenPOWER on IntegriCloud