- if (!tcp_delack_enabled)
- return;
-
- for (i=0; i < (tcbinfo.hashsize / 32); i++) {
- if (delack_bitmask[i]) {
- temp_mask = 1;
- for (j=0; j < 32; j++) {
- if (temp_mask & delack_bitmask[i]) {
- head = &tcbinfo.hashbase[elem_base + j];
- for (inp=head->lh_first; inp != 0; inp = inp->inp_hash.le_next) {
- delack_checked++;
- if ((tp = (struct tcpcb *)inp->inp_ppcb) && (tp->t_flags & TF_DELACK)) {
- tp->t_flags &= ~TF_DELACK;
- tp->t_flags |= TF_ACKNOW;
- tcpstat.tcps_delack++;
- (void) tcp_output(tp);
- }
+
+ lck_rw_lock_shared(pcbinfo->mtx);
+
+ /* Walk the list of valid tcpcbs and send ACKS on the ones with DELACK bit set */
+
+ LIST_FOREACH(inp, &tcb, inp_list) {
+
+ so = inp->inp_socket;
+
+ if (so == &tcbinfo.nat_dummy_socket)
+ continue;
+
+ if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING)
+ continue;
+
+ tcp_lock(so, 1, 0);
+
+ if ((in_pcb_checkstate(inp, WNT_RELEASE,1) == WNT_STOPUSING) && so->so_usecount == 1) {
+ tcp_unlock(so, 1, 0);
+ continue;
+ }
+
+ tp = intotcpcb(inp);
+
+ if (tp == 0 || tp->t_state == TCPS_LISTEN) {
+ tcp_unlock(so, 1, 0);
+ continue;
+ }
+
+
+ /* Only run the retransmit timer in that case */
+ if (tp->t_timer[0] && --tp->t_timer[0] == 0) {
+ tp = tcp_timers(tp, 0);
+ if (tp == NULL)
+ goto tpgone;
+ }
+
+ /* TCP pcb timers following the tcp_now clock rate */
+
+ tp->t_rcvtime++;
+ tp->t_starttime++;
+ if (tp->t_rtttime)
+ tp->t_rtttime++;
+
+ /*
+ * Process delayed acks (if enabled) according to PR_FASTHZ, not the retrans timer
+ */
+
+ if (tcp_delack_enabled && (tcp_now % (TCP_RETRANSHZ/PR_FASTHZ)) && tp->t_flags & TF_DELACK) {
+ delack_done++;
+ tp->t_flags &= ~TF_DELACK;
+ tp->t_flags |= TF_ACKNOW;
+ tcpstat.tcps_delack++;
+ tp->t_unacksegs = 0;
+ (void) tcp_output(tp);
+ }
+tpgone:
+ tcp_unlock(so, 1, 0);
+ }
+ KERNEL_DEBUG(DBG_FNC_TCP_FAST | DBG_FUNC_END, delack_done, 0, tcpstat.tcps_delack,0,0);
+ lck_rw_done(pcbinfo->mtx);
+
+ tcp_now++;
+ timeout(tcp_fasttimo, 0, hz/TCP_RETRANSHZ);
+}
+
+void
+tcp_garbage_collect(inp, istimewait)
+ struct inpcb *inp;
+ int istimewait;
+{
+ struct socket *so;
+ struct tcpcb *tp;
+
+
+ if (inp->inp_socket == &tcbinfo.nat_dummy_socket)
+ return;
+
+
+ if (!lck_mtx_try_lock(inp->inpcb_mtx)) /* skip if still in use */
+ return;
+
+ so = inp->inp_socket;
+ tp = intotcpcb(inp);
+
+ if ((so->so_usecount == 1) &&
+ (so->so_flags & SOF_OVERFLOW)) {
+ in_pcbdetach(inp);
+ so->so_usecount--;
+ lck_mtx_unlock(inp->inpcb_mtx);
+ return;
+ }
+ else {
+ if (inp->inp_wantcnt != WNT_STOPUSING) {
+ lck_mtx_unlock(inp->inpcb_mtx);
+ return;