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.
This commit is contained in:
parent
b20f028b5e
commit
06a0da98f2
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue