Index: sys/kern/uipc_domain.c =================================================================== --- sys/kern/uipc_domain.c +++ sys/kern/uipc_domain.c @@ -81,6 +81,11 @@ static struct mtx dom_mtx; /* domain list lock */ MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF); +static CK_LIST_HEAD(, domain) fasttimo_domains = + CK_LIST_HEAD_INITIALIZER(fasttimo_domains); +static CK_LIST_HEAD(, domain) slowtimo_domains = + CK_LIST_HEAD_INITIALIZER(slowtimo_domains); + /* * Dummy protocol specific user requests function pointer array. * All functions return EOPNOTSUPP. @@ -175,6 +180,7 @@ struct domain *dp = arg; struct protosw *pr; int flags; + bool has_fasttimo, has_slowtimo; flags = atomic_load_acq_int(&dp->dom_flags); if ((flags & DOMF_SUPPORTED) == 0) @@ -192,8 +198,23 @@ max_datalen = MHLEN - max_hdr; if (max_datalen < 1) panic("%s: max_datalen < 1", __func__); - if (IS_DEFAULT_VNET(curvnet)) + if (IS_DEFAULT_VNET(curvnet)) { atomic_set_rel_int(&dp->dom_flags, DOMF_INITED); + has_fasttimo = has_slowtimo = false; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if (pr->pr_fasttimo != NULL) + has_fasttimo = true; + if (pr->pr_slowtimo != NULL) + has_slowtimo = true; + } + + if (has_fasttimo) + CK_LIST_INSERT_HEAD(&fasttimo_domains, dp, + dom_fasttimos); + if (has_slowtimo) + CK_LIST_INSERT_HEAD(&slowtimo_domains, dp, + dom_slowtimos); + } } #ifdef VIMAGE @@ -340,6 +361,7 @@ VNET_ITERATOR_DECL(vnet_iter); struct domain *dp; struct protosw *pr, *fpr; + bool has_fasttimo, has_slowtimo; /* Sanity checks. */ if (family == 0) @@ -399,6 +421,35 @@ } VNET_LIST_RUNLOCK(); + if (fpr->pr_fasttimo != NULL) { + has_fasttimo = false; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if (pr != fpr && pr->pr_fasttimo != NULL) { + has_fasttimo = true; + break; + } + } + + if (!has_fasttimo) + CK_LIST_INSERT_HEAD(&fasttimo_domains, dp, + dom_fasttimos); + } + + if (fpr->pr_slowtimo != NULL) { + has_slowtimo = false; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if (pr != fpr && pr->pr_slowtimo != NULL) { + has_slowtimo = true; + break; + } + } + + if (!has_slowtimo) + CK_LIST_INSERT_HEAD(&slowtimo_domains, dp, + dom_slowtimos); + } + + return (0); } @@ -411,6 +462,7 @@ { struct domain *dp; struct protosw *pr, *dpr; + bool has_fasttimo, has_slowtimo; /* Sanity checks. */ if (family == 0) @@ -447,6 +499,32 @@ return (EPROTONOSUPPORT); } + if (dpr->pr_fasttimo != NULL) { + has_fasttimo = false; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if (pr != dpr && pr->pr_fasttimo != NULL) { + has_fasttimo = true; + break; + } + } + + if (!has_fasttimo) + CK_LIST_REMOVE(dp, dom_fasttimos); + } + + if (dpr->pr_slowtimo != NULL) { + has_slowtimo = false; + for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { + if (pr != dpr && pr->pr_slowtimo != NULL) { + has_slowtimo = true; + break; + } + } + + if (!has_slowtimo) + CK_LIST_REMOVE(dp, dom_slowtimos); + } + /* De-orbit the protocol and make the slot available again. */ dpr->pr_type = 0; dpr->pr_domain = dp; @@ -488,10 +566,7 @@ struct protosw *pr; NET_EPOCH_ENTER(et); - for (dp = domains; dp; dp = dp->dom_next) { - if ((atomic_load_int(&dp->dom_flags) & DOMF_INITED) == 0) - continue; - atomic_thread_fence_acq(); + CK_LIST_FOREACH(dp, &slowtimo_domains, dom_slowtimos) { for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_slowtimo) (*pr->pr_slowtimo)(); @@ -508,10 +583,7 @@ struct protosw *pr; NET_EPOCH_ENTER(et); - for (dp = domains; dp; dp = dp->dom_next) { - if ((atomic_load_int(&dp->dom_flags) & DOMF_INITED) == 0) - continue; - atomic_thread_fence_acq(); + CK_LIST_FOREACH(dp, &fasttimo_domains, dom_fasttimos) { for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_fasttimo) (*pr->pr_fasttimo)(); Index: sys/sys/domain.h =================================================================== --- sys/sys/domain.h +++ sys/sys/domain.h @@ -35,6 +35,8 @@ #ifndef _SYS_DOMAIN_H_ #define _SYS_DOMAIN_H_ +#include + /* * Structure per communications domain. */ @@ -69,6 +71,10 @@ void *(*dom_ifattach)(struct ifnet *); void (*dom_ifdetach)(struct ifnet *, void *); int (*dom_ifmtu)(struct ifnet *); + + CK_LIST_ENTRY(domain) dom_fasttimos; + CK_LIST_ENTRY(domain) dom_slowtimos; + /* af-dependent data on ifnet */ };