return;
}
+/*
+ * We need to execute ht_destroy outside of RCU read-side critical
+ * section, so we postpone its execution using call_rcu. It is simpler
+ * than to change the semantic of the many callers of
+ * destroy_channel().
+ */
+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) {
+ lttng_ht_destroy(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)
{
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);
}
/*
if (!chan) {
PERROR("zmalloc ust registry channel");
ret = -ENOMEM;
- goto error;
+ goto error_alloc;
}
chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
lttng_ht_add_unique_u64(session->channels, &chan->node);
rcu_read_unlock();
+ return 0;
+
error:
+ destroy_channel(chan);
+error_alloc:
return ret;
}
{
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;
}
uint32_t uint32_t_alignment,
uint32_t uint64_t_alignment,
uint32_t long_alignment,
- int byte_order)
+ int byte_order,
+ uint32_t major,
+ uint32_t minor)
{
int ret;
struct ust_registry_session *session;
assert(sessionp);
- assert(app);
session = zmalloc(sizeof(*session));
if (!session) {
PERROR("zmalloc ust registry session");
- goto error;
+ goto error_alloc;
}
pthread_mutex_init(&session->lock, NULL);
}
pthread_mutex_lock(&session->lock);
- ret = ust_metadata_session_statedump(session, app);
+ ret = ust_metadata_session_statedump(session, app, major, minor);
pthread_mutex_unlock(&session->lock);
if (ret) {
ERR("Failed to generate session metadata (errno = %d)", ret);
return 0;
error:
+ ust_registry_session_destroy(session);
+error_alloc:
return -1;
}
assert(!ret);
destroy_channel(chan);
}
- lttng_ht_destroy(reg->channels);
rcu_read_unlock();
+ if (reg->channels) {
+ lttng_ht_destroy(reg->channels);
+ }
free(reg->metadata);
}