When processing ACK in tcp_do_segment, use sbcut_locked() instead of

sbdrop_locked() to cut acked mbufs from the socket buffer. Free this
chain a batch manner after the socket buffer lock is dropped.

This measurably reduces contention on socket buffer.

Sponsored by:	Netflix
Sponsored by:	Nginx, Inc.
Approved by:	re (marius)
This commit is contained in:
Gleb Smirnoff 2013-10-09 12:00:38 +00:00
parent 1d2df300e9
commit c11a15bf8d

View File

@ -1461,6 +1461,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
u_long tiwin;
char *s;
struct in_conninfo *inc;
struct mbuf *mfree;
struct tcpopt to;
#ifdef TCPDEBUG
@ -2718,15 +2719,17 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
sbdrop_locked(&so->so_snd, (int)so->so_snd.sb_cc);
mfree = sbcut_locked(&so->so_snd,
(int)so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
sbdrop_locked(&so->so_snd, acked);
mfree = sbcut_locked(&so->so_snd, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
/* NB: sowwakeup_locked() does an implicit unlock. */
sowwakeup_locked(so);
m_freem(mfree);
/* Detect una wraparound. */
if (!IN_RECOVERY(tp->t_flags) &&
SEQ_GT(tp->snd_una, tp->snd_recover) &&