+
+int
+tcp_lock(struct socket *so, int refcount, void *lr)
+{
+ void *lr_saved;
+
+ if (lr == NULL)
+ lr_saved = __builtin_return_address(0);
+ else
+ lr_saved = lr;
+
+ if (so->so_pcb != NULL) {
+ lck_mtx_lock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
+ } else {
+ panic("tcp_lock: so=%p NO PCB! lr=%p lrh= %s\n",
+ so, lr_saved, solockhistory_nr(so));
+ /* NOTREACHED */
+ }
+
+ if (so->so_usecount < 0) {
+ panic("tcp_lock: so=%p so_pcb=%p lr=%p ref=%x lrh= %s\n",
+ so, so->so_pcb, lr_saved, so->so_usecount, solockhistory_nr(so));
+ /* NOTREACHED */
+ }
+ if (refcount)
+ so->so_usecount++;
+ so->lock_lr[so->next_lock_lr] = lr_saved;
+ so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
+ return (0);
+}
+
+int
+tcp_unlock(struct socket *so, int refcount, void *lr)
+{
+ void *lr_saved;
+
+ if (lr == NULL)
+ lr_saved = __builtin_return_address(0);
+ else
+ lr_saved = lr;
+
+#ifdef MORE_TCPLOCK_DEBUG
+ printf("tcp_unlock: so=%p sopcb=%p lock=%p ref=%x lr=%p\n",
+ so, so->so_pcb, ((struct inpcb *)so->so_pcb)->inpcb_mtx,
+ so->so_usecount, lr_saved);
+#endif
+ if (refcount)
+ so->so_usecount--;
+
+ if (so->so_usecount < 0) {
+ panic("tcp_unlock: so=%p usecount=%x lrh= %s\n",
+ so, so->so_usecount, solockhistory_nr(so));
+ /* NOTREACHED */
+ }
+ if (so->so_pcb == NULL) {
+ panic("tcp_unlock: so=%p NO PCB usecount=%x lr=%p lrh= %s\n",
+ so, so->so_usecount, lr_saved, solockhistory_nr(so));
+ /* NOTREACHED */
+ } else {
+ lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx,
+ LCK_MTX_ASSERT_OWNED);
+ so->unlock_lr[so->next_unlock_lr] = lr_saved;
+ so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
+ lck_mtx_unlock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
+ }
+ return (0);
+}
+
+lck_mtx_t *
+tcp_getlock(
+ struct socket *so,
+ __unused int locktype)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ if (so->so_pcb) {
+ if (so->so_usecount < 0)
+ panic("tcp_getlock: so=%p usecount=%x lrh= %s\n",
+ so, so->so_usecount, solockhistory_nr(so));
+ return(inp->inpcb_mtx);
+ }
+ else {
+ panic("tcp_getlock: so=%p NULL so_pcb %s\n",
+ so, solockhistory_nr(so));
+ return (so->so_proto->pr_domain->dom_mtx);
+ }
+}
+
+int32_t
+tcp_sbspace(struct tcpcb *tp)
+{
+ struct sockbuf *sb = &tp->t_inpcb->inp_socket->so_rcv;
+ int32_t space, newspace;
+
+ space = ((int32_t) imin((sb->sb_hiwat - sb->sb_cc),
+ (sb->sb_mbmax - sb->sb_mbcnt)));
+ if (space < 0)
+ space = 0;
+
+#if TRAFFIC_MGT
+ if (tp->t_inpcb->inp_socket->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BG_REGULATE) {
+ if (tcp_background_io_enabled &&
+ tp->t_inpcb->inp_socket->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BG_SUPPRESSED) {
+ tp->t_flags |= TF_RXWIN0SENT;
+ return 0; /* Triggers TCP window closing by responding there is no space */
+ }
+ }
+#endif /* TRAFFIC_MGT */
+
+ /* Avoid inscreasing window size if the current window
+ * is already very low, we could be in "persist" mode and
+ * we could break some apps (see rdar://5409343)
+ */
+
+ if (space < tp->t_maxseg)
+ return space;
+
+ /* Clip window size for slower link */
+
+ if (((tp->t_flags & TF_SLOWLINK) != 0) && slowlink_wsize > 0 )
+ return imin(space, slowlink_wsize);
+
+ /*
+ * Check for ressources constraints before over-ajusting the amount of space we can
+ * advertise in the TCP window size updates.
+ */
+
+ if (sbspace_factor && (tp->t_inpcb->inp_pcbinfo->ipi_count < tcp_sockthreshold) &&
+ (total_mb_cnt / 8) < (mbstat.m_clusters / sbspace_factor)) {
+ if (space < (int32_t)(sb->sb_maxused - sb->sb_cc)) {/* make sure we don't constrain the window if we have enough ressources */
+ space = (int32_t) imax((sb->sb_maxused - sb->sb_cc), tp->rcv_maxbyps);
+ }
+ newspace = (int32_t) imax(((int32_t)sb->sb_maxused - sb->sb_cc), (int32_t)tp->rcv_maxbyps);
+
+ if (newspace > space)
+ space = newspace;
+ }
+ return space;
+}
+/*
+ * Checks TCP Segment Offloading capability for a given connection and interface pair.
+ */
+void
+tcp_set_tso(tp, ifp)
+ struct tcpcb *tp;
+ struct ifnet *ifp;
+{
+#if INET6
+ struct inpcb *inp = tp->t_inpcb;
+ int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
+
+ if (isipv6) {
+ /*
+ * Radar 6921834: Disable TSO IPv6 because there is no support
+ * for TSO & HW checksum in ip6_output yet
+ */
+#if 0
+ if (ifp && ifp->if_hwassist & IFNET_TSO_IPV6) {
+ tp->t_flags |= TF_TSO;
+ if (ifp->if_tso_v6_mtu != 0)
+ tp->tso_max_segment_size = ifp->if_tso_v6_mtu;
+ else
+ tp->tso_max_segment_size = TCP_MAXWIN;
+ } else
+ tp->t_flags &= ~TF_TSO;
+
+#endif
+ } else
+#endif /* INET6 */
+
+ {
+ if (ifp && ifp->if_hwassist & IFNET_TSO_IPV4) {
+ tp->t_flags |= TF_TSO;
+ if (ifp->if_tso_v4_mtu != 0)
+ tp->tso_max_segment_size = ifp->if_tso_v4_mtu;
+ else
+ tp->tso_max_segment_size = TCP_MAXWIN;
+ } else
+ tp->t_flags &= ~TF_TSO;
+ }
+}
+/* DSEP Review Done pl-20051213-v02 @3253,@3391,@3400 */