diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-04-19 01:36:24 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-04-19 01:36:24 +0000 |
commit | d5999429205388468cbefe40ff2fb2ec33ed823f (patch) | |
tree | a173de0f0d9b5ed9d6f58c32858f369ff027f575 /sys/net | |
parent | c52a120a7c05af823db6aacd9fdd74830410deb9 (diff) | |
download | FreeBSD-src-d5999429205388468cbefe40ff2fb2ec33ed823f.zip FreeBSD-src-d5999429205388468cbefe40ff2fb2ec33ed823f.tar.gz |
First pass at softc list locking for if_ppp.c. Many parts of
this patch were submitted by Maurycy Pawlowski-Wieronski. In addition
to Maurycy's change, break out softc tear down from ppp_clone_destroy()
into ppp_destroy() rather than performing a convoluted series of
extraction casts and indirections during tear down at mod unload.
Submitted by: Maurycy Pawlowski-Wieronski <maurycy@fouk.org>
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_ppp.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index c31b262..d7e007e 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -132,8 +132,16 @@ #define PPPNAME "ppp" static MALLOC_DEFINE(M_PPP, PPPNAME, "PPP interface"); + +static struct mtx ppp_softc_list_mtx; static LIST_HEAD(, ppp_softc) ppp_softc_list; +#define PPP_LIST_LOCK_INIT() mtx_init(&ppp_softc_list_mtx, \ + "ppp_softc_list_mtx", NULL, MTX_DEF) +#define PPP_LIST_LOCK_DESTROY() mtx_destroy(&ppp_softc_list_mtx) +#define PPP_LIST_LOCK() mtx_lock(&ppp_softc_list_mtx) +#define PPP_LIST_UNLOCK() mtx_unlock(&ppp_softc_list_mtx) + /* XXX layering violation */ extern void pppasyncattach(void *); extern void pppasyncdetach(void); @@ -217,33 +225,48 @@ ppp_clone_create(struct if_clone *ifc, int unit) mtx_init(&sc->sc_rawq.ifq_mtx, "ppp_rawq", NULL, MTX_DEF); if_attach(&sc->sc_if); bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN); + + PPP_LIST_LOCK(); LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list); + PPP_LIST_UNLOCK(); return (0); } static void -ppp_clone_destroy(struct ifnet *ifp) +ppp_destroy(struct ppp_softc *sc) { - struct ppp_softc *sc; + struct ifnet *ifp; - sc = ifp->if_softc; - - LIST_REMOVE(sc, sc_list); + ifp = &sc->sc_if; bpfdetach(ifp); if_detach(ifp); mtx_destroy(&sc->sc_rawq.ifq_mtx); mtx_destroy(&sc->sc_fastq.ifq_mtx); mtx_destroy(&sc->sc_inq.ifq_mtx); - free(sc, M_PPP); } +static void +ppp_clone_destroy(struct ifnet *ifp) +{ + struct ppp_softc *sc; + + sc = ifp->if_softc; + PPP_LIST_LOCK(); + LIST_REMOVE(sc, sc_list); + PPP_LIST_UNLOCK(); + ppp_destroy(sc); +} + static int ppp_modevent(module_t mod, int type, void *data) -{ +{ + struct ppp_softc *sc; + switch (type) { case MOD_LOAD: + PPP_LIST_LOCK_INIT(); LIST_INIT(&ppp_softc_list); if_clone_attach(&ppp_cloner); @@ -262,9 +285,14 @@ ppp_modevent(module_t mod, int type, void *data) if_clone_detach(&ppp_cloner); - while (!LIST_EMPTY(&ppp_softc_list)) - ppp_clone_destroy( - &LIST_FIRST(&ppp_softc_list)->sc_if); + PPP_LIST_LOCK(); + while ((sc = LIST_FIRST(&ppp_softc_list)) != NULL) { + LIST_REMOVE(sc, sc_list); + PPP_LIST_UNLOCK(); + ppp_destroy(sc); + PPP_LIST_LOCK(); + } + PPP_LIST_LOCK_DESTROY(); break; } return 0; @@ -290,9 +318,11 @@ pppalloc(pid) struct ifnet *ifp; struct ppp_softc *sc; + PPP_LIST_LOCK(); LIST_FOREACH(sc, &ppp_softc_list, sc_list) { if (sc->sc_xfer == pid) { sc->sc_xfer = 0; + PPP_LIST_UNLOCK(); return sc; } } @@ -300,6 +330,7 @@ pppalloc(pid) if (sc->sc_devp == NULL) break; } + PPP_LIST_UNLOCK(); /* Try to clone an interface if we don't have a free one */ if (sc == NULL) { strcpy(tmpname, PPPNAME); @@ -1135,6 +1166,7 @@ pppintr() GIANT_REQUIRED; + PPP_LIST_LOCK(); LIST_FOREACH(sc, &ppp_softc_list, sc_list) { s = splimp(); if (!(sc->sc_flags & SC_TBUSY) @@ -1156,6 +1188,7 @@ pppintr() ppp_inproc(sc, m); } } + PPP_LIST_UNLOCK(); } #ifdef PPP_COMPRESS |