summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-10-28 05:47:40 +0000
committersam <sam@FreeBSD.org>2003-10-28 05:47:40 +0000
commit39ba2e1c90c5d5fc0d01568719c540b15001528d (patch)
treeec5f03665816c252b1006ac692945285f1783b9b /sys/kern/uipc_socket.c
parenta68a195ad4d4f0bbdd17a20f3ce13c36224a00d7 (diff)
downloadFreeBSD-src-39ba2e1c90c5d5fc0d01568719c540b15001528d.zip
FreeBSD-src-39ba2e1c90c5d5fc0d01568719c540b15001528d.tar.gz
speedup stream socket recv handling by tracking the tail of
the mbuf chain instead of walking the list for each append Submitted by: ps/jayanth Obtained from: netbsd (jason thorpe)
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 7d12c8f..4d4eb63 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -888,6 +888,8 @@ restart:
error = EWOULDBLOCK;
goto release;
}
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
sbunlock(&so->so_rcv);
error = sbwait(&so->so_rcv);
splx(s);
@@ -898,6 +900,8 @@ restart:
dontblock:
if (uio->uio_td)
uio->uio_td->td_proc->p_stats->p_ru.ru_msgrcv++;
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
nextrecord = m->m_nextpkt;
if (pr->pr_flags & PR_ADDR) {
KASSERT(m->m_type == MT_SONAME,
@@ -939,12 +943,32 @@ dontblock:
}
}
if (m) {
- if ((flags & MSG_PEEK) == 0)
+ if ((flags & MSG_PEEK) == 0) {
m->m_nextpkt = nextrecord;
+ /*
+ * If nextrecord == NULL (this is a single chain),
+ * then sb_lastrecord may not be valid here if m
+ * was changed earlier.
+ */
+ if (nextrecord == NULL) {
+ KASSERT(so->so_rcv.sb_mb == m,
+ ("receive tailq 1"));
+ so->so_rcv.sb_lastrecord = m;
+ }
+ }
type = m->m_type;
if (type == MT_OOBDATA)
flags |= MSG_OOB;
+ } else {
+ if ((flags & MSG_PEEK) == 0) {
+ KASSERT(so->so_rcv.sb_mb == m,("receive tailq 2"));
+ so->so_rcv.sb_mb = nextrecord;
+ SB_EMPTY_FIXUP(&so->so_rcv);
+ }
}
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
+
moff = 0;
offset = 0;
while (m && uio->uio_resid > 0 && error == 0) {
@@ -971,6 +995,8 @@ dontblock:
* block interrupts again.
*/
if (mp == 0) {
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
splx(s);
#ifdef ZERO_COPY_SOCKETS
if (so_zero_copy_receive) {
@@ -1018,8 +1044,16 @@ dontblock:
so->so_rcv.sb_mb = m_free(m);
m = so->so_rcv.sb_mb;
}
- if (m)
+ if (m) {
m->m_nextpkt = nextrecord;
+ if (nextrecord == NULL)
+ so->so_rcv.sb_lastrecord = m;
+ } else {
+ so->so_rcv.sb_mb = nextrecord;
+ SB_EMPTY_FIXUP(&so->so_rcv);
+ }
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
}
} else {
if (flags & MSG_PEEK)
@@ -1064,6 +1098,8 @@ dontblock:
*/
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
error = sbwait(&so->so_rcv);
if (error) {
sbunlock(&so->so_rcv);
@@ -1082,8 +1118,21 @@ dontblock:
(void) sbdroprecord(&so->so_rcv);
}
if ((flags & MSG_PEEK) == 0) {
- if (m == 0)
+ if (m == 0) {
+ /*
+ * First part is an inline SB_EMPTY_FIXUP(). Second
+ * part makes sure sb_lastrecord is up-to-date if
+ * there is still data in the socket buffer.
+ */
so->so_rcv.sb_mb = nextrecord;
+ if (so->so_rcv.sb_mb == NULL) {
+ so->so_rcv.sb_mbtail = NULL;
+ so->so_rcv.sb_lastrecord = NULL;
+ } else if (nextrecord->m_nextpkt == NULL)
+ so->so_rcv.sb_lastrecord = nextrecord;
+ }
+ SBLASTRECORDCHK(&so->so_rcv);
+ SBLASTMBUFCHK(&so->so_rcv);
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
}
OpenPOWER on IntegriCloud