==== //depot/user/rwatson/netperf/sys/netinet/tcp_subr.c#33 - /home/rwatson/p4/user/rwatson/netperf/sys/netinet/tcp_subr.c ==== @@ -233,6 +233,7 @@ static uma_zone_t tcpcb_zone; static uma_zone_t tcptw_zone; +static struct mtx isn_mtx; struct callout isn_callout; /* @@ -253,6 +254,7 @@ tcp_rexmit_slop = TCPTV_CPU_VAR; INP_INFO_LOCK_INIT(&tcbinfo, "tcp"); + mtx_init(&isn_mtx, "isn_mtx", NULL, MTX_DEF); LIST_INIT(&tcb); tcbinfo.listhead = &tcb; TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", &hashsize); @@ -1292,8 +1294,9 @@ * as reseeding should not be necessary. * * Locking of the global variables isn_secret, isn_last_reseed, isn_offset, - * isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In - * general, this means holding an exclusive (write) lock. + * isn_offset_old, and isn_ctx is performed using isn_mtx. Originally we + * protected it using the TCP pcbinfo lock, but we saw too much contention + * with the pcbinfo lock when running the callout. */ #define ISN_BYTES_PER_SECOND 1048576 @@ -1315,6 +1318,7 @@ INP_INFO_WLOCK_ASSERT(&tcbinfo); INP_LOCK_ASSERT(tp->t_inpcb); + mtx_lock(&isn_mtx); /* Seed if this is the first use, reseed if requested. */ if ((isn_last_reseed == 0) || ((tcp_isn_reseed_interval > 0) && (((u_int)isn_last_reseed + (u_int)tcp_isn_reseed_interval*hz) @@ -1347,6 +1351,7 @@ isn_offset += ISN_STATIC_INCREMENT + (arc4random() & ISN_RANDOM_INCREMENT); new_isn += isn_offset; + mtx_unlock(&isn_mtx); return (new_isn); } @@ -1361,7 +1366,7 @@ { u_int32_t projected_offset; - INP_INFO_WLOCK(&tcbinfo); + mtx_lock(&isn_mtx); projected_offset = isn_offset_old + ISN_BYTES_PER_SECOND / 100; if (projected_offset > isn_offset) @@ -1369,7 +1374,7 @@ isn_offset_old = isn_offset; callout_reset(&isn_callout, hz/100, tcp_isn_tick, NULL); - INP_INFO_WUNLOCK(&tcbinfo); + mtx_unlock(&isn_mtx); } /*