summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_sockbuf.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-08-01 10:30:26 +0000
committerrwatson <rwatson@FreeBSD.org>2006-08-01 10:30:26 +0000
commitcedd19512d5ec8d27159476420b827e2e01731e1 (patch)
tree20b032b51bec9502f0c354ae03f8f7a68d6f1f67 /sys/kern/uipc_sockbuf.c
parent1157b51024537d013f39373f730c9a1462a81c8b (diff)
downloadFreeBSD-src-cedd19512d5ec8d27159476420b827e2e01731e1.zip
FreeBSD-src-cedd19512d5ec8d27159476420b827e2e01731e1.tar.gz
Reimplement socket buffer tear-down in sofree(): as the socket is no
longer referenced by other threads (hence our freeing it), we don't need to set the can't send and can't receive flags, wake up the consumers, perform two levels of locking, etc. Implement a fast-path teardown, sbdestroy(), which flushes and releases each socket buffer. A manual dom_dispose of the receive buffer is still required explicitly to GC any in-flight file descriptors, etc, before flushing the buffer. This results in a 9% UP performance improvement and 16% SMP performance improvement on a tight loop of socket();close(); in micro-benchmarking, but will likely also affect CPU-bound macro-benchmark performance.
Diffstat (limited to 'sys/kern/uipc_sockbuf.c')
-rw-r--r--sys/kern/uipc_sockbuf.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index e266272..72c54ac 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -64,6 +64,10 @@ static u_long sb_max_adj =
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 @@ sbreserve(sb, cc, so, td)
/*
* 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 @@ sbrelease_locked(sb, so)
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(sb, so)
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 @@ sbcompress(sb, m, n)
* 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 @@ sbflush_locked(sb)
*/
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 @@ sbflush(sb)
/*
* 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 @@ sbdrop_locked(sb, len)
* 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;
OpenPOWER on IntegriCloud