diff options
author | sam <sam@FreeBSD.org> | 2003-10-28 05:47:40 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-10-28 05:47:40 +0000 |
commit | 39ba2e1c90c5d5fc0d01568719c540b15001528d (patch) | |
tree | ec5f03665816c252b1006ac692945285f1783b9b /sys/kern/uipc_socket.c | |
parent | a68a195ad4d4f0bbdd17a20f3ce13c36224a00d7 (diff) | |
download | FreeBSD-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.c | 55 |
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); } |