X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-upcall.c;h=8e43e8489248c99c3ba0b4a149a528ff7f8723de;hb=1f8675481e;hp=4ee5bf59c1306b7b25282f1ae0c98eaf3c68e290;hpb=a605908001070c27aa8c755c92cd361a10b46beb;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 4ee5bf59c..8e43e8489 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -223,6 +223,9 @@ static size_t read_upcalls(struct handler *, struct hmap *); static void handle_upcalls(struct handler *, struct hmap *, struct upcall *, size_t n_upcalls); +static void udpif_stop_threads(struct udpif *); +static void udpif_start_threads(struct udpif *, size_t n_handlers, + size_t n_revalidators); static void *udpif_flow_dumper(void *); static void *udpif_upcall_handler(void *); static void *udpif_revalidator(void *); @@ -278,8 +281,7 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif) void udpif_destroy(struct udpif *udpif) { - udpif_set_threads(udpif, 0, 0); - udpif_flush(udpif); + udpif_stop_threads(udpif); list_remove(&udpif->list_node); latch_destroy(&udpif->exit_latch); @@ -289,18 +291,11 @@ udpif_destroy(struct udpif *udpif) free(udpif); } -/* Tells 'udpif' how many threads it should use to handle upcalls. Disables - * all threads if 'n_handlers' and 'n_revalidators' is zero. 'udpif''s - * datapath handle must have packet reception enabled before starting threads. - */ -void -udpif_set_threads(struct udpif *udpif, size_t n_handlers, - size_t n_revalidators) +/* Stops the handler and revalidator threads, must be enclosed in + * ovsrcu quiescent state unless when destroying udpif. */ +static void +udpif_stop_threads(struct udpif *udpif) { - int error; - - ovsrcu_quiesce_start(); - /* Stop the old threads (if any). */ if (udpif->handlers && (udpif->n_handlers != n_handlers || udpif->n_revalidators != n_revalidators)) { @@ -357,15 +352,14 @@ udpif_set_threads(struct udpif *udpif, size_t n_handlers, udpif->handlers = NULL; udpif->n_handlers = 0; } +} - error = dpif_handlers_set(udpif->dpif, n_handlers); - if (error) { - VLOG_ERR("failed to configure handlers in dpif %s: %s", - dpif_name(udpif->dpif), ovs_strerror(error)); - return; - } - - /* Start new threads (if necessary). */ +/* Starts the handler and revalidator threads, must be enclosed in + * ovsrcu quiescent state. */ +static void +udpif_start_threads(struct udpif *udpif, size_t n_handlers, + size_t n_revalidators) +{ if (!udpif->handlers && n_handlers) { size_t i; @@ -397,7 +391,31 @@ udpif_set_threads(struct udpif *udpif, size_t n_handlers, } xpthread_create(&udpif->flow_dumper, NULL, udpif_flow_dumper, udpif); } +} +/* Tells 'udpif' how many threads it should use to handle upcalls. + * 'n_handlers' and 'n_revalidators' can never be zero. 'udpif''s + * datapath handle must have packet reception enabled before starting + * threads. */ +void +udpif_set_threads(struct udpif *udpif, size_t n_handlers, + size_t n_revalidators) +{ + int error; + + ovs_assert(n_handlers && n_revalidators); + + ovsrcu_quiesce_start(); + udpif_stop_threads(udpif); + + error = dpif_handlers_set(udpif->dpif, n_handlers); + if (error) { + VLOG_ERR("failed to configure handlers in dpif %s: %s", + dpif_name(udpif->dpif), ovs_strerror(error)); + return; + } + + udpif_start_threads(udpif, n_handlers, n_revalidators); ovsrcu_quiesce_end(); } @@ -413,8 +431,11 @@ udpif_synchronize(struct udpif *udpif) * its main loop once. */ size_t n_handlers = udpif->n_handlers; size_t n_revalidators = udpif->n_revalidators; - udpif_set_threads(udpif, 0, 0); - udpif_set_threads(udpif, n_handlers, n_revalidators); + + ovsrcu_quiesce_start(); + udpif_stop_threads(udpif); + udpif_start_threads(udpif, n_handlers, n_revalidators); + ovsrcu_quiesce_end(); } /* Notifies 'udpif' that something changed which may render previous @@ -466,9 +487,13 @@ udpif_flush(struct udpif *udpif) n_handlers = udpif->n_handlers; n_revalidators = udpif->n_revalidators; - udpif_set_threads(udpif, 0, 0); + ovsrcu_quiesce_start(); + + udpif_stop_threads(udpif); dpif_flow_flush(udpif->dpif); - udpif_set_threads(udpif, n_handlers, n_revalidators); + udpif_start_threads(udpif, n_handlers, n_revalidators); + + ovsrcu_quiesce_end(); } /* Removes all flows from all datapaths. */