commit 608a53753e0082cd716b918e77cc1d1a66bdc33f Author: Ryota Ozaki Date: Wed Mar 23 14:52:34 2016 +0900 Apply psz list operations to bridge diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 3985a96..b45fd19 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -619,7 +619,7 @@ bridge_lookup_member(struct bridge_softc *sc, const char *name) BRIDGE_PSZ_RENTER(s); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_READER(bif, &sc->sc_iflist, bif_next) { ifp = bif->bif_ifp; if (strcmp(ifp->if_xname, name) == 0) break; @@ -705,7 +705,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif) ifs->if_bridge = NULL; ifs->if_bridgeif = NULL; - LIST_REMOVE(bif, bif_next); + LIST_REMOVE_WRITER(bif, bif_next); BRIDGE_PSZ_PERFORM(sc); @@ -782,7 +782,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) ifs->if_bridge = sc; ifs->if_bridgeif = bif; - LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next); + LIST_INSERT_HEAD_WRITER(&sc->sc_iflist, bif, bif_next); ifs->_if_input = bridge_input; BRIDGE_UNLOCK(sc); @@ -814,7 +814,7 @@ bridge_ioctl_del(struct bridge_softc *sc, void *arg) * Don't use bridge_lookup_member. We want to get a member * with bif_refs == 0. */ - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_WRITER(bif, &sc->sc_iflist, bif_next) { ifs = bif->bif_ifp; if (strcmp(ifs->if_xname, name) == 0) break; @@ -939,7 +939,7 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) retry: BRIDGE_LOCK(sc); count = 0; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) + LIST_FOREACH_WRITER(bif, &sc->sc_iflist, bif_next) count++; BRIDGE_UNLOCK(sc); @@ -959,7 +959,7 @@ retry: BRIDGE_LOCK(sc); i = 0; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) + LIST_FOREACH_WRITER(bif, &sc->sc_iflist, bif_next) i++; if (i > count) { /* @@ -972,7 +972,7 @@ retry: } i = 0; - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_WRITER(bif, &sc->sc_iflist, bif_next) { struct ifbreq *breq = &breqs[i++]; memset(breq, 0, sizeof(*breq)); @@ -1014,7 +1014,7 @@ bridge_ioctl_rts(struct bridge_softc *sc, void *arg) BRIDGE_RT_LOCK(sc); len = bac->ifbac_len; - LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { + LIST_FOREACH_WRITER(brt, &sc->sc_rtlist, brt_list) { if (len < sizeof(bareq)) goto out; memset(&bareq, 0, sizeof(bareq)); @@ -1463,7 +1463,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa, int ss; BRIDGE_PSZ_RENTER(ss); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_READER(bif, &sc->sc_iflist, bif_next) { bif = bridge_try_hold_bif(bif); if (bif == NULL) continue; @@ -1787,7 +1787,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m) int s; BRIDGE_PSZ_RENTER(s); - LIST_FOREACH(_bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_READER(_bif, &sc->sc_iflist, bif_next) { /* It is destined for us. */ if (bridge_ourether(_bif, eh, 0)) { _bif = bridge_try_hold_bif(_bif); @@ -1863,7 +1863,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, bmcast = m->m_flags & (M_BCAST|M_MCAST); BRIDGE_PSZ_RENTER(s); - LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + LIST_FOREACH_READER(bif, &sc->sc_iflist, bif_next) { bif = bridge_try_hold_bif(bif); if (bif == NULL) continue; @@ -2224,7 +2224,7 @@ bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp) struct bridge_rtnode *brt; BRIDGE_RT_LOCK(sc); - LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { + LIST_FOREACH_WRITER(brt, &sc->sc_rtlist, brt_list) { if (brt->brt_ifp == ifp) break; } @@ -2333,7 +2333,7 @@ bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr) int dir; hash = bridge_rthash(sc, addr); - LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { + LIST_FOREACH_READER(brt, &sc->sc_rthash[hash], brt_hash) { dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN); if (dir == 0) return (brt); @@ -2363,7 +2363,7 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) lbrt = LIST_FIRST(&sc->sc_rthash[hash]); if (lbrt == NULL) { - LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash); + LIST_INSERT_HEAD_WRITER(&sc->sc_rthash[hash], brt, brt_hash); goto out; } @@ -2372,11 +2372,11 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) if (dir == 0) return (EEXIST); if (dir > 0) { - LIST_INSERT_BEFORE(lbrt, brt, brt_hash); + LIST_INSERT_BEFORE_WRITER(lbrt, brt, brt_hash); goto out; } if (LIST_NEXT(lbrt, brt_hash) == NULL) { - LIST_INSERT_AFTER(lbrt, brt, brt_hash); + LIST_INSERT_AFTER_WRITER(lbrt, brt, brt_hash); goto out; } lbrt = LIST_NEXT(lbrt, brt_hash); @@ -2387,7 +2387,7 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) #endif out: - LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list); + LIST_INSERT_HEAD_WRITER(&sc->sc_rtlist, brt, brt_list); sc->sc_brtcnt++; return (0); @@ -2404,8 +2404,8 @@ bridge_rtnode_remove(struct bridge_softc *sc, struct bridge_rtnode *brt) KASSERT(BRIDGE_RT_LOCKED(sc)); - LIST_REMOVE(brt, brt_hash); - LIST_REMOVE(brt, brt_list); + LIST_REMOVE_WRITER(brt, brt_hash); + LIST_REMOVE_WRITER(brt, brt_list); sc->sc_brtcnt--; } diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 550ec7a..f9f2c80 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -356,9 +356,66 @@ void bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *, */ #define BRIDGE_PSZ_RENTER(__s) do { __s = pserialize_read_enter(); } while (0) #define BRIDGE_PSZ_REXIT(__s) do { pserialize_read_exit(__s); } while (0) +/* + * XXX tentative; once official API of pserialize for list operations comes, + * should migrate to use it. + */ +#define LIST_INSERT_AFTER_WRITER(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + (elm)->field.le_next = (listelm)->field.le_next; \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ + membar_producer(); \ + if ((elm)->field.le_next != LIST_END(head)) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_BEFORE_WRITER(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + membar_producer(); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_HEAD_WRITER(head, elm, field) do { \ + QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ + (elm)->field.le_next = (head)->lh_first; \ + (elm)->field.le_prev = &(head)->lh_first; \ + membar_producer(); \ + if ((elm)->field.le_next != LIST_END(head)) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define LIST_FOREACH_READER(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var) != LIST_END(head) && (membar_datadep_consumer(), 1); \ + (var) = ((var)->field.le_next)) + +#define LIST_FOREACH_WRITER LIST_FOREACH + +#define LIST_REMOVE_WRITER(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + #else /* BRIDGE_MPSAFE */ + #define BRIDGE_PSZ_RENTER(__s) do { __s = 0; } while (0) #define BRIDGE_PSZ_REXIT(__s) do { (void)__s; } while (0) + +#define LIST_INSERT_AFTER_WRITER LIST_INSERT_AFTER +#define LIST_INSERT_BEFORE_WRITER LIST_INSERT_BEFORE +#define LIST_INSERT_HEAD_WRITER LIST_INSERT_HEAD +#define LIST_FOREACH_READER LIST_FOREACH +#define LIST_FOREACH_WRITER LIST_FOREACH +#define LIST_REMOVE_WRITER LIST_REMOVE + #endif /* BRIDGE_MPSAFE */ #define BRIDGE_PSZ_PERFORM(_sc) if ((_sc)->sc_iflist_psz) \