Subject: Re: SMP re-entrancy in kernel drivers/"bottom half?"
To: None <jonathan@dsg.stanford.edu>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 12/30/2003 13:34:53
--NextPart-20031230132714-0843500
Content-Type: Text/Plain; charset=us-ascii
> >for your purpose, i think what you need are:
> >- change lowlevel intr handler (Xintr_* in the case of i386) not to
> > take kernel_lock if the driver is marked as mp-safe.
> >- make the driver mp-safe.
> > - change the driver to acquire per-device lock if needed.
> > - change the driver to acquire kernel_lock
> > (or other fine-grained locks) when needed.
for someone interested..
YAMAMOTO Takashi
--NextPart-20031230132714-0843500
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="bkl3.diff"
Index: altq/if_altq.h
===================================================================
--- altq/if_altq.h (revision 1)
+++ altq/if_altq.h (working copy)
@@ -40,6 +40,7 @@ struct altq_pktattr; struct tb_regulator
*/
struct ifaltq {
/* fields compatible with struct ifqueue */
+ struct simplelock ifq_slock;
struct mbuf *ifq_head;
struct mbuf *ifq_tail;
int ifq_len;
Index: netinet/if_arp.c
===================================================================
--- netinet/if_arp.c (revision 335)
+++ netinet/if_arp.c (working copy)
@@ -153,7 +153,7 @@ static void in_arpinput __P((struct mbuf
extern struct ifnet loif[NLOOP];
#endif
LIST_HEAD(, llinfo_arp) llinfo_arp;
-struct ifqueue arpintrq = {0, 0, 0, 50};
+struct ifqueue arpintrq = IFQ_INITIALIZER(50);
int arp_inuse, arp_allocated, arp_intimer;
int arp_maxtries = 5;
int useloopback = 1; /* use loopback interface for local traffic */
@@ -761,7 +761,9 @@ arpintr()
while (arpintrq.ifq_head) {
s = splnet();
+ IFQ_LOCK(&arpintrq);
IF_DEQUEUE(&arpintrq, m);
+ IFQ_UNLOCK(&arpintrq);
splx(s);
if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
panic("arpintr");
Index: netinet/ip_input.c
===================================================================
--- netinet/ip_input.c (revision 476)
+++ netinet/ip_input.c (working copy)
@@ -417,6 +417,7 @@ ip_init()
ip_id = time.tv_sec & 0xfffff;
+ IFQ_INIT(&ipintrq);
ipintrq.ifq_maxlen = ipqmaxlen;
ip_nmbclusters_changed();
@@ -466,7 +467,9 @@ ipintr()
while (1) {
s = splnet();
+ IFQ_LOCK(&ipintrq);
IF_DEQUEUE(&ipintrq, m);
+ IFQ_UNLOCK(&ipintrq);
splx(s);
if (m == 0)
return;
Index: arch/i386/i386/vector.S
===================================================================
--- arch/i386/i386/vector.S (revision 476)
+++ arch/i386/i386/vector.S (working copy)
@@ -234,13 +234,6 @@ IDTVEC(intr_lapic_ltimer)
INTRFASTEXIT
#endif /* NLAPIC > 0 */
-#ifdef MULTIPROCESSOR
-#define LOCK_KERNEL pushl %esp ; call _C_LABEL(x86_intlock) ; addl $4,%esp
-#define UNLOCK_KERNEL pushl %esp ; call _C_LABEL(x86_intunlock) ; addl $4,%esp
-#else
-#define LOCK_KERNEL
-#define UNLOCK_KERNEL
-#endif
#define voidop(num)
@@ -286,7 +279,6 @@ IDTVEC(intr_/**/name/**/num) ;\
sti ;\
incl CPUVAR(IDEPTH) ;\
movl IS_HANDLERS(%ebp),%ebx ;\
- LOCK_KERNEL ;\
6: \
movl IH_LEVEL(%ebx),%edi ;\
cmpl %esi,%edi ;\
@@ -299,14 +291,12 @@ IDTVEC(intr_/**/name/**/num) ;\
testl %ebx,%ebx ;\
jnz 6b ;\
5: \
- UNLOCK_KERNEL ;\
cli ;\
unmask(num) /* unmask it in hardware */ ;\
late_ack(num) ;\
sti ;\
jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
7: \
- UNLOCK_KERNEL ;\
cli ;\
orl $(1 << num),CPUVAR(IPENDING) ;\
level_mask(num) ;\
Index: arch/amd64/amd64/vector.S
===================================================================
--- arch/amd64/amd64/vector.S (revision 294)
+++ arch/amd64/amd64/vector.S (working copy)
@@ -371,13 +371,6 @@ IDTVEC(intr_lapic_ltimer)
INTRFASTEXIT
#endif /* NLAPIC > 0 */
-#ifdef MULTIPROCESSOR
-#define LOCK_KERNEL movq %rsp,%rdi ; call _C_LABEL(x86_intlock)
-#define UNLOCK_KERNEL movq %rsp,%rdi ; call _C_LABEL(x86_intunlock)
-#else
-#define LOCK_KERNEL
-#define UNLOCK_KERNEL
-#endif
#define voidop(num)
@@ -420,7 +413,6 @@ IDTVEC(intr_/**/name/**/num) ;\
sti ;\
incl CPUVAR(IDEPTH) ;\
movq IS_HANDLERS(%r14),%rbx ;\
- LOCK_KERNEL ;\
6: \
movl IH_LEVEL(%rbx),%r12d ;\
cmpl %r13d,%r12d ;\
@@ -432,14 +424,12 @@ IDTVEC(intr_/**/name/**/num) ;\
testq %rbx,%rbx ;\
jnz 6b ;\
5: \
- UNLOCK_KERNEL ;\
cli ;\
unmask(num) /* unmask it in hardware */ ;\
late_ack(num) ;\
sti ;\
jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
7: \
- UNLOCK_KERNEL ;\
cli ;\
orl $(1 << num),CPUVAR(IPENDING) ;\
level_mask(num) ;\
Index: arch/x86/include/intrdefs.h
===================================================================
--- arch/x86/include/intrdefs.h (revision 182)
+++ arch/x86/include/intrdefs.h (working copy)
@@ -3,6 +3,9 @@
#ifndef _i386_INTRDEFS_H
#define _i386_INTRDEFS_H
+#ifdef _KERNEL_OPT
+#include "opt_multiprocessor.h"
+#endif /* _KERNEL_OPT */
/*
* Interrupt priority levels.
*
@@ -23,12 +26,22 @@
#define IPL_NONE 0x0 /* nothing */
#define IPL_SOFTCLOCK 0x4 /* timeouts */
#define IPL_SOFTNET 0x5 /* protocol stacks */
+#ifndef MULTIPROCESSOR
#define IPL_BIO 0x6 /* block I/O */
#define IPL_NET 0x7 /* network */
#define IPL_SOFTSERIAL 0x8 /* serial */
#define IPL_TTY 0x9 /* terminal */
#define IPL_VM 0xa /* memory allocation */
#define IPL_AUDIO 0xb /* audio */
+#else /* MULTIPROCESSOR */
+/* XXX XXX for locking order */
+#define IPL_BIO 0x7 /* block I/O */
+#define IPL_NET 0x7 /* network */
+#define IPL_SOFTSERIAL 0x7 /* serial */
+#define IPL_TTY 0x7 /* terminal */
+#define IPL_VM 0x7 /* memory allocation */
+#define IPL_AUDIO 0x7 /* audio */
+#endif /* MULTIPROCESSOR */
#define IPL_CLOCK 0xc /* clock */
#define IPL_SCHED IPL_CLOCK
#define IPL_HIGH 0xd /* everything */
@@ -36,6 +49,9 @@
#define IPL_IPI 0xe /* inter-processor interrupts */
#define NIPL 16
+#define IH_FLAG_MPSAFE 0x80000000
+#define IPL_FLAGS_MASK (IH_FLAG_MPSAFE)
+
/* Interrupt sharing types. */
#define IST_NONE 0 /* none */
#define IST_PULSE 1 /* pulsed */
Index: arch/x86/include/intr.h
===================================================================
--- arch/x86/include/intr.h (revision 422)
+++ arch/x86/include/intr.h (working copy)
@@ -102,6 +102,9 @@ struct intrhand {
int (*ih_fun)(void *);
void *ih_arg;
int ih_level;
+ int ih_flags;
+ int (*ih_realfun)(void *);
+ void *ih_realarg;
struct intrhand *ih_next;
int ih_pin;
int ih_slot;
Index: arch/x86/x86/intr.c
===================================================================
--- arch/x86/x86/intr.c (revision 425)
+++ arch/x86/x86/intr.c (working copy)
@@ -449,6 +449,25 @@ found:
return 0;
}
+#ifdef MULTIPROCESSOR
+static int intr_biglock_wrapper(void *);
+
+static int
+intr_biglock_wrapper(void *vp)
+{
+ struct intrhand *ih = vp;
+ int ret;
+
+ KERNEL_LOCK(LK_EXCLUSIVE|LK_CANRECURSE);
+
+ ret = (*ih->ih_realfun)(ih->ih_realarg);
+
+ KERNEL_UNLOCK();
+
+ return ret;
+}
+#endif /* MULTIPROCESSOR */
+
void *
intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level,
int (*handler)(void *), void *arg)
@@ -458,6 +477,13 @@ intr_establish(int legacy_irq, struct pi
int slot, error, idt_vec;
struct intrsource *source;
struct intrstub *stubp;
+ int flags;
+
+ flags = level & IPL_FLAGS_MASK; /* XXX */
+ level = level & ~IPL_FLAGS_MASK; /* XXX */
+
+ if (level >= IPL_SCHED) /* XXX */
+ flags |= IH_FLAG_MPSAFE; /* XXX */
#ifdef DIAGNOSTIC
if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15))
@@ -535,13 +561,19 @@ intr_establish(int legacy_irq, struct pi
p = &q->ih_next)
;
- ih->ih_fun = handler;
- ih->ih_arg = arg;
+ ih->ih_fun = ih->ih_realfun = handler;
+ ih->ih_arg = ih->ih_realarg = arg;
ih->ih_next = *p;
ih->ih_level = level;
ih->ih_pin = pin;
ih->ih_cpu = ci;
ih->ih_slot = slot;
+#ifdef MULTIPROCESSOR
+ if ((flags & IH_FLAG_MPSAFE) == 0) {
+ ih->ih_fun = intr_biglock_wrapper;
+ ih->ih_arg = ih;
+ }
+#endif /* MULTIPROCESSOR */
*p = ih;
intr_calculatemasks(ci);
@@ -771,20 +803,6 @@ cpu_intr_init(struct cpu_info *ci)
#ifdef MULTIPROCESSOR
void
-x86_intlock(struct intrframe *iframe)
-{
- if (iframe->if_ppl < IPL_SCHED)
- spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
-}
-
-void
-x86_intunlock(struct intrframe *iframe)
-{
- if (iframe->if_ppl < IPL_SCHED)
- spinlockmgr(&kernel_lock, LK_RELEASE, 0);
-}
-
-void
x86_softintlock(void)
{
spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
Index: dev/pci/if_fxp_pci.c
===================================================================
--- dev/pci/if_fxp_pci.c (revision 323)
+++ dev/pci/if_fxp_pci.c (working copy)
@@ -477,7 +477,8 @@ fxp_pci_attach(parent, self, aux)
return;
}
intrstr = pci_intr_string(pc, ih);
- sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, fxp_intr, sc);
+ sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET | IH_FLAG_MPSAFE,
+ fxp_intr, sc);
if (sc->sc_ih == NULL) {
aprint_error("%s: couldn't establish interrupt",
sc->sc_dev.dv_xname);
Index: dev/ic/i82557.c
===================================================================
--- dev/ic/i82557.c (revision 455)
+++ dev/ic/i82557.c (working copy)
@@ -182,10 +182,13 @@ int fxp_80c24_mediachange(struct ifnet *
void fxp_80c24_mediastatus(struct ifnet *, struct ifmediareq *);
void fxp_start(struct ifnet *);
+void fxp_start_body(struct ifnet *);
int fxp_ioctl(struct ifnet *, u_long, caddr_t);
void fxp_watchdog(struct ifnet *);
int fxp_init(struct ifnet *);
+int fxp_init_body(struct ifnet *);
void fxp_stop(struct ifnet *, int);
+void fxp_stop_body(struct ifnet *, int);
void fxp_txintr(struct fxp_softc *);
void fxp_rxintr(struct fxp_softc *);
@@ -209,6 +212,11 @@ void fxp_load_ucode(struct fxp_softc *);
void fxp_shutdown(void *);
void fxp_power(int, void *);
+#define FXP_LOCK_INIT(sc) simple_lock_init(&(sc)->sc_slock)
+#define FXP_LOCK(sc) simple_lock(&(sc)->sc_slock)
+#define FXP_UNLOCK(sc) simple_unlock(&(sc)->sc_slock)
+#define FXP_LOCK_HELD(sc) simple_lock_held(&(sc)->sc_slock)
+
int fxp_copy_small = 0;
/*
@@ -269,6 +277,7 @@ fxp_attach(struct fxp_softc *sc)
int rseg, i, error;
struct fxp_phytype *fp;
+ FXP_LOCK_INIT(sc);
callout_init(&sc->sc_callout);
/*
@@ -854,12 +863,28 @@ void
fxp_start(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
+
+ /* XXXMP */
+ if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
+ return;
+
+ FXP_LOCK(sc);
+ fxp_start_body(ifp);
+ FXP_UNLOCK(sc);
+}
+
+void
+fxp_start_body(struct ifnet *ifp)
+{
+ struct fxp_softc *sc = ifp->if_softc;
struct mbuf *m0, *m;
struct fxp_txdesc *txd;
struct fxp_txsoft *txs;
bus_dmamap_t dmamap;
int error, lasttx, nexttx, opending, seg;
+ LOCK_ASSERT(FXP_LOCK_HELD(sc));
+
/*
* If we want a re-init, bail out now.
*/
@@ -889,9 +914,12 @@ fxp_start(struct ifnet *ifp)
/*
* Grab a packet off the queue.
*/
+ IFQ_LOCK(&ifp->if_snd);
IFQ_POLL(&ifp->if_snd, m0);
- if (m0 == NULL)
+ if (m0 == NULL) {
+ IFQ_UNLOCK(&ifp->if_snd);
break;
+ }
m = NULL;
if (sc->sc_txpending == FXP_NTXCB) {
@@ -917,6 +945,7 @@ fxp_start(struct ifnet *ifp)
BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
+ IFQ_UNLOCK(&ifp->if_snd);
printf("%s: unable to allocate Tx mbuf\n",
sc->sc_dev.dv_xname);
break;
@@ -925,6 +954,7 @@ fxp_start(struct ifnet *ifp)
if (m0->m_pkthdr.len > MHLEN) {
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
+ IFQ_UNLOCK(&ifp->if_snd);
printf("%s: unable to allocate Tx "
"cluster\n", sc->sc_dev.dv_xname);
m_freem(m);
@@ -936,6 +966,7 @@ fxp_start(struct ifnet *ifp)
error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (error) {
+ IFQ_UNLOCK(&ifp->if_snd);
printf("%s: unable to load Tx buffer, "
"error = %d\n", sc->sc_dev.dv_xname, error);
break;
@@ -943,6 +974,7 @@ fxp_start(struct ifnet *ifp)
}
IFQ_DEQUEUE(&ifp->if_snd, m0);
+ IFQ_UNLOCK(&ifp->if_snd);
csum_flags = m0->m_pkthdr.csum_flags;
if (m != NULL) {
m_freem(m0);
@@ -1077,6 +1109,8 @@ fxp_start(struct ifnet *ifp)
}
}
+int fxp_bkl;
+int fxp_nobkl;
/*
* Process interface interrupts.
*/
@@ -1089,8 +1123,19 @@ fxp_intr(void *arg)
int claimed = 0;
u_int8_t statack;
- if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || sc->sc_enabled == 0)
+#ifdef MULTIPROCESSOR
+ if (kernel_lock.lk_cpu != cpu_number())
+ fxp_bkl++;
+ else
+ fxp_nobkl++;
+#endif
+
+ FXP_LOCK(sc);
+
+ if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0 || sc->sc_enabled == 0) {
+ FXP_UNLOCK(sc);
return (0);
+ }
/*
* If the interface isn't running, don't try to
* service the interrupt.. just ack it and bail.
@@ -1101,6 +1146,7 @@ fxp_intr(void *arg)
claimed = 1;
CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
}
+ FXP_UNLOCK(sc);
return (claimed);
}
@@ -1141,18 +1187,20 @@ fxp_intr(void *arg)
/*
* Try to get more packets going.
*/
- fxp_start(ifp);
+ fxp_start_body(ifp);
if (sc->sc_txpending == 0) {
/*
* If we want a re-init, do that now.
*/
- if (sc->sc_flags & FXPF_WANTINIT)
- (void) fxp_init(ifp);
+ if (sc->sc_flags & FXPF_WANTINIT) {
+ (void) fxp_init_body(ifp);
+ }
}
}
}
+ FXP_UNLOCK(sc);
#if NRND > 0
if (claimed)
rnd_add_uint32(&sc->rnd_source, statack);
@@ -1375,6 +1423,7 @@ fxp_tick(void *arg)
return;
s = splnet();
+ FXP_LOCK(sc);
FXP_CDSTATSSYNC(sc, BUS_DMASYNC_POSTREAD);
@@ -1413,7 +1462,8 @@ fxp_tick(void *arg)
* speed transition).
*/
if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
- (void) fxp_init(ifp);
+ (void) fxp_init_body(ifp);
+ FXP_UNLOCK(sc);
splx(s);
return;
}
@@ -1450,6 +1500,7 @@ fxp_tick(void *arg)
mii_tick(&sc->sc_mii);
}
+ FXP_UNLOCK(sc);
splx(s);
/*
@@ -1486,6 +1537,16 @@ void
fxp_stop(struct ifnet *ifp, int disable)
{
struct fxp_softc *sc = ifp->if_softc;
+
+ FXP_LOCK(sc);
+ fxp_stop_body(ifp, disable);
+ FXP_UNLOCK(sc);
+}
+
+void
+fxp_stop_body(struct ifnet *ifp, int disable)
+{
+ struct fxp_softc *sc = ifp->if_softc;
struct fxp_txsoft *txs;
int i;
@@ -1530,7 +1591,6 @@ fxp_stop(struct ifnet *ifp, int disable)
fxp_rxdrain(sc);
fxp_disable(sc);
}
-
}
/*
@@ -1545,7 +1605,7 @@ fxp_watchdog(struct ifnet *ifp)
struct fxp_softc *sc = ifp->if_softc;
printf("%s: device timeout\n", sc->sc_dev.dv_xname);
- ifp->if_oerrors++;
+ ifp->if_oerrors++; /* XXX MP */
(void) fxp_init(ifp);
}
@@ -1557,6 +1617,19 @@ int
fxp_init(struct ifnet *ifp)
{
struct fxp_softc *sc = ifp->if_softc;
+ int ret;
+
+ FXP_LOCK(sc);
+ ret = fxp_init_body(ifp);
+ FXP_UNLOCK(sc);
+
+ return ret;
+}
+
+int
+fxp_init_body(struct ifnet *ifp)
+{
+ struct fxp_softc *sc = ifp->if_softc;
struct fxp_cb_config *cbp;
struct fxp_cb_ias *cb_ias;
struct fxp_txdesc *txd;
@@ -1569,7 +1642,7 @@ fxp_init(struct ifnet *ifp)
/*
* Cancel any pending I/O
*/
- fxp_stop(ifp, 0);
+ fxp_stop_body(ifp, 0);
/*
* XXX just setting sc_flags to 0 here clears any FXPF_MII
@@ -1868,7 +1941,7 @@ fxp_init(struct ifnet *ifp)
/*
* Attempt to start output on the interface.
*/
- fxp_start(ifp);
+ fxp_start_body(ifp);
out:
if (error) {
@@ -2028,6 +2101,7 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
int s, error;
s = splnet();
+ FXP_LOCK(sc);
switch (cmd) {
case SIOCSIFMEDIA:
@@ -2036,7 +2110,9 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
break;
default:
+ FXP_UNLOCK(sc); /* XXXyamt */
error = ether_ioctl(ifp, cmd, data);
+ FXP_LOCK(sc); /* XXXyamt */
if (error == ENETRESET) {
if (sc->sc_enabled) {
/*
@@ -2047,7 +2123,7 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
sc->sc_flags |= FXPF_WANTINIT;
error = 0;
} else
- error = fxp_init(ifp);
+ error = fxp_init_body(ifp);
} else
error = 0;
}
@@ -2056,8 +2132,9 @@ fxp_ioctl(struct ifnet *ifp, u_long cmd,
/* Try to get more packets going. */
if (sc->sc_enabled)
- fxp_start(ifp);
+ fxp_start_body(ifp);
+ FXP_UNLOCK(sc);
splx(s);
return (error);
}
Index: dev/ic/i82557var.h
===================================================================
--- dev/ic/i82557var.h (revision 168)
+++ dev/ic/i82557var.h (working copy)
@@ -165,6 +165,8 @@ struct fxp_txsoft {
*/
struct fxp_softc {
struct device sc_dev; /* generic device structures */
+ struct simplelock sc_slock;
+ struct simplelock sc_tx_slock;
bus_space_tag_t sc_st; /* bus space tag */
bus_space_handle_t sc_sh; /* bus space handle */
bus_dma_tag_t sc_dmat; /* bus dma tag */
Index: net/if.c
===================================================================
--- net/if.c (revision 462)
+++ net/if.c (working copy)
@@ -435,6 +435,8 @@ if_attach(ifp)
ifindex2ifnet[ifp->if_index] = ifp;
+ IFQ_INIT(&ifp->if_snd);
+
/*
* Link level name is allocated later by a separate call to
* if_alloc_sadl().
Index: net/if.h
===================================================================
--- net/if.h (revision 462)
+++ net/if.h (working copy)
@@ -82,6 +82,7 @@
#include <sys/socket.h>
#include <sys/queue.h>
+#include <sys/lock.h>
#include <net/dlt.h>
#include <net/pfil.h>
@@ -223,6 +224,7 @@ struct if_data14 {
* Structure defining a queue for a network interface.
*/
struct ifqueue {
+ struct simplelock ifq_slock;
struct mbuf *ifq_head;
struct mbuf *ifq_tail;
int ifq_len;
@@ -230,6 +232,9 @@ struct ifqueue {
int ifq_drops;
};
+#define IFQ_INITIALIZER(maxlen) \
+ {SIMPLELOCK_INITIALIZER, NULL, NULL, 0, (maxlen), 0}
+
/*
* Structure defining a queue for a network interface.
*
@@ -628,6 +633,19 @@ do { \
#endif /* DIAGNOSTIC */
#endif /* IFAREF_DEBUG */
+#define IFQ_LOCK_INIT(ifq) simple_lock_init(&(ifq)->ifq_slock)
+#define IFQ_LOCK(ifq) simple_lock(&(ifq)->ifq_slock)
+#define IFQ_UNLOCK(ifq) simple_unlock(&(ifq)->ifq_slock)
+
+#define IFQ_INIT(ifq) \
+do { \
+ IFQ_LOCK_INIT(ifq); \
+ (ifq)->ifq_head = NULL; \
+ (ifq)->ifq_tail = NULL; \
+ (ifq)->ifq_len = 0; \
+ (ifq)->ifq_drops = 0; \
+} while (/*CONSTCOND*/ 0)
+
#ifdef ALTQ
#define ALTQ_DECL(x) x
Index: net/if_pppoe.c
===================================================================
--- net/if_pppoe.c (revision 444)
+++ net/if_pppoe.c (working copy)
@@ -147,8 +147,8 @@ struct pppoe_softc {
};
/* incoming traffic will be queued here */
-struct ifqueue ppoediscinq = { NULL };
-struct ifqueue ppoeinq = { NULL };
+struct ifqueue ppoediscinq;
+struct ifqueue ppoeinq;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
void * pppoe_softintr = NULL;
@@ -212,7 +212,9 @@ pppoeattach(count)
LIST_INIT(&pppoe_softc_list);
if_clone_attach(&pppoe_cloner);
+ IFQ_INIT(&ppoediscinq);
ppoediscinq.ifq_maxlen = IFQ_MAXLEN;
+ IFQ_INIT(&ppoeinq);
ppoeinq.ifq_maxlen = IFQ_MAXLEN;
#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
Index: net/if_ethersubr.c
===================================================================
--- net/if_ethersubr.c (revision 390)
+++ net/if_ethersubr.c (working copy)
@@ -536,7 +536,9 @@ ether_output(struct ifnet *ifp, struct m
* Queue message on interface, and start output if interface
* not yet active.
*/
+ IFQ_LOCK(&ifp->if_snd);
IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error);
+ IFQ_UNLOCK(&ifp->if_snd);
if (error) {
/* mbuf is already freed */
splx(s);
@@ -814,11 +816,13 @@ ether_input(struct ifnet *ifp, struct mb
else
inq = &ppoeinq;
s = splnet();
+ IFQ_LOCK(inq);
if (IF_QFULL(inq)) {
IF_DROP(inq);
m_freem(m);
} else
IF_ENQUEUE(inq, m);
+ IFQ_UNLOCK(inq);
splx(s);
#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
if (!callout_pending(&pppoe_softintr))
@@ -1034,11 +1038,13 @@ ether_input(struct ifnet *ifp, struct mb
}
s = splnet();
+ IFQ_LOCK(inq);
if (IF_QFULL(inq)) {
IF_DROP(inq);
m_freem(m);
} else
IF_ENQUEUE(inq, m);
+ IFQ_UNLOCK(inq);
splx(s);
}
Index: netinet6/ip6_input.c
===================================================================
--- netinet6/ip6_input.c (revision 455)
+++ netinet6/ip6_input.c (working copy)
@@ -167,6 +167,7 @@ ip6_init()
if (pr->pr_domain->dom_family == PF_INET6 &&
pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
ip6_protox[pr->pr_protocol] = pr - inet6sw;
+ IFQ_INIT(&ip6intrq);
ip6intrq.ifq_maxlen = ip6qmaxlen;
nd6_init();
frag6_init();
@@ -205,7 +206,9 @@ ip6intr()
for (;;) {
s = splnet();
+ IFQ_LOCK(&ip6intrq);
IF_DEQUEUE(&ip6intrq, m);
+ IFQ_UNLOCK(&ip6intrq);
splx(s);
if (m == 0)
return;
--NextPart-20031230132714-0843500--