Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -1465,6 +1465,22 @@ return (newsize); } +void +tcp_handle_wakeup(struct tcpcb *tp, struct socket *so) +{ + INP_UNLOCK_ASSERT(tp->t_inpcb); + if (tp->t_flags & TF_WAKESOR) { + tp->t_flags &= ~TF_WAKESOR; + SOCKBUF_UNLOCK_ASSERT(&so->so_rcv); + sorwakeup(so); + } + if (tp->t_flags & TF_WAKESOW) { + tp->t_flags &= ~TF_WAKESOW; + SOCKBUF_UNLOCK_ASSERT(&so->so_snd); + sowwakeup(so); + } +} + void tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos) @@ -1805,7 +1821,7 @@ else if (!tcp_timer_active(tp, TT_PERSIST)) tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); - sowwakeup(so); + tp->t_flags |= TF_WAKESOW; if (sbavail(&so->so_snd)) (void) tp->t_fb->tfb_tcp_output(tp); goto check_delack; @@ -1861,8 +1877,8 @@ m_adj(m, drop_hdrlen); /* delayed header drop */ sbappendstream_locked(&so->so_rcv, m, 0); } - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; if (DELAY_ACK(tp, tlen)) { tp->t_flags |= TF_DELACK; } else { @@ -2793,8 +2809,8 @@ tp->snd_wnd = 0; ourfinisacked = 0; } - /* NB: sowwakeup_locked() does an implicit unlock. */ - sowwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_snd); + tp->t_flags |= TF_WAKESOW; m_freem(mfree); /* Detect una wraparound. */ if (!IN_RECOVERY(tp->t_flags) && @@ -3007,8 +3023,8 @@ m_freem(m); else sbappendstream_locked(&so->so_rcv, m, 0); - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; } else { /* * XXX: Due to the header drop above "th" is @@ -3140,6 +3156,7 @@ tcp_timer_activate(tp, TT_DELACK, tcp_delacktime); } INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); return; dropafterack: @@ -3173,6 +3190,7 @@ tp->t_flags |= TF_ACKNOW; (void) tp->t_fb->tfb_tcp_output(tp); INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); m_freem(m); return; @@ -3180,6 +3198,7 @@ if (tp != NULL) { tcp_dropwithreset(m, th, tp, tlen, rstreason); INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); } else tcp_dropwithreset(m, th, NULL, tlen, rstreason); return; @@ -3194,8 +3213,10 @@ &tcp_savetcp, 0); #endif TCP_PROBE3(debug__input, tp, th, m); - if (tp != NULL) + if (tp != NULL) { INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); + } m_freem(m); } Index: sys/netinet/tcp_reass.c =================================================================== --- sys/netinet/tcp_reass.c +++ sys/netinet/tcp_reass.c @@ -961,7 +961,8 @@ } else { sbappendstream_locked(&so->so_rcv, m, 0); } - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; return (flags); } if (tcp_new_limits) { @@ -1109,6 +1110,7 @@ #ifdef TCP_REASS_LOGGING tcp_reass_log_dump(tp); #endif - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; return (flags); } Index: sys/netinet/tcp_stacks/bbr.c =================================================================== --- sys/netinet/tcp_stacks/bbr.c +++ sys/netinet/tcp_stacks/bbr.c @@ -7985,8 +7985,8 @@ acked_amount = min(acked, (int)sbavail(&so->so_snd)); tp->snd_wnd -= acked_amount; mfree = sbcut_locked(&so->so_snd, acked_amount); - /* NB: sowwakeup_locked() does an implicit unlock. */ - sowwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_snd); + tp->t_flags |= TF_WAKESOW; m_freem(mfree); if (SEQ_GT(th->th_ack, tp->snd_una)) { bbr_collapse_rtt(tp, bbr, TCP_REXMTVAL(tp)); @@ -8453,8 +8453,8 @@ appended = #endif sbappendstream_locked(&so->so_rcv, m, 0); - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && appended != mcnt) counter_fo_release(so->so_rcv.sb_shlim, @@ -8696,8 +8696,8 @@ sbappendstream_locked(&so->so_rcv, m, 0); ctf_calc_rwin(so, tp); } - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && mcnt != appended) counter_fo_release(so->so_rcv.sb_shlim, mcnt - appended); @@ -8888,7 +8888,7 @@ &tcp_savetcp, 0); #endif /* Wake up the socket if we have room to write more */ - sowwakeup(so); + tp->t_flags |= TF_WAKESOW; if (tp->snd_una == tp->snd_max) { /* Nothing left outstanding */ bbr_log_progress_event(bbr, tp, ticks, PROGRESS_CLEAR, __LINE__); @@ -11857,8 +11857,10 @@ } retval = bbr_do_segment_nounlock(m, th, so, tp, drop_hdrlen, tlen, iptos, 0, &tv); - if (retval == 0) + if (retval == 0) { INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); + } } /* Index: sys/netinet/tcp_stacks/rack.c =================================================================== --- sys/netinet/tcp_stacks/rack.c +++ sys/netinet/tcp_stacks/rack.c @@ -8453,8 +8453,8 @@ */ ourfinisacked = 1; } - /* NB: sowwakeup_locked() does an implicit unlock. */ - sowwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_snd); + tp->t_flags |= TF_WAKESOW; m_freem(mfree); if (rack->r_ctl.rc_early_recovery == 0) { if (IN_RECOVERY(tp->t_flags)) { @@ -8766,8 +8766,8 @@ appended = #endif sbappendstream_locked(&so->so_rcv, m, 0); - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && appended != mcnt) counter_fo_release(so->so_rcv.sb_shlim, @@ -9015,8 +9015,8 @@ sbappendstream_locked(&so->so_rcv, m, 0); ctf_calc_rwin(so, tp); } - /* NB: sorwakeup_locked() does an implicit unlock. */ - sorwakeup_locked(so); + SOCKBUF_UNLOCK(&so->so_rcv); + tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && mcnt != appended) counter_fo_release(so->so_rcv.sb_shlim, mcnt - appended); @@ -9233,7 +9233,7 @@ rack_timer_cancel(tp, rack, rack->r_ctl.rc_rcvtime, __LINE__); } /* Wake up the socket if we have room to write more */ - sowwakeup(so); + tp->t_flags |= TF_WAKESOW; if (sbavail(&so->so_snd)) { rack->r_wanted_output = 1; } @@ -11290,8 +11290,10 @@ tcp_get_usecs(&tv); } if(rack_do_segment_nounlock(m, th, so, tp, - drop_hdrlen, tlen, iptos, 0, &tv) == 0) + drop_hdrlen, tlen, iptos, 0, &tv) == 0) { INP_WUNLOCK(tp->t_inpcb); + tcp_handle_wakeup(tp, so); + } } struct rack_sendmap * Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -377,7 +377,7 @@ #define TF_NEEDFIN 0x00000800 /* send FIN (implicit state) */ #define TF_NOPUSH 0x00001000 /* don't push */ #define TF_PREVVALID 0x00002000 /* saved values for bad rxmit valid */ -#define TF_UNUSED1 0x00004000 /* unused */ +#define TF_WAKESOR 0x00004000 /* wake up receive socket */ #define TF_GPUTINPROG 0x00008000 /* Goodput measurement in progress */ #define TF_MORETOCOME 0x00010000 /* More data to be appended to sock */ #define TF_LQ_OVERFLOW 0x00020000 /* listen queue overflow */ @@ -389,9 +389,9 @@ #define TF_FORCEDATA 0x00800000 /* force out a byte */ #define TF_TSO 0x01000000 /* TSO enabled on this connection */ #define TF_TOE 0x02000000 /* this connection is offloaded */ -#define TF_UNUSED3 0x04000000 /* unused */ -#define TF_UNUSED4 0x08000000 /* unused */ -#define TF_UNUSED5 0x10000000 /* unused */ +#define TF_WAKESOW 0x04000000 /* wake up send socket */ +#define TF_UNUSED1 0x08000000 /* unused */ +#define TF_UNUSED2 0x10000000 /* unused */ #define TF_CONGRECOVERY 0x20000000 /* congestion recovery mode */ #define TF_WASCRECOVERY 0x40000000 /* was in congestion recovery */ #define TF_FASTOPEN 0x80000000 /* TCP Fast Open indication */ @@ -920,7 +920,8 @@ const void *); char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *, const void *); -int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *, struct mbuf *); +int tcp_reass(struct tcpcb *, struct tcphdr *, tcp_seq *, int *, + struct mbuf *); void tcp_reass_global_init(void); void tcp_reass_flush(struct tcpcb *); void tcp_dooptions(struct tcpopt *, u_char *, int, int); @@ -944,6 +945,7 @@ int tcp_input(struct mbuf **, int *, int); int tcp_autorcvbuf(struct mbuf *, struct tcphdr *, struct socket *, struct tcpcb *, int); +void tcp_handle_wakeup(struct tcpcb *, struct socket *); void tcp_do_segment(struct mbuf *, struct tcphdr *, struct socket *, struct tcpcb *, int, int, uint8_t);