Module Name: src
Committed By: thorpej
Date: Sun Sep 4 17:34:44 UTC 2022
Modified Files:
src/sys/net: pktqueue.c
Log Message:
In pktq_flush():
- Run a dummy softint at IPL_SOFTNET on all CPUs to ensure that the
ISR for this pktqueue is not running (addresses a pre-existing XXX).
- Hold the barrier lock around the critical section to ensure that
implicit pktq_barrier() calls via pktq_ifdetach() are held off during
the critical section.
- Ensure the critical section completes in minimal time by not freeing
memory during the critical section; instead, just build a list of the
packets pulled out of the per-CPU queues and free them after the critical
section is over.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/net/pktqueue.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/pktqueue.c
diff -u src/sys/net/pktqueue.c:1.20 src/sys/net/pktqueue.c:1.21
--- src/sys/net/pktqueue.c:1.20 Fri Sep 2 05:50:36 2022
+++ src/sys/net/pktqueue.c Sun Sep 4 17:34:43 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: pktqueue.c,v 1.20 2022/09/02 05:50:36 thorpej Exp $ */
+/* $NetBSD: pktqueue.c,v 1.21 2022/09/04 17:34:43 thorpej Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.20 2022/09/02 05:50:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pktqueue.c,v 1.21 2022/09/04 17:34:43 thorpej Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -540,7 +540,23 @@ pktq_flush(pktqueue_t *pq)
{
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
- struct mbuf *m;
+ struct mbuf *m, *m0 = NULL;
+
+ ASSERT_SLEEPABLE();
+
+ /*
+ * Run a dummy softint at IPL_SOFTNET on all CPUs to ensure that any
+ * already running handler for this pktqueue is no longer running.
+ */
+ xc_barrier(XC_HIGHPRI_IPL(IPL_SOFTNET));
+
+ /*
+ * Acquire the barrier lock. While the caller ensures that
+ * no explcit pktq_barrier() calls will be issued, this holds
+ * off any implicit pktq_barrier() calls that would happen
+ * as the result of pktq_ifdetach().
+ */
+ mutex_enter(&pq->pq_lock);
for (CPU_INFO_FOREACH(cii, ci)) {
struct pcq *q;
@@ -550,14 +566,23 @@ pktq_flush(pktqueue_t *pq)
kpreempt_enable();
/*
- * XXX This can't be right -- if the softint is running
- * then pcq_get isn't safe here.
+ * Pull the packets off the pcq and chain them into
+ * a list to be freed later.
*/
while ((m = pcq_get(q)) != NULL) {
pktq_inc_count(pq, PQCNT_DEQUEUE);
- m_freem(m);
+ m->m_nextpkt = m0;
+ m0 = m;
}
}
+
+ mutex_exit(&pq->pq_lock);
+
+ /* Free the packets now that the critical section is over. */
+ while ((m = m0) != NULL) {
+ m0 = m->m_nextpkt;
+ m_freem(m);
+ }
}
static void