svn commit: r323954 - head/sys/net
Stephen Hurd
shurd at FreeBSD.org
Sat Sep 23 16:46:32 UTC 2017
Author: shurd
Date: Sat Sep 23 16:46:30 2017
New Revision: 323954
URL: https://svnweb.freebsd.org/changeset/base/323954
Log:
Have ifmp_ring_enqueue() abdicate instead of switch to a consumer
Move TX out of the enqueue() path. As a result, we need
to have ifmp_ring_check_drainage() pick up from the abdicate state.
We also need to either enqueue the TX task, or check drainage
after calling ifmp_ring_enqueue() to ensure it's sent.
This change results in a 30% small packet forwarding improvement.
Reviewed by: olivier, sbruno
Approved by: sbruno (mentor)
Sponsored by: Limelight Networks
Differential Revision: https://reviews.freebsd.org/D12439
Modified:
head/sys/net/iflib.c
head/sys/net/mp_ring.c
Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c Sat Sep 23 13:37:02 2017 (r323953)
+++ head/sys/net/iflib.c Sat Sep 23 16:46:30 2017 (r323954)
@@ -3515,8 +3515,7 @@ _task_fn_tx(void *context)
}
if (txq->ift_db_pending)
ifmp_ring_enqueue(txq->ift_br, (void **)&txq, 1, TX_BATCH_SIZE);
- else
- ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE);
+ ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE);
if (ctx->ifc_flags & IFC_LEGACY)
IFDI_INTR_ENABLE(ctx);
else {
@@ -3718,16 +3717,14 @@ iflib_if_transmit(if_t ifp, struct mbuf *m)
DBG_COUNTER_INC(tx_seen);
err = ifmp_ring_enqueue(txq->ift_br, (void **)&m, 1, TX_BATCH_SIZE);
+ GROUPTASK_ENQUEUE(&txq->ift_task);
if (err) {
- GROUPTASK_ENQUEUE(&txq->ift_task);
/* support forthcoming later */
#ifdef DRIVER_BACKPRESSURE
txq->ift_closed = TRUE;
#endif
ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE);
m_freem(m);
- } else if (TXQ_AVAIL(txq) < (txq->ift_size >> 1)) {
- GROUPTASK_ENQUEUE(&txq->ift_task);
}
return (err);
Modified: head/sys/net/mp_ring.c
==============================================================================
--- head/sys/net/mp_ring.c Sat Sep 23 13:37:02 2017 (r323953)
+++ head/sys/net/mp_ring.c Sat Sep 23 16:46:30 2017 (r323954)
@@ -454,18 +454,12 @@ ifmp_ring_enqueue(struct ifmp_ring *r, void **items, i
do {
os.state = ns.state = r->state;
ns.pidx_tail = pidx_stop;
- ns.flags = BUSY;
+ if (os.flags == IDLE)
+ ns.flags = ABDICATED;
} while (atomic_cmpset_rel_64(&r->state, os.state, ns.state) == 0);
critical_exit();
counter_u64_add(r->enqueues, n);
- /*
- * Turn into a consumer if some other thread isn't active as a consumer
- * already.
- */
- if (os.flags != BUSY)
- drain_ring_lockless(r, ns, os.flags, budget);
-
return (0);
}
#endif
@@ -476,7 +470,9 @@ ifmp_ring_check_drainage(struct ifmp_ring *r, int budg
union ring_state os, ns;
os.state = r->state;
- if (os.flags != STALLED || os.pidx_head != os.pidx_tail || r->can_drain(r) == 0)
+ if ((os.flags != STALLED && os.flags != ABDICATED) || // Only continue in STALLED and ABDICATED
+ os.pidx_head != os.pidx_tail || // Require work to be available
+ (os.flags != ABDICATED && r->can_drain(r) == 0)) // Can either drain, or everyone left
return;
MPASS(os.cidx != os.pidx_tail); /* implied by STALLED */
More information about the svn-src-head
mailing list