aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Watson <rwatson@FreeBSD.org>2008-02-04 12:25:13 +0000
committerRobert Watson <rwatson@FreeBSD.org>2008-02-04 12:25:13 +0000
commit3f0bfcccfd39ce7c8b6564a254a1edb504caf5bb (patch)
tree07b631ecc21ddad4957ba8b20d818e81af4c6e1f
parent2591e96ce2cf2fae957926a68d8e5ee93482c97c (diff)
downloadsrc-3f0bfcccfd39ce7c8b6564a254a1edb504caf5bb.tar.gz
src-3f0bfcccfd39ce7c8b6564a254a1edb504caf5bb.zip
Further clean up sorflush:
- Expose sbrelease_internal(), a variant of sbrelease() with no expectations about the validity of locks in the socket buffer. - Use sbrelease_internel() in sorflush(), and as a result avoid intializing and destroying a socket buffer lock for the temporary stack copy of the actual buffer, asb. - Add a comment indicating why we do what we do, and remove an XXX since things have gotten less ugly in sorflush() lately. This makes socket close cleaner, and possibly also marginally faster. MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=175968
-rw-r--r--sys/kern/uipc_sockbuf.c3
-rw-r--r--sys/kern/uipc_socket.c24
-rw-r--r--sys/sys/socketvar.h1
3 files changed, 14 insertions, 14 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 16923cf5c34f..9e8982685e5a 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -67,7 +67,6 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */
static void sbdrop_internal(struct sockbuf *sb, int len);
static void sbflush_internal(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
@@ -322,7 +321,7 @@ sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
/*
* Free mbufs held by a socket, and reserved mbuf space.
*/
-static void
+void
sbrelease_internal(struct sockbuf *sb, struct socket *so)
{
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 0de6d2906b47..bbb4f89ced45 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1877,15 +1877,13 @@ sorflush(struct socket *so)
struct sockbuf asb;
/*
- * 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.
- */
-
- /*
+ * In order to avoid calling dom_dispose with the socket buffer mutex
+ * held, and in order to generally avoid holding the lock for a long
+ * time, we make a copy of the socket buffer and clear the original
+ * (except locks, state). The new socket buffer copy won't have
+ * initialized locks so we can only call routines that won't use or
+ * assert those locks.
+ *
* Dislodge threads currently blocked in receive and wait to acquire
* a lock against other simultaneous readers before clearing the
* socket buffer. Don't let our acquire be interrupted by a signal
@@ -1907,11 +1905,13 @@ sorflush(struct socket *so)
SOCKBUF_UNLOCK(sb);
sbunlock(sb);
- SOCKBUF_LOCK_INIT(&asb, "so_rcv");
+ /*
+ * Dispose of special rights and flush the socket buffer. Don't call
+ * any unsafe routines (that rely on locks being initialized) on asb.
+ */
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);
+ sbrelease_internal(&asb, so);
}
/*
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 09e58ab7b35b..40f3dd9baa78 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -483,6 +483,7 @@ void sbdroprecord_locked(struct sockbuf *sb);
void sbflush(struct sockbuf *sb);
void sbflush_locked(struct sockbuf *sb);
void sbrelease(struct sockbuf *sb, struct socket *so);
+void sbrelease_internal(struct sockbuf *sb, struct socket *so);
void sbrelease_locked(struct sockbuf *sb, struct socket *so);
int sbreserve(struct sockbuf *sb, u_long cc, struct socket *so,
struct thread *td);