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