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

Reply via email to