FOREACH_VNET...
Julian Elischer
julian at elischer.org
Sun Sep 7 06:27:04 UTC 2008
trying to replace VNET_ITERLOOP_{BEGIN,END}
looking at an example:
static void
if_slowtimo(void *arg)
{
struct ifnet *ifp;
IFNET_RLOCK();
VNET_ITERLOOP_BEGIN();
INIT_VNET_NET(curvnet);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
(*ifp->if_watchdog)(ifp);
}
VNET_ITERLOOP_END();
IFNET_RUNLOCK();
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
}
If we expand this out we get: (reindented for readability)
static void
if_slowtimo(void *arg)
{
struct ifnet *ifp;
IFNET_RLOCK();
struct vnet *vnet_iter;
VNET_LIST_REF();
LIST_FOREACH(vnet_iter, &vnet_head, vnet_le) {
struct vnet *saved_vnet = curvnet;
curvnet = vnet_iter;
INIT_VNET_NET(curvnet);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
(*ifp->if_watchdog)(ifp);
}
curvnet = saved_vnet;
}
VNET_LIST_UNREF();
IFNET_RUNLOCK();
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
}
now several things leap out here..
(like, declaring variables in mid block)
using different macros to try do this cleanly might lead to:
static void
if_slowtimo(void *arg)
{
struct ifnet *ifp;
VNET_DECL(vnet_iter);
VNET_DECL(saved_vnet);
IFNET_RLOCK();
CURVNET_SAVE(saved_vnet);
VNET_LIST_REF();
FOREACH_VNET(vnet_iter) {
CURVNET_SET_QUIET(vnet_iter);
INIT_VNET_NET(vnet_iter);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
(*ifp->if_watchdog)(ifp);
}
}
CURVNET_SET(vnet_hold);
VNET_LIST_UNREF();
IFNET_RUNLOCK();
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
}
this adds a lot to the original..
I could see:
using bigger macros, getting it back (size wise) to:
static void
if_slowtimo(void *arg)
{
struct ifnet *ifp;
VNET_ITERATOR_DECL(vnet_iter, saved_vnet);
IFNET_RLOCK();
FOREACH_VNET(vnet_iter, saved_vnet) {
VNET_SWITCHTO(vnet_iter);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
(*ifp->if_watchdog)(ifp);
}
}
FOREACH_VNET_COMPLETE(saved_vnet);
IFNET_RUNLOCK();
timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
}
still bigger than the original macros though arguably more "C-like"
anyone have better ways to express this?
Brook, robert, bz? does this look better?
Julian
More information about the freebsd-virtualization
mailing list