--- //depot/projects/netperf_socket/sys/net/if_tun.c 2004/02/28 09:51:12 +++ //depot/user/rwatson/netperf/sys/net/if_tun.c 2004/03/06 20:55:10 @@ -81,6 +81,15 @@ #define TUNDEBUG if (tundebug) if_printf #define TUNNAME "tun" +/* + * All mutable global variables in if_tun are locked using tunmtx, with + * the exception of tundebug, which is used unlocked. Per-softc data + * not yet locked. + * + * XXXRW: tunclones can't be properly locked with the current API. Bug + * phk about this. + */ +static struct mtx tunmtx; static MALLOC_DEFINE(M_TUN, TUNNAME, "Tunnel Interface"); static int tundebug = 0; static struct clonedevs *tunclones; @@ -150,6 +159,7 @@ switch (type) { case MOD_LOAD: + mtx_init(&tunmtx, "tunmtx", NULL, MTX_DEF); tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); if (tag == NULL) return (ENOMEM); @@ -157,19 +167,25 @@ case MOD_UNLOAD: EVENTHANDLER_DEREGISTER(dev_clone, tag); - while (!TAILQ_EMPTY(&tunhead)) { - tp = TAILQ_FIRST(&tunhead); + mtx_lock(&tunmtx); + while ((tp = TAILQ_FIRST(&tunhead)) != NULL) { + TAILQ_REMOVE(&tunhead, tp, tun_list); + mtx_unlock(&tunmtx); + KASSERT((tp->tun_flags & TUN_OPEN) == 0, ("tununits is out of sync - unit %d", tp->tun_if.if_dunit)); - TAILQ_REMOVE(&tunhead, tp, tun_list); + dev = tp->tun_dev; bpfdetach(&tp->tun_if); if_detach(&tp->tun_if); destroy_dev(dev); free(tp, M_TUN); + mtx_lock(&tunmtx); } + mtx_unlock(&tunmtx); clone_cleanup(&tunclones); + mtx_destroy(&tunmtx); break; } return 0; @@ -208,7 +224,9 @@ MALLOC(sc, struct tun_softc *, sizeof(*sc), M_TUN, M_WAITOK | M_ZERO); sc->tun_flags = TUN_INITED; sc->tun_dev = dev; + mtx_lock(&tunmtx); TAILQ_INSERT_TAIL(&tunhead, sc, tun_list); + mtx_unlock(&tunmtx); ifp = &sc->tun_if; if_initname(ifp, TUNNAME, dev2unit(dev));