By making "destroyed" own a reference, we can treat dp_netdev's ref_cnt like any other in Open vSwitch.
Signed-off-by: Ben Pfaff <b...@nicira.com> --- lib/dpif-netdev.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index b890e4f..62837b0 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -91,8 +91,8 @@ struct dp_netdev_queue { struct dp_netdev { const struct dpif_class *class; char *name; - int open_cnt; - bool destroyed; + struct ovs_refcount ref_cnt; + atomic_flag destroyed; struct dp_netdev_queue queues[N_QUEUES]; struct classifier cls; /* Classifier. */ @@ -224,7 +224,7 @@ create_dpif_netdev(struct dp_netdev *dp) uint16_t netflow_id = hash_string(dp->name, 0); struct dpif_netdev *dpif; - dp->open_cnt++; + ovs_refcount_ref(&dp->ref_cnt); dpif = xmalloc(sizeof *dpif); dpif_init(&dpif->dpif, dp->class, dp->name, netflow_id >> 8, netflow_id); @@ -286,7 +286,8 @@ create_dp_netdev(const char *name, const struct dpif_class *class, dp = xzalloc(sizeof *dp); dp->class = class; dp->name = xstrdup(name); - dp->open_cnt = 0; + ovs_refcount_init(&dp->ref_cnt); + atomic_flag_init(&dp->destroyed); for (i = 0; i < N_QUEUES; i++) { dp->queues[i].head = dp->queues[i].tail = 0; } @@ -371,6 +372,8 @@ dp_netdev_free(struct dp_netdev *dp) hmap_destroy(&dp->flow_table); seq_destroy(dp->port_seq); hmap_destroy(&dp->ports); + atomic_flag_destroy(&dp->destroyed); + ovs_refcount_destroy(&dp->ref_cnt); free(dp->name); free(dp); } @@ -382,8 +385,7 @@ dpif_netdev_close(struct dpif *dpif) ovs_mutex_lock(&dp_netdev_mutex); - ovs_assert(dp->open_cnt > 0); - if (--dp->open_cnt == 0 && dp->destroyed) { + if (ovs_refcount_unref(&dp->ref_cnt) == 1) { shash_find_and_delete(&dp_netdevs, dp->name); dp_netdev_free(dp); } @@ -397,9 +399,12 @@ dpif_netdev_destroy(struct dpif *dpif) { struct dp_netdev *dp = get_dp_netdev(dpif); - ovs_mutex_lock(&dp_netdev_mutex); - dp->destroyed = true; - ovs_mutex_unlock(&dp_netdev_mutex); + if (!atomic_flag_test_and_set(&dp->destroyed)) { + if (ovs_refcount_unref(&dp->ref_cnt) == 1) { + /* Can't happen: 'dpif' still owns a reference to 'dp'. */ + OVS_NOT_REACHED(); + } + } return 0; } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev