X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-registry.c;h=6e9f0699b334bbeebb00957b0e9a9b0bd486ea1b;hb=dc3b758c34398d9eeee3f9be91a3c24e3b7f0e92;hp=6c483e4b71c3107b614cc6201a53719d88307fd9;hpb=af6142cf6f9ff4657f3c80b4c19df50247a86e91;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 6c483e4b7..6e9f0699b 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -23,6 +23,7 @@ #include #include "ust-registry.h" +#include "utils.h" /* * Hash table match function for event in the registry. @@ -308,12 +309,28 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan, return; } +/* + * We need to execute ht_destroy outside of RCU read-side critical + * section and outside of call_rcu thread, so we postpone its execution + * using ht_cleanup_push. It is simpler than to change the semantic of + * the many callers of delete_ust_app_session(). + */ +static +void destroy_channel_rcu(struct rcu_head *head) +{ + struct ust_registry_channel *chan = + caa_container_of(head, struct ust_registry_channel, rcu_head); + + if (chan->ht) { + ht_cleanup_push(chan->ht); + } + free(chan); +} + /* * Destroy every element of the registry and free the memory. This does NOT * free the registry pointer since it might not have been allocated before so * it's the caller responsability. - * - * This MUST be called within a RCU read side lock section. */ static void destroy_channel(struct ust_registry_channel *chan) { @@ -322,14 +339,14 @@ static void destroy_channel(struct ust_registry_channel *chan) assert(chan); + rcu_read_lock(); /* Destroy all event associated with this registry. */ cds_lfht_for_each_entry(chan->ht->ht, &iter.iter, event, node.node) { /* Delete the node from the ht and free it. */ ust_registry_destroy_event(chan, event); } - lttng_ht_destroy(chan->ht); - - free(chan); + rcu_read_unlock(); + call_rcu(&chan->rcu_head, destroy_channel_rcu); } /* @@ -347,7 +364,7 @@ int ust_registry_channel_add(struct ust_registry_session *session, if (!chan) { PERROR("zmalloc ust registry channel"); ret = -ENOMEM; - goto error; + goto error_alloc; } chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); @@ -376,7 +393,11 @@ int ust_registry_channel_add(struct ust_registry_session *session, lttng_ht_add_unique_u64(session->channels, &chan->node); rcu_read_unlock(); + return 0; + error: + destroy_channel(chan); +error_alloc: return ret; } @@ -418,22 +439,24 @@ void ust_registry_channel_del_free(struct ust_registry_session *session, { struct lttng_ht_iter iter; struct ust_registry_channel *chan; + int ret; assert(session); rcu_read_lock(); chan = ust_registry_channel_find(session, key); if (!chan) { + rcu_read_unlock(); goto end; } iter.iter.node = &chan->node.node; - lttng_ht_del(session->channels, &iter); - + ret = lttng_ht_del(session->channels, &iter); + assert(!ret); + rcu_read_unlock(); destroy_channel(chan); end: - rcu_read_unlock(); return; } @@ -464,7 +487,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, session = zmalloc(sizeof(*session)); if (!session) { PERROR("zmalloc ust registry session"); - goto error; + goto error_alloc; } pthread_mutex_init(&session->lock, NULL); @@ -500,6 +523,8 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, return 0; error: + ust_registry_session_destroy(session); +error_alloc: return -1; } @@ -525,8 +550,10 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) assert(!ret); destroy_channel(chan); } - lttng_ht_destroy(reg->channels); rcu_read_unlock(); + if (reg->channels) { + ht_cleanup_push(reg->channels); + } free(reg->metadata); }