}
}
+/* Waits for all ongoing upcall translations to complete. This ensures that
+ * there are no transient references to any removed ofprotos (or other
+ * objects). In particular, this should be called after an ofproto is removed
+ * (e.g. via xlate_remove_ofproto()) but before it is destroyed. */
+void
+udpif_synchronize(struct udpif *udpif)
+{
+ /* This is stronger than necessary. It would be sufficient to ensure
+ * (somehow) that each handler and revalidator thread had passed through
+ * 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);
+}
+
/* Notifies 'udpif' that something changed which may render previous
* xlate_actions() results invalid. */
void
-/* Copyright (c) 2013 Nicira, Inc.
+/* Copyright (c) 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
struct udpif *udpif_create(struct dpif_backer *, struct dpif *);
void udpif_set_threads(struct udpif *, size_t n_handlers,
size_t n_revalidators);
+void udpif_synchronize(struct udpif *);
void udpif_destroy(struct udpif *);
void udpif_revalidate(struct udpif *);
void udpif_get_memory_usage(struct udpif *, struct simap *usage);
xlate_remove_ofproto(ofproto);
ovs_rwlock_unlock(&xlate_rwlock);
- /* Discard any flow_miss_batches queued up for 'ofproto', avoiding a
- * use-after-free error. */
- udpif_revalidate(ofproto->backer->udpif);
+ /* Ensure that the upcall processing threads have no remaining references
+ * to the ofproto or anything in it. */
+ udpif_synchronize(ofproto->backer->udpif);
hmap_remove(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node);