! ! Move the increment operation under the lock and split ! the condition variable into two so that we can see on which ! one we are waiting. This might also more properly propagate ! the update of the flowclean_cycles flag. ! ! Suggested by: rwatson ! Sponsored by: ISPsystem ! Reviewed by: julian ! MFC After: ! Index: sys/net/flowtable.c =================================================================== --- sys/net/flowtable.c (revision 203933) +++ sys/net/flowtable.c (working copy) @@ -177,7 +177,8 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone); #define V_flow_ipv4_zone VNET(flow_ipv4_zone) #define V_flow_ipv6_zone VNET(flow_ipv6_zone) -static struct cv flowclean_cv; +static struct cv flowclean_f_cv; +static struct cv flowclean_c_cv; static struct mtx flowclean_lock; static uint32_t flowclean_cycles; @@ -1000,14 +1001,14 @@ flowtable_cleaner(void) } VNET_LIST_RUNLOCK(); - flowclean_cycles++; /* * The 10 second interval between cleaning checks * is arbitrary */ mtx_lock(&flowclean_lock); - cv_broadcast(&flowclean_cv); - cv_timedwait(&flowclean_cv, &flowclean_lock, 10*hz); + flowclean_cycles++; + cv_broadcast(&flowclean_f_cv); + cv_timedwait(&flowclean_c_cv, &flowclean_lock, 10*hz); mtx_unlock(&flowclean_lock); } } @@ -1020,8 +1021,8 @@ flowtable_flush(void *unused __unused) mtx_lock(&flowclean_lock); start = flowclean_cycles; while (start == flowclean_cycles) { - cv_broadcast(&flowclean_cv); - cv_wait(&flowclean_cv, &flowclean_lock); + cv_broadcast(&flowclean_c_cv); + cv_wait(&flowclean_f_cv, &flowclean_lock); } mtx_unlock(&flowclean_lock); } @@ -1052,7 +1053,8 @@ static void flowtable_init(const void *unused __unused) { - cv_init(&flowclean_cv, "flowcleanwait"); + cv_init(&flowclean_c_cv, "c_flowcleanwait"); + cv_init(&flowclean_f_cv, "f_flowcleanwait"); mtx_init(&flowclean_lock, "flowclean lock", NULL, MTX_DEF); EVENTHANDLER_REGISTER(ifnet_departure_event, flowtable_flush, NULL, EVENTHANDLER_PRI_ANY);