Clean-up: modernize pretty_xml.cpp
[lttng-tools.git] / src / bin / lttng-sessiond / ust-app.cpp
index 54cd4dea645b7e1b30edf06822156bdc3781ed37..12250edfdaefb1341736ba5b78c62a53ceba1c8e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 EfficiOS Inc.
  * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
  * SPDX-License-Identifier: GPL-2.0-only
@@ -7,10 +7,48 @@
  */
 
 #define _LGPL_SOURCE
+
+#include "buffer-registry.hpp"
+#include "condition-internal.hpp"
+#include "event-notifier-error-accounting.hpp"
+#include "event.hpp"
+#include "fd-limit.hpp"
+#include "field.hpp"
+#include "health-sessiond.hpp"
+#include "lttng-sessiond.hpp"
+#include "lttng-ust-ctl.hpp"
+#include "lttng-ust-error.hpp"
+#include "notification-thread-commands.hpp"
+#include "session.hpp"
+#include "ust-app.hpp"
+#include "ust-consumer.hpp"
+#include "ust-field-convert.hpp"
+#include "utils.hpp"
+
+#include <common/bytecode/bytecode.hpp>
+#include <common/common.hpp>
+#include <common/compat/errno.hpp>
+#include <common/exception.hpp>
+#include <common/format.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/make-unique.hpp>
+#include <common/pthread-lock.hpp>
+#include <common/sessiond-comm/sessiond-comm.hpp>
+#include <common/urcu.hpp>
+
+#include <lttng/condition/condition.h>
+#include <lttng/condition/event-rule-matches-internal.hpp>
+#include <lttng/condition/event-rule-matches.h>
+#include <lttng/event-rule/event-rule-internal.hpp>
+#include <lttng/event-rule/event-rule.h>
+#include <lttng/event-rule/user-tracepoint.h>
+#include <lttng/trigger/trigger-internal.hpp>
+
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <pthread.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <urcu/compiler.h>
-#include <signal.h>
+#include <vector>
 
-#include <common/bytecode/bytecode.h>
-#include <common/compat/errno.h>
-#include <common/common.h>
-#include <common/hashtable/utils.h>
-#include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/event-rule-internal.h>
-#include <lttng/event-rule/user-tracepoint.h>
-#include <lttng/condition/condition.h>
-#include <lttng/condition/event-rule-matches-internal.h>
-#include <lttng/condition/event-rule-matches.h>
-#include <lttng/trigger/trigger-internal.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "buffer-registry.h"
-#include "condition-internal.h"
-#include "fd-limit.h"
-#include "health-sessiond.h"
-#include "ust-app.h"
-#include "ust-consumer.h"
-#include "lttng-ust-ctl.h"
-#include "lttng-ust-error.h"
-#include "utils.h"
-#include "session.h"
-#include "lttng-sessiond.h"
-#include "notification-thread-commands.h"
-#include "rotate.h"
-#include "event.h"
-#include "event-notifier-error-accounting.h"
-#include "ust-field-utils.h"
+namespace lsu = lttng::sessiond::ust;
+namespace lst = lttng::sessiond::trace;
 
 struct lttng_ht *ust_app_ht;
 struct lttng_ht *ust_app_ht_by_sock;
 struct lttng_ht *ust_app_ht_by_notify_sock;
 
-static
-int ust_app_flush_app_session(struct ust_app *app, struct ust_app_session *ua_sess);
+static int ust_app_flush_app_session(ust_app& app, ust_app_session& ua_sess);
 
 /* Next available channel key. Access under next_channel_key_lock. */
 static uint64_t _next_channel_key;
@@ -66,10 +76,66 @@ static pthread_mutex_t next_channel_key_lock = PTHREAD_MUTEX_INITIALIZER;
 static uint64_t _next_session_id;
 static pthread_mutex_t next_session_id_lock = PTHREAD_MUTEX_INITIALIZER;
 
+namespace {
+
+/*
+ * Return the session registry according to the buffer type of the given
+ * session.
+ *
+ * A registry per UID object MUST exists before calling this function or else
+ * it LTTNG_ASSERT() if not found. RCU read side lock must be acquired.
+ */
+static lsu::registry_session *get_session_registry(const struct ust_app_session *ua_sess)
+{
+       lsu::registry_session *registry = nullptr;
+
+       LTTNG_ASSERT(ua_sess);
+
+       switch (ua_sess->buffer_type) {
+       case LTTNG_BUFFER_PER_PID:
+       {
+               struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id);
+               if (!reg_pid) {
+                       goto error;
+               }
+               registry = reg_pid->registry->reg.ust;
+               break;
+       }
+       case LTTNG_BUFFER_PER_UID:
+       {
+               struct buffer_reg_uid *reg_uid =
+                       buffer_reg_uid_find(ua_sess->tracing_id,
+                                           ua_sess->bits_per_long,
+                                           lttng_credentials_get_uid(&ua_sess->real_credentials));
+               if (!reg_uid) {
+                       goto error;
+               }
+               registry = reg_uid->registry->reg.ust;
+               break;
+       }
+       default:
+               abort();
+       };
+
+error:
+       return registry;
+}
+
+lsu::registry_session::locked_ptr get_locked_session_registry(const struct ust_app_session *ua_sess)
+{
+       auto session = get_session_registry(ua_sess);
+       if (session) {
+               pthread_mutex_lock(&session->_lock);
+       }
+
+       return lsu::registry_session::locked_ptr{ session };
+}
+} /* namespace */
+
 /*
  * Return the incremented value of next_channel_key.
  */
-static uint64_t get_next_channel_key(void)
+static uint64_t get_next_channel_key()
 {
        uint64_t ret;
 
@@ -82,7 +148,7 @@ static uint64_t get_next_channel_key(void)
 /*
  * Return the atomically incremented value of next_session_id.
  */
-static uint64_t get_next_session_id(void)
+static uint64_t get_next_session_id()
 {
        uint64_t ret;
 
@@ -92,9 +158,8 @@ static uint64_t get_next_session_id(void)
        return ret;
 }
 
-static void copy_channel_attr_to_ustctl(
-               struct lttng_ust_ctl_consumer_channel_attr *attr,
-               struct lttng_ust_abi_channel_attr *uattr)
+static void copy_channel_attr_to_ustctl(struct lttng_ust_ctl_consumer_channel_attr *attr,
+                                       struct lttng_ust_abi_channel_attr *uattr)
 {
        /* Copy event attributes since the layout is different. */
        attr->subbuf_size = uattr->subbuf_size;
@@ -116,14 +181,12 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key)
 {
        struct ust_app_event *event;
        const struct ust_app_ht_key *key;
-       int ev_loglevel_value;
 
        LTTNG_ASSERT(node);
        LTTNG_ASSERT(_key);
 
        event = caa_container_of(node, struct ust_app_event, node.node);
        key = (ust_app_ht_key *) _key;
-       ev_loglevel_value = event->attr.loglevel;
 
        /* Match the 4 elements of the key: name, filter, loglevel, exclusions */
 
@@ -133,19 +196,12 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key)
        }
 
        /* Event loglevel. */
-       if (ev_loglevel_value != key->loglevel_type) {
-               if (event->attr.loglevel_type == LTTNG_UST_ABI_LOGLEVEL_ALL
-                               && key->loglevel_type == 0 &&
-                               ev_loglevel_value == -1) {
-                       /*
-                        * Match is accepted. This is because on event creation, the
-                        * loglevel is set to -1 if the event loglevel type is ALL so 0 and
-                        * -1 are accepted for this loglevel type since 0 is the one set by
-                        * the API when receiving an enable event.
-                        */
-               } else {
-                       goto no_match;
-               }
+       if (!loglevels_match(event->attr.loglevel_type,
+                            event->attr.loglevel,
+                            key->loglevel_type,
+                            key->loglevel_value,
+                            LTTNG_UST_ABI_LOGLEVEL_ALL)) {
+               goto no_match;
        }
 
        /* One of the filters is NULL, fail. */
@@ -156,8 +212,7 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key)
        if (key->filter && event->filter) {
                /* Both filters exists, check length followed by the bytecode. */
                if (event->filter->len != key->filter->len ||
-                               memcmp(event->filter->data, key->filter->data,
-                                       event->filter->len) != 0) {
+                   memcmp(event->filter->data, key->filter->data, event->filter->len) != 0) {
                        goto no_match;
                }
        }
@@ -170,13 +225,13 @@ static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key)
        if (key->exclusion && event->exclusion) {
                /* Both exclusions exists, check count followed by the names. */
                if (event->exclusion->count != key->exclusion->count ||
-                               memcmp(event->exclusion->names, key->exclusion->names,
-                                       event->exclusion->count * LTTNG_UST_ABI_SYM_NAME_LEN) != 0) {
+                   memcmp(event->exclusion->names,
+                          key->exclusion->names,
+                          event->exclusion->count * LTTNG_UST_ABI_SYM_NAME_LEN) != 0) {
                        goto no_match;
                }
        }
 
-
        /* Match. */
        return 1;
 
@@ -188,8 +243,7 @@ no_match:
  * Unique add of an ust app event in the given ht. This uses the custom
  * ht_match_ust_app_event match function and the event name as hash.
  */
-static void add_unique_ust_app_event(struct ust_app_channel *ua_chan,
-               struct ust_app_event *event)
+static void add_unique_ust_app_event(struct ust_app_channel *ua_chan, struct ust_app_event *event)
 {
        struct cds_lfht_node *node_ptr;
        struct ust_app_ht_key key;
@@ -202,12 +256,15 @@ static void add_unique_ust_app_event(struct ust_app_channel *ua_chan,
        ht = ua_chan->events;
        key.name = event->attr.name;
        key.filter = event->filter;
-       key.loglevel_type = (lttng_ust_abi_loglevel_type) event->attr.loglevel;
+       key.loglevel_type = (lttng_ust_abi_loglevel_type) event->attr.loglevel_type;
+       key.loglevel_value = event->attr.loglevel;
        key.exclusion = event->exclusion;
 
        node_ptr = cds_lfht_add_unique(ht->ht,
-                       ht->hash_fct(event->node.key, lttng_ht_seed),
-                       ht_match_ust_app_event, &key, &event->node.node);
+                                      ht->hash_fct(event->node.key, lttng_ht_seed),
+                                      ht_match_ust_app_event,
+                                      &key,
+                                      &event->node.node);
        LTTNG_ASSERT(node_ptr == &event->node.node);
 }
 
@@ -219,7 +276,7 @@ static void close_notify_sock_rcu(struct rcu_head *head)
 {
        int ret;
        struct ust_app_notify_sock_obj *obj =
-               caa_container_of(head, struct ust_app_notify_sock_obj, head);
+               lttng::utils::container_of(head, &ust_app_notify_sock_obj::head);
 
        /* Must have a valid fd here. */
        LTTNG_ASSERT(obj->fd >= 0);
@@ -233,60 +290,16 @@ static void close_notify_sock_rcu(struct rcu_head *head)
        free(obj);
 }
 
-/*
- * Return the session registry according to the buffer type of the given
- * session.
- *
- * A registry per UID object MUST exists before calling this function or else
- * it LTTNG_ASSERT() if not found. RCU read side lock must be acquired.
- */
-static struct ust_registry_session *get_session_registry(
-               struct ust_app_session *ua_sess)
-{
-       struct ust_registry_session *registry = NULL;
-
-       LTTNG_ASSERT(ua_sess);
-
-       switch (ua_sess->buffer_type) {
-       case LTTNG_BUFFER_PER_PID:
-       {
-               struct buffer_reg_pid *reg_pid = buffer_reg_pid_find(ua_sess->id);
-               if (!reg_pid) {
-                       goto error;
-               }
-               registry = reg_pid->registry->reg.ust;
-               break;
-       }
-       case LTTNG_BUFFER_PER_UID:
-       {
-               struct buffer_reg_uid *reg_uid = buffer_reg_uid_find(
-                               ua_sess->tracing_id, ua_sess->bits_per_long,
-                               lttng_credentials_get_uid(&ua_sess->real_credentials));
-               if (!reg_uid) {
-                       goto error;
-               }
-               registry = reg_uid->registry->reg.ust;
-               break;
-       }
-       default:
-               abort();
-       };
-
-error:
-       return registry;
-}
-
 /*
  * Delete ust context safely. RCU read lock must be held before calling
  * this function.
  */
-static
-void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx,
-               struct ust_app *app)
+static void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx, struct ust_app *app)
 {
        int ret;
 
        LTTNG_ASSERT(ua_ctx);
+       ASSERT_RCU_READ_LOCKED();
 
        if (ua_ctx->obj) {
                pthread_mutex_lock(&app->sock_lock);
@@ -295,18 +308,28 @@ void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx,
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app release ctx failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app release ctx failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app release ctx obj handle %d failed with ret %d: pid = %d, sock = %d",
-                                               ua_ctx->obj->handle, ret,
-                                               app->pid, app->sock);
+                                   ua_ctx->obj->handle,
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
                free(ua_ctx->obj);
        }
+
+       if (ua_ctx->ctx.ctx == LTTNG_UST_ABI_CONTEXT_APP_CONTEXT) {
+               free(ua_ctx->ctx.u.app_ctx.provider_name);
+               free(ua_ctx->ctx.u.app_ctx.ctx_name);
+       }
+
        free(ua_ctx);
 }
 
@@ -314,31 +337,34 @@ void delete_ust_app_ctx(int sock, struct ust_app_ctx *ua_ctx,
  * Delete ust app event safely. RCU read lock must be held before calling
  * this function.
  */
-static
-void delete_ust_app_event(int sock, struct ust_app_event *ua_event,
-               struct ust_app *app)
+static void delete_ust_app_event(int sock, struct ust_app_event *ua_event, struct ust_app *app)
 {
        int ret;
 
        LTTNG_ASSERT(ua_event);
+       ASSERT_RCU_READ_LOCKED();
 
        free(ua_event->filter);
-       if (ua_event->exclusion != NULL)
+       if (ua_event->exclusion != nullptr)
                free(ua_event->exclusion);
-       if (ua_event->obj != NULL) {
+       if (ua_event->obj != nullptr) {
                pthread_mutex_lock(&app->sock_lock);
                ret = lttng_ust_ctl_release_object(sock, ua_event->obj);
                pthread_mutex_unlock(&app->sock_lock);
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app release event failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app release event failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app release event obj failed with ret %d: pid = %d, sock = %d",
-                                               ret, app->pid, app->sock);
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
                free(ua_event->obj);
@@ -350,11 +376,10 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event,
  * Delayed reclaim of a ust_app_event_notifier_rule object. This MUST be called
  * through a call_rcu().
  */
-static
-void free_ust_app_event_notifier_rule_rcu(struct rcu_head *head)
+static void free_ust_app_event_notifier_rule_rcu(struct rcu_head *head)
 {
-       struct ust_app_event_notifier_rule *obj = caa_container_of(
-                       head, struct ust_app_event_notifier_rule, rcu_head);
+       struct ust_app_event_notifier_rule *obj =
+               lttng::utils::container_of(head, &ust_app_event_notifier_rule::rcu_head);
 
        free(obj);
 }
@@ -362,32 +387,35 @@ void free_ust_app_event_notifier_rule_rcu(struct rcu_head *head)
 /*
  * Delete ust app event notifier rule safely.
  */
-static void delete_ust_app_event_notifier_rule(int sock,
-               struct ust_app_event_notifier_rule *ua_event_notifier_rule,
-               struct ust_app *app)
+static void delete_ust_app_event_notifier_rule(
+       int sock, struct ust_app_event_notifier_rule *ua_event_notifier_rule, struct ust_app *app)
 {
        int ret;
 
        LTTNG_ASSERT(ua_event_notifier_rule);
 
-       if (ua_event_notifier_rule->exclusion != NULL) {
+       if (ua_event_notifier_rule->exclusion != nullptr) {
                free(ua_event_notifier_rule->exclusion);
        }
 
-       if (ua_event_notifier_rule->obj != NULL) {
+       if (ua_event_notifier_rule->obj != nullptr) {
                pthread_mutex_lock(&app->sock_lock);
                ret = lttng_ust_ctl_release_object(sock, ua_event_notifier_rule->obj);
                pthread_mutex_unlock(&app->sock_lock);
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app release event notifier failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app release event notifier failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app release event notifier failed with ret %d: pid = %d, sock = %d",
-                                               ret, app->pid, app->sock);
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
 
@@ -395,8 +423,7 @@ static void delete_ust_app_event_notifier_rule(int sock,
        }
 
        lttng_trigger_put(ua_event_notifier_rule->trigger);
-       call_rcu(&ua_event_notifier_rule->rcu_head,
-                       free_ust_app_event_notifier_rule_rcu);
+       call_rcu(&ua_event_notifier_rule->rcu_head, free_ust_app_event_notifier_rule_rcu);
 }
 
 /*
@@ -404,8 +431,7 @@ static void delete_ust_app_event_notifier_rule(int sock,
  *
  * Return 0 on success or else a negative value.
  */
-static int release_ust_app_stream(int sock, struct ust_app_stream *stream,
-               struct ust_app *app)
+static int release_ust_app_stream(int sock, struct ust_app_stream *stream, struct ust_app *app)
 {
        int ret = 0;
 
@@ -418,13 +444,17 @@ static int release_ust_app_stream(int sock, struct ust_app_stream *stream,
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app release stream failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app release stream failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app release stream obj failed with ret %d: pid = %d, sock = %d",
-                                               ret, app->pid, app->sock);
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
                lttng_fd_put(LTTNG_FD_APPS, 2);
@@ -438,30 +468,22 @@ static int release_ust_app_stream(int sock, struct ust_app_stream *stream,
  * Delete ust app stream safely. RCU read lock must be held before calling
  * this function.
  */
-static
-void delete_ust_app_stream(int sock, struct ust_app_stream *stream,
-               struct ust_app *app)
+static void delete_ust_app_stream(int sock, struct ust_app_stream *stream, struct ust_app *app)
 {
        LTTNG_ASSERT(stream);
+       ASSERT_RCU_READ_LOCKED();
 
        (void) release_ust_app_stream(sock, stream, app);
        free(stream);
 }
 
-/*
- * 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 delete_ust_app_channel_rcu(struct rcu_head *head)
+static void delete_ust_app_channel_rcu(struct rcu_head *head)
 {
        struct ust_app_channel *ua_chan =
-               caa_container_of(head, struct ust_app_channel, rcu_head);
+               lttng::utils::container_of(head, &ust_app_channel::rcu_head);
 
-       ht_cleanup_push(ua_chan->ctx);
-       ht_cleanup_push(ua_chan->events);
+       lttng_ht_destroy(ua_chan->ctx);
+       lttng_ht_destroy(ua_chan->events);
        free(ua_chan);
 }
 
@@ -472,8 +494,7 @@ void delete_ust_app_channel_rcu(struct rcu_head *head)
  *
  * The session list lock must be held by the caller.
  */
-static
-void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
+static void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
 {
        uint64_t discarded = 0, lost = 0;
        struct ltt_session *session;
@@ -483,7 +504,7 @@ void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
                return;
        }
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
        session = session_find_by_id(ua_chan->session->tracing_id);
        if (!session || !session->ust_session) {
                /*
@@ -506,16 +527,17 @@ void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
 
        if (ua_chan->attr.overwrite) {
                consumer_get_lost_packets(ua_chan->session->tracing_id,
-                               ua_chan->key, session->ust_session->consumer,
-                               &lost);
+                                         ua_chan->key,
+                                         session->ust_session->consumer,
+                                         &lost);
        } else {
                consumer_get_discarded_events(ua_chan->session->tracing_id,
-                               ua_chan->key, session->ust_session->consumer,
-                               &discarded);
+                                             ua_chan->key,
+                                             session->ust_session->consumer,
+                                             &discarded);
        }
-       uchan = trace_ust_find_channel_by_name(
-                       session->ust_session->domain_global.channels,
-                       ua_chan->name);
+       uchan = trace_ust_find_channel_by_name(session->ust_session->domain_global.channels,
+                                              ua_chan->name);
        if (!uchan) {
                ERR("Missing UST channel to store discarded counters");
                goto end;
@@ -525,7 +547,6 @@ void save_per_pid_lost_discarded_counters(struct ust_app_channel *ua_chan)
        uchan->per_pid_closed_app_lost += lost;
 
 end:
-       rcu_read_unlock();
        if (session) {
                session_put(session);
        }
@@ -537,29 +558,30 @@ end:
  *
  * The session list lock must be held by the caller.
  */
-static
-void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
-               struct ust_app *app)
+static void delete_ust_app_channel(int sock,
+                                  struct ust_app_channel *ua_chan,
+                                  struct ust_app *app,
+                                  const lsu::registry_session::locked_ptr& locked_registry)
 {
        int ret;
        struct lttng_ht_iter iter;
        struct ust_app_event *ua_event;
        struct ust_app_ctx *ua_ctx;
        struct ust_app_stream *stream, *stmp;
-       struct ust_registry_session *registry;
 
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        DBG3("UST app deleting channel %s", ua_chan->name);
 
        /* Wipe stream */
-       cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) {
+       cds_list_for_each_entry_safe (stream, stmp, &ua_chan->streams.head, list) {
                cds_list_del(&stream->list);
                delete_ust_app_stream(sock, stream, app);
        }
 
        /* Wipe context */
-       cds_lfht_for_each_entry(ua_chan->ctx->ht, &iter.iter, ua_ctx, node.node) {
+       cds_lfht_for_each_entry (ua_chan->ctx->ht, &iter.iter, ua_ctx, node.node) {
                cds_list_del(&ua_ctx->list);
                ret = lttng_ht_del(ua_chan->ctx, &iter);
                LTTNG_ASSERT(!ret);
@@ -567,8 +589,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
        }
 
        /* Wipe events */
-       cds_lfht_for_each_entry(ua_chan->events->ht, &iter.iter, ua_event,
-                       node.node) {
+       cds_lfht_for_each_entry (ua_chan->events->ht, &iter.iter, ua_event, node.node) {
                ret = lttng_ht_del(ua_chan->events, &iter);
                LTTNG_ASSERT(!ret);
                delete_ust_app_event(sock, ua_event, app);
@@ -576,11 +597,14 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
 
        if (ua_chan->session->buffer_type == LTTNG_BUFFER_PER_PID) {
                /* Wipe and free registry from session registry. */
-               registry = get_session_registry(ua_chan->session);
-               if (registry) {
-                       ust_registry_channel_del_free(registry, ua_chan->key,
-                               sock >= 0);
+               if (locked_registry) {
+                       try {
+                               locked_registry->remove_channel(ua_chan->key, sock >= 0);
+                       } catch (const std::exception& ex) {
+                               DBG("Could not find channel for removal: %s", ex.what());
+                       }
                }
+
                /*
                 * A negative socket can be used by the caller when
                 * cleaning-up a ua_chan in an error path. Skip the
@@ -591,7 +615,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
                }
        }
 
-       if (ua_chan->obj != NULL) {
+       if (ua_chan->obj != nullptr) {
                /* Remove channel from application UST object descriptor. */
                iter.iter.node = &ua_chan->ust_objd_node.node;
                ret = lttng_ht_del(app->ust_objd, &iter);
@@ -602,16 +626,20 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan,
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app channel %s release failed. Application is dead: pid = %d, sock = %d",
-                                               ua_chan->name, app->pid,
-                                               app->sock);
+                                    ua_chan->name,
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app channel %s release failed. Communication time out: pid = %d, sock = %d",
-                                               ua_chan->name, app->pid,
-                                               app->sock);
+                                    ua_chan->name,
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app channel %s release failed with ret %d: pid = %d, sock = %d",
-                                               ua_chan->name, ret, app->pid,
-                                               app->sock);
+                                   ua_chan->name,
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
                lttng_fd_put(LTTNG_FD_APPS, 1);
@@ -659,19 +687,21 @@ int ust_app_release_object(struct ust_app *app, struct lttng_ust_abi_object_data
  * but it can be caused by recoverable errors (e.g. the application has
  * terminated concurrently).
  */
-ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
-               struct consumer_socket *socket, int send_zero_data)
+ssize_t ust_app_push_metadata(const lsu::registry_session::locked_ptr& locked_registry,
+                             struct consumer_socket *socket,
+                             int send_zero_data)
 {
        int ret;
-       char *metadata_str = NULL;
+       char *metadata_str = nullptr;
        size_t len, offset, new_metadata_len_sent;
        ssize_t ret_val;
        uint64_t metadata_key, metadata_version;
 
-       LTTNG_ASSERT(registry);
+       LTTNG_ASSERT(locked_registry);
        LTTNG_ASSERT(socket);
+       ASSERT_RCU_READ_LOCKED();
 
-       metadata_key = registry->metadata_key;
+       metadata_key = locked_registry->_metadata_key;
 
        /*
         * Means that no metadata was assigned to the session. This can
@@ -681,13 +711,13 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
                return 0;
        }
 
-       offset = registry->metadata_len_sent;
-       len = registry->metadata_len - registry->metadata_len_sent;
-       new_metadata_len_sent = registry->metadata_len;
-       metadata_version = registry->metadata_version;
+       offset = locked_registry->_metadata_len_sent;
+       len = locked_registry->_metadata_len - locked_registry->_metadata_len_sent;
+       new_metadata_len_sent = locked_registry->_metadata_len;
+       metadata_version = locked_registry->_metadata_version;
        if (len == 0) {
                DBG3("No metadata to push for metadata key %" PRIu64,
-                               registry->metadata_key);
+                    locked_registry->_metadata_key);
                ret_val = len;
                if (send_zero_data) {
                        DBG("No metadata to push");
@@ -697,17 +727,17 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
        }
 
        /* Allocate only what we have to send. */
-       metadata_str = (char *) zmalloc(len);
+       metadata_str = calloc<char>(len);
        if (!metadata_str) {
                PERROR("zmalloc ust app metadata string");
                ret_val = -ENOMEM;
                goto error;
        }
        /* Copy what we haven't sent out. */
-       memcpy(metadata_str, registry->metadata + offset, len);
+       memcpy(metadata_str, locked_registry->_metadata + offset, len);
 
 push_data:
-       pthread_mutex_unlock(&registry->lock);
+       pthread_mutex_unlock(&locked_registry->_lock);
        /*
         * We need to unlock the registry while we push metadata to
         * break a circular dependency between the consumerd metadata
@@ -720,9 +750,9 @@ push_data:
         * daemon. Those push and pull schemes are performed on two
         * different bidirectionnal communication sockets.
         */
-       ret = consumer_push_metadata(socket, metadata_key,
-                       metadata_str, len, offset, metadata_version);
-       pthread_mutex_lock(&registry->lock);
+       ret = consumer_push_metadata(
+               socket, metadata_key, metadata_str, len, offset, metadata_version);
+       pthread_mutex_lock(&locked_registry->_lock);
        if (ret < 0) {
                /*
                 * There is an acceptable race here between the registry
@@ -759,9 +789,8 @@ push_data:
                 * largest metadata_len_sent value of the concurrent
                 * send.
                 */
-               registry->metadata_len_sent =
-                       std::max(registry->metadata_len_sent,
-                               new_metadata_len_sent);
+               locked_registry->_metadata_len_sent =
+                       std::max(locked_registry->_metadata_len_sent, new_metadata_len_sent);
        }
        free(metadata_str);
        return len;
@@ -776,7 +805,7 @@ error:
                 * the metadata cache has been destroyed on the
                 * consumer.
                 */
-               registry->metadata_closed = 1;
+               locked_registry->_metadata_closed = true;
        }
 error_push:
        free(metadata_str);
@@ -797,40 +826,37 @@ error_push:
  * but it can be caused by recoverable errors (e.g. the application has
  * terminated concurrently).
  */
-static int push_metadata(struct ust_registry_session *registry,
-               struct consumer_output *consumer)
+static int push_metadata(const lsu::registry_session::locked_ptr& locked_registry,
+                        struct consumer_output *consumer)
 {
        int ret_val;
        ssize_t ret;
        struct consumer_socket *socket;
 
-       LTTNG_ASSERT(registry);
+       LTTNG_ASSERT(locked_registry);
        LTTNG_ASSERT(consumer);
+       ASSERT_RCU_READ_LOCKED();
 
-       pthread_mutex_lock(&registry->lock);
-       if (registry->metadata_closed) {
+       if (locked_registry->_metadata_closed) {
                ret_val = -EPIPE;
                goto error;
        }
 
        /* Get consumer socket to use to push the metadata.*/
-       socket = consumer_find_socket_by_bitness(registry->bits_per_long,
-                       consumer);
+       socket = consumer_find_socket_by_bitness(locked_registry->abi.bits_per_long, consumer);
        if (!socket) {
                ret_val = -1;
                goto error;
        }
 
-       ret = ust_app_push_metadata(registry, socket, 0);
+       ret = ust_app_push_metadata(locked_registry, socket, 0);
        if (ret < 0) {
                ret_val = ret;
                goto error;
        }
-       pthread_mutex_unlock(&registry->lock);
        return 0;
 
 error:
-       pthread_mutex_unlock(&registry->lock);
        return ret_val;
 }
 
@@ -846,40 +872,18 @@ error:
  *
  * Return 0 on success else a negative value.
  */
-static int close_metadata(struct ust_registry_session *registry,
-               struct consumer_output *consumer)
+static int close_metadata(uint64_t metadata_key,
+                         unsigned int consumer_bitness,
+                         struct consumer_output *consumer)
 {
        int ret;
        struct consumer_socket *socket;
-       uint64_t metadata_key;
-       bool registry_was_already_closed;
+       lttng::urcu::read_lock_guard read_lock_guard;
 
-       LTTNG_ASSERT(registry);
        LTTNG_ASSERT(consumer);
 
-       rcu_read_lock();
-
-       pthread_mutex_lock(&registry->lock);
-       metadata_key = registry->metadata_key;
-       registry_was_already_closed = registry->metadata_closed;
-       if (metadata_key != 0) {
-               /*
-                * Metadata closed. Even on error this means that the consumer
-                * is not responding or not found so either way a second close
-                * should NOT be emit for this registry.
-                */
-               registry->metadata_closed = 1;
-       }
-       pthread_mutex_unlock(&registry->lock);
-
-       if (metadata_key == 0 || registry_was_already_closed) {
-               ret = 0;
-               goto end;
-       }
-
-       /* Get consumer socket to use to push the metadata.*/
-       socket = consumer_find_socket_by_bitness(registry->bits_per_long,
-                       consumer);
+       /* Get consumer socket to use to push the metadata. */
+       socket = consumer_find_socket_by_bitness(consumer_bitness, consumer);
        if (!socket) {
                ret = -1;
                goto end;
@@ -891,23 +895,15 @@ static int close_metadata(struct ust_registry_session *registry,
        }
 
 end:
-       rcu_read_unlock();
        return ret;
 }
 
-/*
- * 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 delete_ust_app_session_rcu(struct rcu_head *head)
+static void delete_ust_app_session_rcu(struct rcu_head *head)
 {
        struct ust_app_session *ua_sess =
-               caa_container_of(head, struct ust_app_session, rcu_head);
+               lttng::utils::container_of(head, &ust_app_session::rcu_head);
 
-       ht_cleanup_push(ua_sess->channels);
+       lttng_ht_destroy(ua_sess->channels);
        free(ua_sess);
 }
 
@@ -917,28 +913,34 @@ void delete_ust_app_session_rcu(struct rcu_head *head)
  *
  * The session list lock must be held by the caller.
  */
-static
-void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
-               struct ust_app *app)
+static void delete_ust_app_session(int sock, struct ust_app_session *ua_sess, struct ust_app *app)
 {
        int ret;
        struct lttng_ht_iter iter;
        struct ust_app_channel *ua_chan;
-       struct ust_registry_session *registry;
 
        LTTNG_ASSERT(ua_sess);
+       ASSERT_RCU_READ_LOCKED();
 
        pthread_mutex_lock(&ua_sess->lock);
 
        LTTNG_ASSERT(!ua_sess->deleted);
        ua_sess->deleted = true;
 
-       registry = get_session_registry(ua_sess);
+       auto locked_registry = get_locked_session_registry(ua_sess);
        /* Registry can be null on error path during initialization. */
-       if (registry) {
+       if (locked_registry) {
                /* Push metadata for application before freeing the application. */
-               (void) push_metadata(registry, ua_sess->consumer);
+               (void) push_metadata(locked_registry, ua_sess->consumer);
+       }
+
+       cds_lfht_for_each_entry (ua_sess->channels->ht, &iter.iter, ua_chan, node.node) {
+               ret = lttng_ht_del(ua_sess->channels, &iter);
+               LTTNG_ASSERT(!ret);
+               delete_ust_app_channel(sock, ua_chan, app, locked_registry);
+       }
 
+       if (locked_registry) {
                /*
                 * Don't ask to close metadata for global per UID buffers. Close
                 * metadata only on destroy trace session in this case. Also, the
@@ -946,16 +948,17 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
                 * close so don't send a close command if closed.
                 */
                if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) {
-                       /* And ask to close it for this session registry. */
-                       (void) close_metadata(registry, ua_sess->consumer);
-               }
-       }
+                       const auto metadata_key = locked_registry->_metadata_key;
+                       const auto consumer_bitness = locked_registry->abi.bits_per_long;
 
-       cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan,
-                       node.node) {
-               ret = lttng_ht_del(ua_sess->channels, &iter);
-               LTTNG_ASSERT(!ret);
-               delete_ust_app_channel(sock, ua_chan, app);
+                       if (!locked_registry->_metadata_closed && metadata_key != 0) {
+                               locked_registry->_metadata_closed = true;
+                       }
+
+                       /* Release lock before communication, see comments in close_metadata(). */
+                       locked_registry.reset();
+                       (void) close_metadata(metadata_key, consumer_bitness, ua_sess->consumer);
+               }
        }
 
        /* In case of per PID, the registry is kept in the session. */
@@ -978,13 +981,17 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app release session handle failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app release session handle failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                    app->pid,
+                                    app->sock);
                        } else {
                                ERR("UST app release session handle failed with ret %d: pid = %d, sock = %d",
-                                               ret, app->pid, app->sock);
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                }
 
@@ -1004,11 +1011,8 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess,
 /*
  * Delete a traceable application structure from the global list. Never call
  * this function outside of a call_rcu call.
- *
- * RCU read side lock should _NOT_ be held when calling this function.
  */
-static
-void delete_ust_app(struct ust_app *app)
+static void delete_ust_app(struct ust_app *app)
 {
        int ret, sock;
        struct ust_app_session *ua_sess, *tmp_ua_sess;
@@ -1026,31 +1030,31 @@ void delete_ust_app(struct ust_app *app)
        app->sock = -1;
 
        /* Wipe sessions */
-       cds_list_for_each_entry_safe(ua_sess, tmp_ua_sess, &app->teardown_head,
-                       teardown_node) {
+       cds_list_for_each_entry_safe (ua_sess, tmp_ua_sess, &app->teardown_head, teardown_node) {
                /* Free every object in the session and the session. */
-               rcu_read_lock();
+               lttng::urcu::read_lock_guard read_lock;
                delete_ust_app_session(sock, ua_sess, app);
-               rcu_read_unlock();
        }
 
        /* Remove the event notifier rules associated with this app. */
-       rcu_read_lock();
-       cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
-                       &iter.iter, event_notifier_rule, node.node) {
-               ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &iter);
-               LTTNG_ASSERT(!ret);
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-               delete_ust_app_event_notifier_rule(
-                               app->sock, event_notifier_rule, app);
-       }
+               cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
+                                        &iter.iter,
+                                        event_notifier_rule,
+                                        node.node) {
+                       ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &iter);
+                       LTTNG_ASSERT(!ret);
 
-       rcu_read_unlock();
+                       delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app);
+               }
+       }
 
-       ht_cleanup_push(app->sessions);
-       ht_cleanup_push(app->ust_sessions_objd);
-       ht_cleanup_push(app->ust_objd);
-       ht_cleanup_push(app->token_to_event_notifier_rule_ht);
+       lttng_ht_destroy(app->sessions);
+       lttng_ht_destroy(app->ust_sessions_objd);
+       lttng_ht_destroy(app->ust_objd);
+       lttng_ht_destroy(app->token_to_event_notifier_rule_ht);
 
        /*
         * This could be NULL if the event notifier setup failed (e.g the app
@@ -1060,12 +1064,11 @@ void delete_ust_app(struct ust_app *app)
                enum lttng_error_code ret_code;
                enum event_notifier_error_accounting_status status;
 
-               const int event_notifier_read_fd = lttng_pipe_get_readfd(
-                               app->event_notifier_group.event_pipe);
+               const int event_notifier_read_fd =
+                       lttng_pipe_get_readfd(app->event_notifier_group.event_pipe);
 
                ret_code = notification_thread_command_remove_tracer_event_source(
-                               the_notification_thread_handle,
-                               event_notifier_read_fd);
+                       the_notification_thread_handle, event_notifier_read_fd);
                if (ret_code != LTTNG_OK) {
                        ERR("Failed to remove application tracer event source from notification thread");
                }
@@ -1079,8 +1082,8 @@ void delete_ust_app(struct ust_app *app)
                free(app->event_notifier_group.object);
        }
 
-       event_notifier_write_fd_is_open = lttng_pipe_is_write_open(
-                       app->event_notifier_group.event_pipe);
+       event_notifier_write_fd_is_open =
+               lttng_pipe_is_write_open(app->event_notifier_group.event_pipe);
        lttng_pipe_destroy(app->event_notifier_group.event_pipe);
        /*
         * Release the file descriptors reserved for the event notifier pipe.
@@ -1117,13 +1120,11 @@ void delete_ust_app(struct ust_app *app)
 /*
  * URCU intermediate call to delete an UST app.
  */
-static
-void delete_ust_app_rcu(struct rcu_head *head)
+static void delete_ust_app_rcu(struct rcu_head *head)
 {
        struct lttng_ht_node_ulong *node =
-               caa_container_of(head, struct lttng_ht_node_ulong, head);
-       struct ust_app *app =
-               caa_container_of(node, struct ust_app, pid_n);
+               lttng::utils::container_of(head, &lttng_ht_node_ulong::head);
+       struct ust_app *app = lttng::utils::container_of(node, &ust_app::pid_n);
 
        DBG3("Call RCU deleting app PID %d", app->pid);
        delete_ust_app(app);
@@ -1135,8 +1136,7 @@ void delete_ust_app_rcu(struct rcu_head *head)
  *
  * The session list lock must be held by the caller.
  */
-static void destroy_app_session(struct ust_app *app,
-               struct ust_app_session *ua_sess)
+static void destroy_app_session(struct ust_app *app, struct ust_app_session *ua_sess)
 {
        int ret;
        struct lttng_ht_iter iter;
@@ -1161,14 +1161,13 @@ end:
 /*
  * Alloc new UST app session.
  */
-static
-struct ust_app_session *alloc_ust_app_session(void)
+static struct ust_app_session *alloc_ust_app_session()
 {
        struct ust_app_session *ua_sess;
 
        /* Init most of the default value by allocating and zeroing */
-       ua_sess = (ust_app_session *) zmalloc(sizeof(struct ust_app_session));
-       if (ua_sess == NULL) {
+       ua_sess = zmalloc<ust_app_session>();
+       if (ua_sess == nullptr) {
                PERROR("malloc");
                goto error_free;
        }
@@ -1176,27 +1175,26 @@ struct ust_app_session *alloc_ust_app_session(void)
        ua_sess->handle = -1;
        ua_sess->channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
        ua_sess->metadata_attr.type = LTTNG_UST_ABI_CHAN_METADATA;
-       pthread_mutex_init(&ua_sess->lock, NULL);
+       pthread_mutex_init(&ua_sess->lock, nullptr);
 
        return ua_sess;
 
 error_free:
-       return NULL;
+       return nullptr;
 }
 
 /*
  * Alloc new UST app channel.
  */
-static
-struct ust_app_channel *alloc_ust_app_channel(const char *name,
-               struct ust_app_session *ua_sess,
-               struct lttng_ust_abi_channel_attr *attr)
+static struct ust_app_channel *alloc_ust_app_channel(const char *name,
+                                                    struct ust_app_session *ua_sess,
+                                                    struct lttng_ust_abi_channel_attr *attr)
 {
        struct ust_app_channel *ua_chan;
 
        /* Init most of the default value by allocating and zeroing */
-       ua_chan = (ust_app_channel *) zmalloc(sizeof(struct ust_app_channel));
-       if (ua_chan == NULL) {
+       ua_chan = zmalloc<ust_app_channel>();
+       if (ua_chan == nullptr) {
                PERROR("malloc");
                goto error;
        }
@@ -1205,7 +1203,7 @@ struct ust_app_channel *alloc_ust_app_channel(const char *name,
        strncpy(ua_chan->name, name, sizeof(ua_chan->name));
        ua_chan->name[sizeof(ua_chan->name) - 1] = '\0';
 
-       ua_chan->enabled = 1;
+       ua_chan->enabled = true;
        ua_chan->handle = -1;
        ua_chan->session = ua_sess;
        ua_chan->key = get_next_channel_key();
@@ -1235,7 +1233,7 @@ struct ust_app_channel *alloc_ust_app_channel(const char *name,
        return ua_chan;
 
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -1243,12 +1241,12 @@ error:
  *
  * Return newly allocated stream pointer or NULL on error.
  */
-struct ust_app_stream *ust_app_alloc_stream(void)
+struct ust_app_stream *ust_app_alloc_stream()
 {
-       struct ust_app_stream *stream = NULL;
+       struct ust_app_stream *stream = nullptr;
 
-       stream = (ust_app_stream *) zmalloc(sizeof(*stream));
-       if (stream == NULL) {
+       stream = zmalloc<ust_app_stream>();
+       if (stream == nullptr) {
                PERROR("zmalloc ust app stream");
                goto error;
        }
@@ -1263,20 +1261,18 @@ error:
 /*
  * Alloc new UST app event.
  */
-static
-struct ust_app_event *alloc_ust_app_event(char *name,
-               struct lttng_ust_abi_event *attr)
+static struct ust_app_event *alloc_ust_app_event(char *name, struct lttng_ust_abi_event *attr)
 {
        struct ust_app_event *ua_event;
 
        /* Init most of the default value by allocating and zeroing */
-       ua_event = (ust_app_event *) zmalloc(sizeof(struct ust_app_event));
-       if (ua_event == NULL) {
+       ua_event = zmalloc<ust_app_event>();
+       if (ua_event == nullptr) {
                PERROR("Failed to allocate ust_app_event structure");
                goto error;
        }
 
-       ua_event->enabled = 1;
+       ua_event->enabled = true;
        strncpy(ua_event->name, name, sizeof(ua_event->name));
        ua_event->name[sizeof(ua_event->name) - 1] = '\0';
        lttng_ht_node_init_str(&ua_event->node, ua_event->name);
@@ -1291,52 +1287,49 @@ struct ust_app_event *alloc_ust_app_event(char *name,
        return ua_event;
 
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
  * Allocate a new UST app event notifier rule.
  */
-static struct ust_app_event_notifier_rule *alloc_ust_app_event_notifier_rule(
-               struct lttng_trigger *trigger)
+static struct ust_app_event_notifier_rule *
+alloc_ust_app_event_notifier_rule(struct lttng_trigger *trigger)
 {
-       enum lttng_event_rule_generate_exclusions_status
-                       generate_exclusion_status;
+       enum lttng_event_rule_generate_exclusions_status generate_exclusion_status;
        enum lttng_condition_status cond_status;
        struct ust_app_event_notifier_rule *ua_event_notifier_rule;
-       struct lttng_condition *condition = NULL;
-       const struct lttng_event_rule *event_rule = NULL;
+       struct lttng_condition *condition = nullptr;
+       const struct lttng_event_rule *event_rule = nullptr;
 
-       ua_event_notifier_rule = (ust_app_event_notifier_rule *) zmalloc(sizeof(struct ust_app_event_notifier_rule));
-       if (ua_event_notifier_rule == NULL) {
+       ua_event_notifier_rule = zmalloc<ust_app_event_notifier_rule>();
+       if (ua_event_notifier_rule == nullptr) {
                PERROR("Failed to allocate ust_app_event_notifier_rule structure");
                goto error;
        }
 
-       ua_event_notifier_rule->enabled = 1;
+       ua_event_notifier_rule->enabled = true;
        ua_event_notifier_rule->token = lttng_trigger_get_tracer_token(trigger);
-       lttng_ht_node_init_u64(&ua_event_notifier_rule->node,
-                       ua_event_notifier_rule->token);
+       lttng_ht_node_init_u64(&ua_event_notifier_rule->node, ua_event_notifier_rule->token);
 
        condition = lttng_trigger_get_condition(trigger);
        LTTNG_ASSERT(condition);
        LTTNG_ASSERT(lttng_condition_get_type(condition) ==
-                       LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
+                    LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
 
-       cond_status = lttng_condition_event_rule_matches_get_rule(
-                       condition, &event_rule);
+       cond_status = lttng_condition_event_rule_matches_get_rule(condition, &event_rule);
        LTTNG_ASSERT(cond_status == LTTNG_CONDITION_STATUS_OK);
        LTTNG_ASSERT(event_rule);
 
        ua_event_notifier_rule->error_counter_index =
-                       lttng_condition_event_rule_matches_get_error_counter_index(condition);
+               lttng_condition_event_rule_matches_get_error_counter_index(condition);
        /* Acquire the event notifier's reference to the trigger. */
        lttng_trigger_get(trigger);
 
        ua_event_notifier_rule->trigger = trigger;
        ua_event_notifier_rule->filter = lttng_event_rule_get_filter_bytecode(event_rule);
        generate_exclusion_status = lttng_event_rule_generate_exclusions(
-                       event_rule, &ua_event_notifier_rule->exclusion);
+               event_rule, &ua_event_notifier_rule->exclusion);
        switch (generate_exclusion_status) {
        case LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK:
        case LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE:
@@ -1348,7 +1341,7 @@ static struct ust_app_event_notifier_rule *alloc_ust_app_event_notifier_rule(
        }
 
        DBG3("UST app event notifier rule allocated: token = %" PRIu64,
-                       ua_event_notifier_rule->token);
+            ua_event_notifier_rule->token);
 
        return ua_event_notifier_rule;
 
@@ -1356,19 +1349,18 @@ error_put_trigger:
        lttng_trigger_put(trigger);
 error:
        free(ua_event_notifier_rule);
-       return NULL;
+       return nullptr;
 }
 
 /*
  * Alloc new UST app context.
  */
-static
-struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context_attr *uctx)
+static struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context_attr *uctx)
 {
        struct ust_app_ctx *ua_ctx;
 
-       ua_ctx = (ust_app_ctx *) zmalloc(sizeof(struct ust_app_ctx));
-       if (ua_ctx == NULL) {
+       ua_ctx = zmalloc<ust_app_ctx>();
+       if (ua_ctx == nullptr) {
                goto error;
        }
 
@@ -1377,7 +1369,7 @@ struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context_attr *uctx)
        if (uctx) {
                memcpy(&ua_ctx->ctx, uctx, sizeof(ua_ctx->ctx));
                if (uctx->ctx == LTTNG_UST_ABI_CONTEXT_APP_CONTEXT) {
-                       char *provider_name = NULL, *ctx_name = NULL;
+                       char *provider_name = nullptr, *ctx_name = nullptr;
 
                        provider_name = strdup(uctx->u.app_ctx.provider_name);
                        ctx_name = strdup(uctx->u.app_ctx.ctx_name);
@@ -1396,7 +1388,7 @@ struct ust_app_ctx *alloc_ust_app_ctx(struct lttng_ust_context_attr *uctx)
        return ua_ctx;
 error:
        free(ua_ctx);
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -1404,20 +1396,21 @@ error:
  *
  * Return allocated filter or NULL on error.
  */
-static struct lttng_ust_abi_filter_bytecode *create_ust_filter_bytecode_from_bytecode(
-               const struct lttng_bytecode *orig_f)
+static struct lttng_ust_abi_filter_bytecode *
+create_ust_filter_bytecode_from_bytecode(const struct lttng_bytecode *orig_f)
 {
-       struct lttng_ust_abi_filter_bytecode *filter = NULL;
+       struct lttng_ust_abi_filter_bytecode *filter = nullptr;
 
        /* Copy filter bytecode. */
-       filter = (lttng_ust_abi_filter_bytecode *) zmalloc(sizeof(*filter) + orig_f->len);
+       filter = zmalloc<lttng_ust_abi_filter_bytecode>(sizeof(*filter) + orig_f->len);
        if (!filter) {
-               PERROR("Failed to allocate lttng_ust_filter_bytecode: bytecode len = %" PRIu32 " bytes", orig_f->len);
+               PERROR("Failed to allocate lttng_ust_filter_bytecode: bytecode len = %" PRIu32
+                      " bytes",
+                      orig_f->len);
                goto error;
        }
 
-       LTTNG_ASSERT(sizeof(struct lttng_bytecode) ==
-                       sizeof(struct lttng_ust_abi_filter_bytecode));
+       LTTNG_ASSERT(sizeof(struct lttng_bytecode) == sizeof(struct lttng_ust_abi_filter_bytecode));
        memcpy(filter, orig_f, sizeof(*filter) + orig_f->len);
 error:
        return filter;
@@ -1431,17 +1424,19 @@ error:
 static struct lttng_ust_abi_capture_bytecode *
 create_ust_capture_bytecode_from_bytecode(const struct lttng_bytecode *orig_f)
 {
-       struct lttng_ust_abi_capture_bytecode *capture = NULL;
+       struct lttng_ust_abi_capture_bytecode *capture = nullptr;
 
        /* Copy capture bytecode. */
-       capture = (lttng_ust_abi_capture_bytecode *) zmalloc(sizeof(*capture) + orig_f->len);
+       capture = zmalloc<lttng_ust_abi_capture_bytecode>(sizeof(*capture) + orig_f->len);
        if (!capture) {
-               PERROR("Failed to allocate lttng_ust_abi_capture_bytecode: bytecode len = %" PRIu32 " bytes", orig_f->len);
+               PERROR("Failed to allocate lttng_ust_abi_capture_bytecode: bytecode len = %" PRIu32
+                      " bytes",
+                      orig_f->len);
                goto error;
        }
 
        LTTNG_ASSERT(sizeof(struct lttng_bytecode) ==
-                       sizeof(struct lttng_ust_abi_capture_bytecode));
+                    sizeof(struct lttng_ust_abi_capture_bytecode));
        memcpy(capture, orig_f, sizeof(*capture) + orig_f->len);
 error:
        return capture;
@@ -1456,17 +1451,19 @@ struct ust_app *ust_app_find_by_sock(int sock)
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
 
-       lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &iter);
+       ASSERT_RCU_READ_LOCKED();
+
+       lttng_ht_lookup(ust_app_ht_by_sock, (void *) ((unsigned long) sock), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                DBG2("UST app find by sock %d not found", sock);
                goto error;
        }
 
-       return caa_container_of(node, struct ust_app, sock_n);
+       return lttng::utils::container_of(node, &ust_app::sock_n);
 
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -1478,18 +1475,19 @@ static struct ust_app *find_app_by_notify_sock(int sock)
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
 
-       lttng_ht_lookup(ust_app_ht_by_notify_sock, (void *)((unsigned long) sock),
-                       &iter);
+       ASSERT_RCU_READ_LOCKED();
+
+       lttng_ht_lookup(ust_app_ht_by_notify_sock, (void *) ((unsigned long) sock), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                DBG2("UST app find by notify sock %d not found", sock);
                goto error;
        }
 
-       return caa_container_of(node, struct ust_app, notify_sock_n);
+       return lttng::utils::container_of(node, &ust_app::notify_sock_n);
 
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -1499,13 +1497,15 @@ error:
  * Return an ust_app_event object or NULL on error.
  */
 static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht,
-               const char *name, const struct lttng_bytecode *filter,
-               int loglevel_value,
-               const struct lttng_event_exclusion *exclusion)
+                                               const char *name,
+                                               const struct lttng_bytecode *filter,
+                                               lttng_ust_abi_loglevel_type loglevel_type,
+                                               int loglevel_value,
+                                               const struct lttng_event_exclusion *exclusion)
 {
        struct lttng_ht_iter iter;
        struct lttng_ht_node_str *node;
-       struct ust_app_event *event = NULL;
+       struct ust_app_event *event = nullptr;
        struct ust_app_ht_key key;
 
        LTTNG_ASSERT(name);
@@ -1514,19 +1514,23 @@ static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht,
        /* Setup key for event lookup. */
        key.name = name;
        key.filter = filter;
-       key.loglevel_type = (lttng_ust_abi_loglevel_type) loglevel_value;
+       key.loglevel_type = loglevel_type;
+       key.loglevel_value = loglevel_value;
        /* lttng_event_exclusion and lttng_ust_event_exclusion structures are similar */
        key.exclusion = exclusion;
 
        /* Lookup using the event name as hash and a custom match fct. */
-       cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
-                       ht_match_ust_app_event, &key, &iter.iter);
+       cds_lfht_lookup(ht->ht,
+                       ht->hash_fct((void *) name, lttng_ht_seed),
+                       ht_match_ust_app_event,
+                       &key,
+                       &iter.iter);
        node = lttng_ht_iter_get_node_str(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                goto end;
        }
 
-       event = caa_container_of(node, struct ust_app_event, node);
+       event = lttng::utils::container_of(node, &ust_app_event::node);
 
 end:
        return event;
@@ -1538,25 +1542,24 @@ end:
  * Must be called with the RCU read lock held.
  * Return an ust_app_event_notifier_rule object or NULL on error.
  */
-static struct ust_app_event_notifier_rule *find_ust_app_event_notifier_rule(
-               struct lttng_ht *ht, uint64_t token)
+static struct ust_app_event_notifier_rule *find_ust_app_event_notifier_rule(struct lttng_ht *ht,
+                                                                           uint64_t token)
 {
        struct lttng_ht_iter iter;
        struct lttng_ht_node_u64 *node;
-       struct ust_app_event_notifier_rule *event_notifier_rule = NULL;
+       struct ust_app_event_notifier_rule *event_notifier_rule = nullptr;
 
        LTTNG_ASSERT(ht);
+       ASSERT_RCU_READ_LOCKED();
 
        lttng_ht_lookup(ht, &token, &iter);
        node = lttng_ht_iter_get_node_u64(&iter);
-       if (node == NULL) {
-               DBG2("UST app event notifier rule token not found: token = %" PRIu64,
-                               token);
+       if (node == nullptr) {
+               DBG2("UST app event notifier rule token not found: token = %" PRIu64, token);
                goto end;
        }
 
-       event_notifier_rule = caa_container_of(
-                       node, struct ust_app_event_notifier_rule, node);
+       event_notifier_rule = lttng::utils::container_of(node, &ust_app_event_notifier_rule::node);
 end:
        return event_notifier_rule;
 }
@@ -1566,30 +1569,33 @@ end:
  *
  * Called with UST app session lock held.
  */
-static
-int create_ust_channel_context(struct ust_app_channel *ua_chan,
-               struct ust_app_ctx *ua_ctx, struct ust_app *app)
+static int create_ust_channel_context(struct ust_app_channel *ua_chan,
+                                     struct ust_app_ctx *ua_ctx,
+                                     struct ust_app *app)
 {
        int ret;
 
        health_code_update();
 
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_add_context(app->sock, &ua_ctx->ctx,
-                       ua_chan->obj, &ua_ctx->obj);
+       ret = lttng_ust_ctl_add_context(app->sock, &ua_ctx->ctx, ua_chan->obj, &ua_ctx->obj);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app create channel context failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app create channel context failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app create channel context failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error;
        }
@@ -1597,7 +1603,8 @@ int create_ust_channel_context(struct ust_app_channel *ua_chan,
        ua_ctx->handle = ua_ctx->obj->handle;
 
        DBG2("UST app context handle %d created successfully for channel %s",
-                       ua_ctx->handle, ua_chan->name);
+            ua_ctx->handle,
+            ua_chan->name);
 
 error:
        health_code_update();
@@ -1608,11 +1615,11 @@ error:
  * Set the filter on the tracer.
  */
 static int set_ust_object_filter(struct ust_app *app,
-               const struct lttng_bytecode *bytecode,
-               struct lttng_ust_abi_object_data *ust_object)
+                                const struct lttng_bytecode *bytecode,
+                                struct lttng_ust_abi_object_data *ust_object)
 {
        int ret;
-       struct lttng_ust_abi_filter_bytecode *ust_bytecode = NULL;
+       struct lttng_ust_abi_filter_bytecode *ust_bytecode = nullptr;
 
        health_code_update();
 
@@ -1622,21 +1629,25 @@ static int set_ust_object_filter(struct ust_app *app,
                goto error;
        }
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_set_filter(app->sock, ust_bytecode,
-                       ust_object);
+       ret = lttng_ust_ctl_set_filter(app->sock, ust_bytecode, ust_object);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app  set filter failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app  set filter failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app  set filter failed with ret %d: pid = %d, sock = %d, object = %p",
-                                       ret, app->pid, app->sock, ust_object);
+                           ret,
+                           app->pid,
+                           app->sock,
+                           ust_object);
                }
                goto error;
        }
@@ -1655,12 +1666,12 @@ error:
  * the captured payloads.
  */
 static int set_ust_capture(struct ust_app *app,
-               const struct lttng_bytecode *bytecode,
-               unsigned int capture_seqnum,
-               struct lttng_ust_abi_object_data *ust_object)
+                          const struct lttng_bytecode *bytecode,
+                          unsigned int capture_seqnum,
+                          struct lttng_ust_abi_object_data *ust_object)
 {
        int ret;
-       struct lttng_ust_abi_capture_bytecode *ust_bytecode = NULL;
+       struct lttng_ust_abi_capture_bytecode *ust_bytecode = nullptr;
 
        health_code_update();
 
@@ -1676,22 +1687,24 @@ static int set_ust_capture(struct ust_app *app,
        ust_bytecode->seqnum = capture_seqnum;
 
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_set_capture(app->sock, ust_bytecode,
-                       ust_object);
+       ret = lttng_ust_ctl_set_capture(app->sock, ust_bytecode, ust_object);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app set capture failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        DBG3("UST app set capture failed. Communication timeout: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app event set capture failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid,
-                                       app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
 
                goto error;
@@ -1705,22 +1718,21 @@ error:
        return ret;
 }
 
-static
-struct lttng_ust_abi_event_exclusion *create_ust_exclusion_from_exclusion(
-               const struct lttng_event_exclusion *exclusion)
+static struct lttng_ust_abi_event_exclusion *
+create_ust_exclusion_from_exclusion(const struct lttng_event_exclusion *exclusion)
 {
-       struct lttng_ust_abi_event_exclusion *ust_exclusion = NULL;
+       struct lttng_ust_abi_event_exclusion *ust_exclusion = nullptr;
        size_t exclusion_alloc_size = sizeof(struct lttng_ust_abi_event_exclusion) +
                LTTNG_UST_ABI_SYM_NAME_LEN * exclusion->count;
 
-       ust_exclusion = (lttng_ust_abi_event_exclusion *) zmalloc(exclusion_alloc_size);
+       ust_exclusion = zmalloc<lttng_ust_abi_event_exclusion>(exclusion_alloc_size);
        if (!ust_exclusion) {
                PERROR("malloc");
                goto end;
        }
 
        LTTNG_ASSERT(sizeof(struct lttng_event_exclusion) ==
-                       sizeof(struct lttng_ust_abi_event_exclusion));
+                    sizeof(struct lttng_ust_abi_event_exclusion));
        memcpy(ust_exclusion, exclusion, exclusion_alloc_size);
 end:
        return ust_exclusion;
@@ -1730,18 +1742,17 @@ end:
  * Set event exclusions on the tracer.
  */
 static int set_ust_object_exclusions(struct ust_app *app,
-               const struct lttng_event_exclusion *exclusions,
-               struct lttng_ust_abi_object_data *ust_object)
+                                    const struct lttng_event_exclusion *exclusions,
+                                    struct lttng_ust_abi_object_data *ust_object)
 {
        int ret;
-       struct lttng_ust_abi_event_exclusion *ust_exclusions = NULL;
+       struct lttng_ust_abi_event_exclusion *ust_exclusions = nullptr;
 
        LTTNG_ASSERT(exclusions && exclusions->count > 0);
 
        health_code_update();
 
-       ust_exclusions = create_ust_exclusion_from_exclusion(
-                       exclusions);
+       ust_exclusions = create_ust_exclusion_from_exclusion(exclusions);
        if (!ust_exclusions) {
                ret = -LTTNG_ERR_NOMEM;
                goto error;
@@ -1753,14 +1764,19 @@ static int set_ust_object_exclusions(struct ust_app *app,
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app event exclusion failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app event exclusion failed. Communication time out(pid: %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app event exclusions failed with ret %d: pid = %d, sock = %d, object = %p",
-                                       ret, app->pid, app->sock, ust_object);
+                           ret,
+                           app->pid,
+                           app->sock,
+                           ust_object);
                }
                goto error;
        }
@@ -1776,8 +1792,7 @@ error:
 /*
  * Disable the specified event on to UST tracer for the UST session.
  */
-static int disable_ust_object(struct ust_app *app,
-               struct lttng_ust_abi_object_data *object)
+static int disable_ust_object(struct ust_app *app, struct lttng_ust_abi_object_data *object)
 {
        int ret;
 
@@ -1790,20 +1805,24 @@ static int disable_ust_object(struct ust_app *app,
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app disable object failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app disable object failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app disable object failed with ret %d: pid = %d, sock = %d, object = %p",
-                                       ret, app->pid, app->sock, object);
+                           ret,
+                           app->pid,
+                           app->sock,
+                           object);
                }
                goto error;
        }
 
-       DBG2("UST app object %p disabled successfully for app: pid = %d",
-                       object, app->pid);
+       DBG2("UST app object %p disabled successfully for app: pid = %d", object, app->pid);
 
 error:
        health_code_update();
@@ -1814,7 +1833,8 @@ error:
  * Disable the specified channel on to UST tracer for the UST session.
  */
 static int disable_ust_channel(struct ust_app *app,
-               struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan)
+                              struct ust_app_session *ua_sess,
+                              struct ust_app_channel *ua_chan)
 {
        int ret;
 
@@ -1827,21 +1847,25 @@ static int disable_ust_channel(struct ust_app *app,
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app disable channel failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app disable channel failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app channel %s disable failed, session handle %d, with ret %d: pid = %d, sock = %d",
-                                       ua_chan->name, ua_sess->handle, ret,
-                                       app->pid, app->sock);
+                           ua_chan->name,
+                           ua_sess->handle,
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error;
        }
 
-       DBG2("UST app channel %s disabled successfully for app: pid = %d",
-                       ua_chan->name, app->pid);
+       DBG2("UST app channel %s disabled successfully for app: pid = %d", ua_chan->name, app->pid);
 
 error:
        health_code_update();
@@ -1852,7 +1876,8 @@ error:
  * Enable the specified channel on to UST tracer for the UST session.
  */
 static int enable_ust_channel(struct ust_app *app,
-               struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan)
+                             struct ust_app_session *ua_sess,
+                             struct ust_app_channel *ua_chan)
 {
        int ret;
 
@@ -1865,23 +1890,29 @@ static int enable_ust_channel(struct ust_app *app,
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app channel %s enable failed. Application is dead: pid = %d, sock = %d",
-                                       ua_chan->name, app->pid, app->sock);
+                            ua_chan->name,
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app channel %s enable failed. Communication time out: pid = %d, sock = %d",
-                                       ua_chan->name, app->pid, app->sock);
+                            ua_chan->name,
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app channel %s enable failed, session handle %d, with ret %d: pid = %d, sock = %d",
-                                       ua_chan->name, ua_sess->handle, ret,
-                                       app->pid, app->sock);
+                           ua_chan->name,
+                           ua_sess->handle,
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error;
        }
 
-       ua_chan->enabled = 1;
+       ua_chan->enabled = true;
 
-       DBG2("UST app channel %s enabled successfully for app: pid = %d",
-                       ua_chan->name, app->pid);
+       DBG2("UST app channel %s enabled successfully for app: pid = %d", ua_chan->name, app->pid);
 
 error:
        health_code_update();
@@ -1891,8 +1922,7 @@ error:
 /*
  * Enable the specified event on to UST tracer for the UST session.
  */
-static int enable_ust_object(
-               struct ust_app *app, struct lttng_ust_abi_object_data *ust_object)
+static int enable_ust_object(struct ust_app *app, struct lttng_ust_abi_object_data *ust_object)
 {
        int ret;
 
@@ -1905,20 +1935,24 @@ static int enable_ust_object(
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app enable object failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app enable object failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app enable object failed with ret %d: pid = %d, sock = %d, object = %p",
-                                       ret, app->pid, app->sock, ust_object);
+                           ret,
+                           app->pid,
+                           app->sock,
+                           ust_object);
                }
                goto error;
        }
 
-       DBG2("UST app object %p enabled successfully for app: pid = %d",
-                       ust_object, app->pid);
+       DBG2("UST app object %p enabled successfully for app: pid = %d", ust_object, app->pid);
 
 error:
        health_code_update();
@@ -1931,7 +1965,8 @@ error:
  * Return 0 on success. On error, a negative value is returned.
  */
 static int send_channel_pid_to_ust(struct ust_app *app,
-               struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan)
+                                  struct ust_app_session *ua_sess,
+                                  struct ust_app_channel *ua_chan)
 {
        int ret;
        struct ust_app_stream *stream, *stmp;
@@ -1942,18 +1977,20 @@ static int send_channel_pid_to_ust(struct ust_app *app,
 
        health_code_update();
 
-       DBG("UST app sending channel %s to UST app sock %d", ua_chan->name,
-                       app->sock);
+       DBG("UST app sending channel %s to UST app sock %d", ua_chan->name, app->sock);
 
        /* Send channel to the application. */
        ret = ust_consumer_send_channel_to_ust(app, ua_sess, ua_chan);
        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
-               ret = -ENOTCONN;        /* Caused by app exiting. */
+               ret = -ENOTCONN; /* Caused by app exiting. */
                goto error;
        } else if (ret == -EAGAIN) {
                /* Caused by timeout. */
-               WARN("Communication with application %d timed out on send_channel for channel \"%s\" of session \"%" PRIu64 "\".",
-                               app->pid, ua_chan->name, ua_sess->tracing_id);
+               WARN("Communication with application %d timed out on send_channel for channel \"%s\" of session \"%" PRIu64
+                    "\".",
+                    app->pid,
+                    ua_chan->name,
+                    ua_sess->tracing_id);
                /* Treat this the same way as an application that is exiting. */
                ret = -ENOTCONN;
                goto error;
@@ -1964,16 +2001,19 @@ static int send_channel_pid_to_ust(struct ust_app *app,
        health_code_update();
 
        /* Send all streams to application. */
-       cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) {
+       cds_list_for_each_entry_safe (stream, stmp, &ua_chan->streams.head, list) {
                ret = ust_consumer_send_stream_to_ust(app, ua_chan, stream);
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = -ENOTCONN; /* Caused by app exiting. */
                        goto error;
                } else if (ret == -EAGAIN) {
                        /* Caused by timeout. */
-                       WARN("Communication with application %d timed out on send_stream for stream \"%s\" of channel \"%s\" of session \"%" PRIu64 "\".",
-                                       app->pid, stream->name, ua_chan->name,
-                                       ua_sess->tracing_id);
+                       WARN("Communication with application %d timed out on send_stream for stream \"%s\" of channel \"%s\" of session \"%" PRIu64
+                            "\".",
+                            app->pid,
+                            stream->name,
+                            ua_chan->name,
+                            ua_sess->tracing_id);
                        /*
                         * Treat this the same way as an application that is
                         * exiting.
@@ -1986,8 +2026,6 @@ static int send_channel_pid_to_ust(struct ust_app *app,
                cds_list_del(&stream->list);
                delete_ust_app_stream(-1, stream, app);
        }
-       /* Flag the channel that it is sent to the application. */
-       ua_chan->is_sent = 1;
 
 error:
        health_code_update();
@@ -1999,9 +2037,9 @@ error:
  *
  * Should be called with session mutex held.
  */
-static
-int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan, struct ust_app_event *ua_event)
+static int create_ust_event(struct ust_app *app,
+                           struct ust_app_channel *ua_chan,
+                           struct ust_app_event *ua_event)
 {
        int ret = 0;
 
@@ -2009,22 +2047,25 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
 
        /* Create UST event on tracer */
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_create_event(app->sock, &ua_event->attr, ua_chan->obj,
-                       &ua_event->obj);
+       ret = lttng_ust_ctl_create_event(app->sock, &ua_event->attr, ua_chan->obj, &ua_event->obj);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app create event failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app create event failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app create event '%s' failed with ret %d: pid = %d, sock = %d",
-                                       ua_event->attr.name, ret, app->pid,
-                                       app->sock);
+                           ua_event->attr.name,
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error;
        }
@@ -2032,7 +2073,9 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
        ua_event->handle = ua_event->obj->handle;
 
        DBG2("UST app event %s created successfully for pid:%d object = %p",
-                       ua_event->attr.name, app->pid, ua_event->obj);
+            ua_event->attr.name,
+            app->pid,
+            ua_event->obj);
 
        health_code_update();
 
@@ -2085,16 +2128,15 @@ error:
        return ret;
 }
 
-static int init_ust_event_notifier_from_event_rule(
-               const struct lttng_event_rule *rule,
-               struct lttng_ust_abi_event_notifier *event_notifier)
+static int
+init_ust_event_notifier_from_event_rule(const struct lttng_event_rule *rule,
+                                       struct lttng_ust_abi_event_notifier *event_notifier)
 {
        enum lttng_event_rule_status status;
        enum lttng_ust_abi_loglevel_type ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
        int loglevel = -1, ret = 0;
        const char *pattern;
 
-
        memset(event_notifier, 0, sizeof(*event_notifier));
 
        if (lttng_event_rule_targets_agent_domain(rule)) {
@@ -2104,15 +2146,14 @@ static int init_ust_event_notifier_from_event_rule(
                 * attached later on.
                 * Set the default values for the agent event.
                 */
-               pattern = event_get_default_agent_ust_name(
-                               lttng_event_rule_get_domain_type(rule));
+               pattern = event_get_default_agent_ust_name(lttng_event_rule_get_domain_type(rule));
                loglevel = 0;
                ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
        } else {
                const struct lttng_log_level_rule *log_level_rule;
 
                LTTNG_ASSERT(lttng_event_rule_get_type(rule) ==
-                               LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
+                            LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
 
                status = lttng_event_rule_user_tracepoint_get_name_pattern(rule, &pattern);
                if (status != LTTNG_EVENT_RULE_STATUS_OK) {
@@ -2120,8 +2161,7 @@ static int init_ust_event_notifier_from_event_rule(
                        abort();
                }
 
-               status = lttng_event_rule_user_tracepoint_get_log_level_rule(
-                               rule, &log_level_rule);
+               status = lttng_event_rule_user_tracepoint_get_log_level_rule(rule, &log_level_rule);
                if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
                        ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_ALL;
                } else if (status == LTTNG_EVENT_RULE_STATUS_OK) {
@@ -2130,13 +2170,13 @@ static int init_ust_event_notifier_from_event_rule(
                        switch (lttng_log_level_rule_get_type(log_level_rule)) {
                        case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
                                ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_SINGLE;
-                               llr_status = lttng_log_level_rule_exactly_get_level(
-                                               log_level_rule, &loglevel);
+                               llr_status = lttng_log_level_rule_exactly_get_level(log_level_rule,
+                                                                                   &loglevel);
                                break;
                        case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
                                ust_loglevel_type = LTTNG_UST_ABI_LOGLEVEL_RANGE;
                                llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level(
-                                               log_level_rule, &loglevel);
+                                       log_level_rule, &loglevel);
                                break;
                        default:
                                abort();
@@ -2150,11 +2190,10 @@ static int init_ust_event_notifier_from_event_rule(
        }
 
        event_notifier->event.instrumentation = LTTNG_UST_ABI_TRACEPOINT;
-       ret = lttng_strncpy(event_notifier->event.name, pattern,
-                       LTTNG_UST_ABI_SYM_NAME_LEN - 1);
+       ret = lttng_strncpy(
+               event_notifier->event.name, pattern, sizeof(event_notifier->event.name));
        if (ret) {
-               ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ",
-                               pattern);
+               ERR("Failed to copy event rule pattern to notifier: pattern = '%s' ", pattern);
                goto end;
        }
 
@@ -2169,13 +2208,13 @@ end:
  * given application.
  */
 static int create_ust_event_notifier(struct ust_app *app,
-               struct ust_app_event_notifier_rule *ua_event_notifier_rule)
+                                    struct ust_app_event_notifier_rule *ua_event_notifier_rule)
 {
        int ret = 0;
        enum lttng_condition_status condition_status;
-       const struct lttng_condition *condition = NULL;
+       const struct lttng_condition *condition = nullptr;
        struct lttng_ust_abi_event_notifier event_notifier;
-       const struct lttng_event_rule *event_rule = NULL;
+       const struct lttng_event_rule *event_rule = nullptr;
        unsigned int capture_bytecode_count = 0, i;
        enum lttng_condition_status cond_status;
        enum lttng_event_rule_type event_rule_type;
@@ -2183,25 +2222,21 @@ static int create_ust_event_notifier(struct ust_app *app,
        health_code_update();
        LTTNG_ASSERT(app->event_notifier_group.object);
 
-       condition = lttng_trigger_get_const_condition(
-                       ua_event_notifier_rule->trigger);
+       condition = lttng_trigger_get_const_condition(ua_event_notifier_rule->trigger);
        LTTNG_ASSERT(condition);
        LTTNG_ASSERT(lttng_condition_get_type(condition) ==
-                       LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
+                    LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES);
 
-       condition_status = lttng_condition_event_rule_matches_get_rule(
-                       condition, &event_rule);
+       condition_status = lttng_condition_event_rule_matches_get_rule(condition, &event_rule);
        LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK);
 
        LTTNG_ASSERT(event_rule);
 
        event_rule_type = lttng_event_rule_get_type(event_rule);
        LTTNG_ASSERT(event_rule_type == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT ||
-                       event_rule_type == LTTNG_EVENT_RULE_TYPE_JUL_LOGGING ||
-                       event_rule_type ==
-                                       LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING ||
-                       event_rule_type ==
-                                       LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING);
+                    event_rule_type == LTTNG_EVENT_RULE_TYPE_JUL_LOGGING ||
+                    event_rule_type == LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING ||
+                    event_rule_type == LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING);
 
        init_ust_event_notifier_from_event_rule(event_rule, &event_notifier);
        event_notifier.event.token = ua_event_notifier_rule->token;
@@ -2209,23 +2244,28 @@ static int create_ust_event_notifier(struct ust_app *app,
 
        /* Create UST event notifier against the tracer. */
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_create_event_notifier(app->sock, &event_notifier,
-                       app->event_notifier_group.object,
-                       &ua_event_notifier_rule->obj);
+       ret = lttng_ust_ctl_create_event_notifier(app->sock,
+                                                 &event_notifier,
+                                                 app->event_notifier_group.object,
+                                                 &ua_event_notifier_rule->obj);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app create event notifier failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app create event notifier failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app create event notifier '%s' failed with ret %d: pid = %d, sock = %d",
-                                       event_notifier.event.name, ret, app->pid,
-                                       app->sock);
+                           event_notifier.event.name,
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error;
        }
@@ -2233,15 +2273,17 @@ static int create_ust_event_notifier(struct ust_app *app,
        ua_event_notifier_rule->handle = ua_event_notifier_rule->obj->handle;
 
        DBG2("UST app event notifier %s created successfully: app = '%s': pid = %d, object = %p",
-                       event_notifier.event.name, app->name, app->pid,
-                       ua_event_notifier_rule->obj);
+            event_notifier.event.name,
+            app->name,
+            app->pid,
+            ua_event_notifier_rule->obj);
 
        health_code_update();
 
        /* Set filter if one is present. */
        if (ua_event_notifier_rule->filter) {
-               ret = set_ust_object_filter(app, ua_event_notifier_rule->filter,
-                               ua_event_notifier_rule->obj);
+               ret = set_ust_object_filter(
+                       app, ua_event_notifier_rule->filter, ua_event_notifier_rule->obj);
                if (ret < 0) {
                        goto error;
                }
@@ -2249,9 +2291,8 @@ static int create_ust_event_notifier(struct ust_app *app,
 
        /* Set exclusions for the event. */
        if (ua_event_notifier_rule->exclusion) {
-               ret = set_ust_object_exclusions(app,
-                               ua_event_notifier_rule->exclusion,
-                               ua_event_notifier_rule->obj);
+               ret = set_ust_object_exclusions(
+                       app, ua_event_notifier_rule->exclusion, ua_event_notifier_rule->obj);
                if (ret < 0) {
                        goto error;
                }
@@ -2259,16 +2300,15 @@ static int create_ust_event_notifier(struct ust_app *app,
 
        /* Set the capture bytecodes. */
        cond_status = lttng_condition_event_rule_matches_get_capture_descriptor_count(
-                       condition, &capture_bytecode_count);
+               condition, &capture_bytecode_count);
        LTTNG_ASSERT(cond_status == LTTNG_CONDITION_STATUS_OK);
 
        for (i = 0; i < capture_bytecode_count; i++) {
                const struct lttng_bytecode *capture_bytecode =
-                               lttng_condition_event_rule_matches_get_capture_bytecode_at_index(
-                                               condition, i);
+                       lttng_condition_event_rule_matches_get_capture_bytecode_at_index(condition,
+                                                                                        i);
 
-               ret = set_ust_capture(app, capture_bytecode, i,
-                               ua_event_notifier_rule->obj);
+               ret = set_ust_capture(app, capture_bytecode, i, ua_event_notifier_rule->obj);
                if (ret < 0) {
                        goto error;
                }
@@ -2310,8 +2350,7 @@ error:
 /*
  * Copy data between an UST app event and a LTT event.
  */
-static void shadow_copy_event(struct ust_app_event *ua_event,
-               struct ltt_ust_event *uevent)
+static void shadow_copy_event(struct ust_app_event *ua_event, struct ltt_ust_event *uevent)
 {
        size_t exclusion_alloc_size;
 
@@ -2332,13 +2371,12 @@ static void shadow_copy_event(struct ust_app_event *ua_event,
        /* Copy exclusion data */
        if (uevent->exclusion) {
                exclusion_alloc_size = sizeof(struct lttng_event_exclusion) +
-                               LTTNG_UST_ABI_SYM_NAME_LEN * uevent->exclusion->count;
-               ua_event->exclusion = (lttng_event_exclusion *) zmalloc(exclusion_alloc_size);
-               if (ua_event->exclusion == NULL) {
+                       LTTNG_UST_ABI_SYM_NAME_LEN * uevent->exclusion->count;
+               ua_event->exclusion = zmalloc<lttng_event_exclusion>(exclusion_alloc_size);
+               if (ua_event->exclusion == nullptr) {
                        PERROR("malloc");
                } else {
-                       memcpy(ua_event->exclusion, uevent->exclusion,
-                                       exclusion_alloc_size);
+                       memcpy(ua_event->exclusion, uevent->exclusion, exclusion_alloc_size);
                }
        }
 }
@@ -2346,8 +2384,7 @@ static void shadow_copy_event(struct ust_app_event *ua_event,
 /*
  * Copy data between an UST app channel and a LTT channel.
  */
-static void shadow_copy_channel(struct ust_app_channel *ua_chan,
-               struct ltt_ust_channel *uchan)
+static void shadow_copy_channel(struct ust_app_channel *ua_chan, struct ltt_ust_channel *uchan)
 {
        DBG2("UST app shadow copy of channel %s started", ua_chan->name);
 
@@ -2382,7 +2419,8 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
  * Copy data between a UST app session and a regular LTT session.
  */
 static void shadow_copy_session(struct ust_app_session *ua_sess,
-               struct ltt_ust_session *usess, struct ust_app *app)
+                               struct ltt_ust_session *usess,
+                               struct ust_app *app)
 {
        struct tm *timeinfo;
        char datetime[16];
@@ -2401,7 +2439,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
        LTTNG_OPTIONAL_SET(&ua_sess->effective_credentials.uid, usess->uid);
        LTTNG_OPTIONAL_SET(&ua_sess->effective_credentials.gid, usess->gid);
        ua_sess->buffer_type = usess->buffer_type;
-       ua_sess->bits_per_long = app->bits_per_long;
+       ua_sess->bits_per_long = app->abi.bits_per_long;
 
        /* There is only one consumer object per session possible. */
        consumer_output_get(usess->consumer);
@@ -2409,20 +2447,23 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
 
        ua_sess->output_traces = usess->output_traces;
        ua_sess->live_timer_interval = usess->live_timer_interval;
-       copy_channel_attr_to_ustctl(&ua_sess->metadata_attr,
-                       &usess->metadata_attr);
+       copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &usess->metadata_attr);
 
        switch (ua_sess->buffer_type) {
        case LTTNG_BUFFER_PER_PID:
-               ret = snprintf(ua_sess->path, sizeof(ua_sess->path),
-                               DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", app->name, app->pid,
-                               datetime);
+               ret = snprintf(ua_sess->path,
+                              sizeof(ua_sess->path),
+                              DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
+                              app->name,
+                              app->pid,
+                              datetime);
                break;
        case LTTNG_BUFFER_PER_UID:
-               ret = snprintf(ua_sess->path, sizeof(ua_sess->path),
-                               DEFAULT_UST_TRACE_UID_PATH,
-                               lttng_credentials_get_uid(&ua_sess->real_credentials),
-                               app->bits_per_long);
+               ret = snprintf(ua_sess->path,
+                              sizeof(ua_sess->path),
+                              DEFAULT_UST_TRACE_UID_PATH,
+                              lttng_credentials_get_uid(&ua_sess->real_credentials),
+                              app->abi.bits_per_long);
                break;
        default:
                abort();
@@ -2434,23 +2475,26 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
                goto error;
        }
 
-       strncpy(ua_sess->root_shm_path, usess->root_shm_path,
-               sizeof(ua_sess->root_shm_path));
+       strncpy(ua_sess->root_shm_path, usess->root_shm_path, sizeof(ua_sess->root_shm_path));
        ua_sess->root_shm_path[sizeof(ua_sess->root_shm_path) - 1] = '\0';
-       strncpy(ua_sess->shm_path, usess->shm_path,
-               sizeof(ua_sess->shm_path));
+       strncpy(ua_sess->shm_path, usess->shm_path, sizeof(ua_sess->shm_path));
        ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0';
        if (ua_sess->shm_path[0]) {
                switch (ua_sess->buffer_type) {
                case LTTNG_BUFFER_PER_PID:
-                       ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
-                                       "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
-                                       app->name, app->pid, datetime);
+                       ret = snprintf(tmp_shm_path,
+                                      sizeof(tmp_shm_path),
+                                      "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
+                                      app->name,
+                                      app->pid,
+                                      datetime);
                        break;
                case LTTNG_BUFFER_PER_UID:
-                       ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
-                                       "/" DEFAULT_UST_TRACE_UID_PATH,
-                                       app->uid, app->bits_per_long);
+                       ret = snprintf(tmp_shm_path,
+                                      sizeof(tmp_shm_path),
+                                      "/" DEFAULT_UST_TRACE_UID_PATH,
+                                      app->uid,
+                                      app->abi.bits_per_long);
                        break;
                default:
                        abort();
@@ -2461,7 +2505,8 @@ static void shadow_copy_session(struct ust_app_session *ua_sess,
                        abort();
                        goto error;
                }
-               strncat(ua_sess->shm_path, tmp_shm_path,
+               strncat(ua_sess->shm_path,
+                       tmp_shm_path,
                        sizeof(ua_sess->shm_path) - strlen(ua_sess->shm_path) - 1);
                ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0';
        }
@@ -2474,9 +2519,9 @@ error:
 /*
  * Lookup sesison wrapper.
  */
-static
-void __lookup_session_by_app(const struct ltt_ust_session *usess,
-                       struct ust_app *app, struct lttng_ht_iter *iter)
+static void __lookup_session_by_app(const struct ltt_ust_session *usess,
+                                   struct ust_app *app,
+                                   struct lttng_ht_iter *iter)
 {
        /* Get right UST app session from app */
        lttng_ht_lookup(app->sessions, &usess->id, iter);
@@ -2486,22 +2531,22 @@ void __lookup_session_by_app(const struct ltt_ust_session *usess,
  * Return ust app session from the app session hashtable using the UST session
  * id.
  */
-static struct ust_app_session *lookup_session_by_app(
-               const struct ltt_ust_session *usess, struct ust_app *app)
+static struct ust_app_session *lookup_session_by_app(const struct ltt_ust_session *usess,
+                                                    struct ust_app *app)
 {
        struct lttng_ht_iter iter;
        struct lttng_ht_node_u64 *node;
 
        __lookup_session_by_app(usess, app, &iter);
        node = lttng_ht_iter_get_node_u64(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                goto error;
        }
 
-       return caa_container_of(node, struct ust_app_session, node);
+       return lttng::utils::container_of(node, &ust_app_session::node);
 
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -2512,7 +2557,8 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
-               struct ust_app *app, struct buffer_reg_pid **regp)
+                               struct ust_app *app,
+                               struct buffer_reg_pid **regp)
 {
        int ret = 0;
        struct buffer_reg_pid *reg_pid;
@@ -2520,7 +2566,7 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        reg_pid = buffer_reg_pid_find(ua_sess->id);
        if (!reg_pid) {
@@ -2528,8 +2574,8 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
                 * This is the create channel path meaning that if there is NO
                 * registry available, we have to create one for this session.
                 */
-               ret = buffer_reg_pid_create(ua_sess->id, &reg_pid,
-                       ua_sess->root_shm_path, ua_sess->shm_path);
+               ret = buffer_reg_pid_create(
+                       ua_sess->id, &reg_pid, ua_sess->root_shm_path, ua_sess->shm_path);
                if (ret < 0) {
                        goto error;
                }
@@ -2538,17 +2584,17 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess,
        }
 
        /* Initialize registry. */
-       ret = ust_registry_session_init(&reg_pid->registry->reg.ust, app,
-                       app->bits_per_long, app->uint8_t_alignment,
-                       app->uint16_t_alignment, app->uint32_t_alignment,
-                       app->uint64_t_alignment, app->long_alignment,
-                       app->byte_order, app->version.major, app->version.minor,
-                       reg_pid->root_shm_path, reg_pid->shm_path,
-                       lttng_credentials_get_uid(&ua_sess->effective_credentials),
-                       lttng_credentials_get_gid(&ua_sess->effective_credentials),
-                       ua_sess->tracing_id,
-                       app->uid);
-       if (ret < 0) {
+       reg_pid->registry->reg.ust = ust_registry_session_per_pid_create(
+               app,
+               app->abi,
+               app->version.major,
+               app->version.minor,
+               reg_pid->root_shm_path,
+               reg_pid->shm_path,
+               lttng_credentials_get_uid(&ua_sess->effective_credentials),
+               lttng_credentials_get_gid(&ua_sess->effective_credentials),
+               ua_sess->tracing_id);
+       if (!reg_pid->registry->reg.ust) {
                /*
                 * reg_pid->registry->reg.ust is NULL upon error, so we need to
                 * destroy the buffer registry, because it is always expected
@@ -2568,7 +2614,6 @@ end:
                *regp = reg_pid;
        }
 error:
-       rcu_read_unlock();
        return ret;
 }
 
@@ -2580,8 +2625,9 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
-               struct ust_app_session *ua_sess,
-               struct ust_app *app, struct buffer_reg_uid **regp)
+                               struct ust_app_session *ua_sess,
+                               struct ust_app *app,
+                               struct buffer_reg_uid **regp)
 {
        int ret = 0;
        struct buffer_reg_uid *reg_uid;
@@ -2589,17 +2635,21 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(app);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
-       reg_uid = buffer_reg_uid_find(usess->id, app->bits_per_long, app->uid);
+       reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid);
        if (!reg_uid) {
                /*
                 * This is the create channel path meaning that if there is NO
                 * registry available, we have to create one for this session.
                 */
-               ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid,
-                               LTTNG_DOMAIN_UST, &reg_uid,
-                               ua_sess->root_shm_path, ua_sess->shm_path);
+               ret = buffer_reg_uid_create(usess->id,
+                                           app->abi.bits_per_long,
+                                           app->uid,
+                                           LTTNG_DOMAIN_UST,
+                                           &reg_uid,
+                                           ua_sess->root_shm_path,
+                                           ua_sess->shm_path);
                if (ret < 0) {
                        goto error;
                }
@@ -2608,24 +2658,26 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
        }
 
        /* Initialize registry. */
-       ret = ust_registry_session_init(&reg_uid->registry->reg.ust, NULL,
-                       app->bits_per_long, app->uint8_t_alignment,
-                       app->uint16_t_alignment, app->uint32_t_alignment,
-                       app->uint64_t_alignment, app->long_alignment,
-                       app->byte_order, app->version.major,
-                       app->version.minor, reg_uid->root_shm_path,
-                       reg_uid->shm_path, usess->uid, usess->gid,
-                       ua_sess->tracing_id, app->uid);
-       if (ret < 0) {
+       reg_uid->registry->reg.ust = ust_registry_session_per_uid_create(app->abi,
+                                                                        app->version.major,
+                                                                        app->version.minor,
+                                                                        reg_uid->root_shm_path,
+                                                                        reg_uid->shm_path,
+                                                                        usess->uid,
+                                                                        usess->gid,
+                                                                        ua_sess->tracing_id,
+                                                                        app->uid);
+       if (!reg_uid->registry->reg.ust) {
                /*
                 * reg_uid->registry->reg.ust is NULL upon error, so we need to
                 * destroy the buffer registry, because it is always expected
                 * that if the buffer registry can be found, its ust registry is
                 * non-NULL.
                 */
-               buffer_reg_uid_destroy(reg_uid, NULL);
+               buffer_reg_uid_destroy(reg_uid, nullptr);
                goto error;
        }
+
        /* Add node to teardown list of the session. */
        cds_list_add(&reg_uid->lnode, &usess->buffer_reg_uid_list);
 
@@ -2637,7 +2689,6 @@ end:
                *regp = reg_uid;
        }
 error:
-       rcu_read_unlock();
        return ret;
 }
 
@@ -2653,8 +2704,9 @@ error:
  * -ENOTCONN which is the default code if the lttng_ust_ctl_create_session fails.
  */
 static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
-               struct ust_app *app, struct ust_app_session **ua_sess_ptr,
-               int *is_created)
+                                         struct ust_app *app,
+                                         struct ust_app_session **ua_sess_ptr,
+                                         int *is_created)
 {
        int ret, created = 0;
        struct ust_app_session *ua_sess;
@@ -2666,11 +2718,12 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
        health_code_update();
 
        ua_sess = lookup_session_by_app(usess, app);
-       if (ua_sess == NULL) {
+       if (ua_sess == nullptr) {
                DBG2("UST app pid: %d session id %" PRIu64 " not found, creating it",
-                               app->pid, usess->id);
+                    app->pid,
+                    usess->id);
                ua_sess = alloc_ust_app_session();
-               if (ua_sess == NULL) {
+               if (ua_sess == nullptr) {
                        /* Only malloc can failed so something is really wrong */
                        ret = -ENOMEM;
                        goto error;
@@ -2682,7 +2735,7 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_PID:
                /* Init local registry. */
-               ret = setup_buffer_reg_pid(ua_sess, app, NULL);
+               ret = setup_buffer_reg_pid(ua_sess, app, nullptr);
                if (ret < 0) {
                        delete_ust_app_session(-1, ua_sess, app);
                        goto error;
@@ -2690,7 +2743,7 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
                break;
        case LTTNG_BUFFER_PER_UID:
                /* Look for a global registry. If none exists, create one. */
-               ret = setup_buffer_reg_uid(usess, ua_sess, app, NULL);
+               ret = setup_buffer_reg_uid(usess, ua_sess, app, nullptr);
                if (ret < 0) {
                        delete_ust_app_session(-1, ua_sess, app);
                        goto error;
@@ -2711,15 +2764,19 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG("UST app creating session failed. Application is dead: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                   app->pid,
+                                   app->sock);
                                ret = 0;
                        } else if (ret == -EAGAIN) {
                                DBG("UST app creating session failed. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
+                                   app->pid,
+                                   app->sock);
                                ret = 0;
                        } else {
                                ERR("UST app creating session failed with ret %d: pid = %d, sock =%d",
-                                               ret, app->pid, app->sock);
+                                   ret,
+                                   app->pid,
+                                   app->sock);
                        }
                        delete_ust_app_session(-1, ua_sess, app);
                        if (ret != -ENOMEM) {
@@ -2735,12 +2792,10 @@ static int find_or_create_ust_app_session(struct ltt_ust_session *usess,
                ua_sess->handle = ret;
 
                /* Add ust app session to app's HT */
-               lttng_ht_node_init_u64(&ua_sess->node,
-                               ua_sess->tracing_id);
+               lttng_ht_node_init_u64(&ua_sess->node, ua_sess->tracing_id);
                lttng_ht_add_unique_u64(app->sessions, &ua_sess->node);
                lttng_ht_node_init_ulong(&ua_sess->ust_objd_node, ua_sess->handle);
-               lttng_ht_add_unique_ulong(app->ust_sessions_objd,
-                               &ua_sess->ust_objd_node);
+               lttng_ht_add_unique_ulong(app->ust_sessions_objd, &ua_sess->ust_objd_node);
 
                DBG2("UST app session created successfully with handle %d", ret);
        }
@@ -2780,19 +2835,17 @@ static int ht_match_ust_app_ctx(struct cds_lfht_node *node, const void *_key)
                goto no_match;
        }
 
-       switch(key->ctx) {
+       switch (key->ctx) {
        case LTTNG_UST_ABI_CONTEXT_PERF_THREAD_COUNTER:
                if (strncmp(key->u.perf_counter.name,
-                               ctx->ctx.u.perf_counter.name,
-                               sizeof(key->u.perf_counter.name))) {
+                           ctx->ctx.u.perf_counter.name,
+                           sizeof(key->u.perf_counter.name)) != 0) {
                        goto no_match;
                }
                break;
        case LTTNG_UST_ABI_CONTEXT_APP_CONTEXT:
-               if (strcmp(key->u.app_ctx.provider_name,
-                               ctx->ctx.u.app_ctx.provider_name) ||
-                               strcmp(key->u.app_ctx.ctx_name,
-                               ctx->ctx.u.app_ctx.ctx_name)) {
+               if (strcmp(key->u.app_ctx.provider_name, ctx->ctx.u.app_ctx.provider_name) != 0 ||
+                   strcmp(key->u.app_ctx.ctx_name, ctx->ctx.u.app_ctx.ctx_name) != 0) {
                        goto no_match;
                }
                break;
@@ -2813,26 +2866,29 @@ no_match:
  * Must be called while holding RCU read side lock.
  * Return an ust_app_ctx object or NULL on error.
  */
-static
-struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht,
-               struct lttng_ust_context_attr *uctx)
+static struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht,
+                                               struct lttng_ust_context_attr *uctx)
 {
        struct lttng_ht_iter iter;
        struct lttng_ht_node_ulong *node;
-       struct ust_app_ctx *app_ctx = NULL;
+       struct ust_app_ctx *app_ctx = nullptr;
 
        LTTNG_ASSERT(uctx);
        LTTNG_ASSERT(ht);
+       ASSERT_RCU_READ_LOCKED();
 
        /* Lookup using the lttng_ust_context_type and a custom match fct. */
-       cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed),
-                       ht_match_ust_app_ctx, uctx, &iter.iter);
+       cds_lfht_lookup(ht->ht,
+                       ht->hash_fct((void *) uctx->ctx, lttng_ht_seed),
+                       ht_match_ust_app_ctx,
+                       uctx,
+                       &iter.iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
        if (!node) {
                goto end;
        }
 
-       app_ctx = caa_container_of(node, struct ust_app_ctx, node);
+       app_ctx = lttng::utils::container_of(node, &ust_app_ctx::node);
 
 end:
        return app_ctx;
@@ -2843,14 +2899,15 @@ end:
  *
  * Called with UST app session lock held and a RCU read side lock.
  */
-static
-int create_ust_app_channel_context(struct ust_app_channel *ua_chan,
-               struct lttng_ust_context_attr *uctx,
-               struct ust_app *app)
+static int create_ust_app_channel_context(struct ust_app_channel *ua_chan,
+                                         struct lttng_ust_context_attr *uctx,
+                                         struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_ctx *ua_ctx;
 
+       ASSERT_RCU_READ_LOCKED();
+
        DBG2("UST app adding context to channel %s", ua_chan->name);
 
        ua_ctx = find_ust_app_context(ua_chan->ctx, uctx);
@@ -2860,7 +2917,7 @@ int create_ust_app_channel_context(struct ust_app_channel *ua_chan,
        }
 
        ua_ctx = alloc_ust_app_ctx(uctx);
-       if (ua_ctx == NULL) {
+       if (ua_ctx == nullptr) {
                /* malloc failed */
                ret = -ENOMEM;
                goto error;
@@ -2884,9 +2941,7 @@ error:
  *
  * Called with UST app session lock held.
  */
-static
-int enable_ust_app_event(struct ust_app_session *ua_sess,
-               struct ust_app_event *ua_event, struct ust_app *app)
+static int enable_ust_app_event(struct ust_app_event *ua_event, struct ust_app *app)
 {
        int ret;
 
@@ -2895,7 +2950,7 @@ int enable_ust_app_event(struct ust_app_session *ua_sess,
                goto error;
        }
 
-       ua_event->enabled = 1;
+       ua_event->enabled = true;
 
 error:
        return ret;
@@ -2904,8 +2959,7 @@ error:
 /*
  * Disable on the tracer side a ust app event for the session and channel.
  */
-static int disable_ust_app_event(struct ust_app_session *ua_sess,
-               struct ust_app_event *ua_event, struct ust_app *app)
+static int disable_ust_app_event(struct ust_app_event *ua_event, struct ust_app *app)
 {
        int ret;
 
@@ -2914,7 +2968,7 @@ static int disable_ust_app_event(struct ust_app_session *ua_sess,
                goto error;
        }
 
-       ua_event->enabled = 0;
+       ua_event->enabled = false;
 
 error:
        return ret;
@@ -2923,9 +2977,9 @@ error:
 /*
  * Lookup ust app channel for session and disable it on the tracer side.
  */
-static
-int disable_ust_app_channel(struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan, struct ust_app *app)
+static int disable_ust_app_channel(struct ust_app_session *ua_sess,
+                                  struct ust_app_channel *ua_chan,
+                                  struct ust_app *app)
 {
        int ret;
 
@@ -2934,7 +2988,7 @@ int disable_ust_app_channel(struct ust_app_session *ua_sess,
                goto error;
        }
 
-       ua_chan->enabled = 0;
+       ua_chan->enabled = false;
 
 error:
        return ret;
@@ -2945,22 +2999,26 @@ error:
  * MUST be called with a RCU read side lock acquired.
  */
 static int enable_ust_app_channel(struct ust_app_session *ua_sess,
-               struct ltt_ust_channel *uchan, struct ust_app *app)
+                                 struct ltt_ust_channel *uchan,
+                                 struct ust_app *app)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
        struct lttng_ht_node_str *ua_chan_node;
        struct ust_app_channel *ua_chan;
 
-       lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
+       ASSERT_RCU_READ_LOCKED();
+
+       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &iter);
        ua_chan_node = lttng_ht_iter_get_node_str(&iter);
-       if (ua_chan_node == NULL) {
+       if (ua_chan_node == nullptr) {
                DBG2("Unable to find channel %s in ust session id %" PRIu64,
-                               uchan->name, ua_sess->tracing_id);
+                    uchan->name,
+                    ua_sess->tracing_id);
                goto error;
        }
 
-       ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+       ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
 
        ret = enable_ust_channel(app, ua_sess, ua_chan);
        if (ret < 0) {
@@ -2979,9 +3037,10 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int do_consumer_create_channel(struct ltt_ust_session *usess,
-               struct ust_app_session *ua_sess, struct ust_app_channel *ua_chan,
-               int bitness, struct ust_registry_session *registry,
-               uint64_t trace_archive_id)
+                                     struct ust_app_session *ua_sess,
+                                     struct ust_app_channel *ua_chan,
+                                     int bitness,
+                                     lsu::registry_session *registry)
 {
        int ret;
        unsigned int nb_fd = 0;
@@ -2992,7 +3051,7 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess,
        LTTNG_ASSERT(ua_chan);
        LTTNG_ASSERT(registry);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
        health_code_update();
 
        /* Get the right consumer socket for the application. */
@@ -3015,8 +3074,8 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess,
         * Ask consumer to create channel. The consumer will return the number of
         * stream we have to expect.
         */
-       ret = ust_consumer_ask_channel(ua_sess, ua_chan, usess->consumer, socket,
-                       registry, usess->current_trace_chunk);
+       ret = ust_consumer_ask_channel(
+               ua_sess, ua_chan, usess->consumer, socket, registry, usess->current_trace_chunk);
        if (ret < 0) {
                goto error_ask;
        }
@@ -3047,7 +3106,6 @@ static int do_consumer_create_channel(struct ltt_ust_session *usess,
                }
        }
 
-       rcu_read_unlock();
        return 0;
 
 error_destroy:
@@ -3064,7 +3122,6 @@ error_ask:
        lttng_fd_put(LTTNG_FD_APPS, 1);
 error:
        health_code_update();
-       rcu_read_unlock();
        return ret;
 }
 
@@ -3075,7 +3132,7 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int duplicate_stream_object(struct buffer_reg_stream *reg_stream,
-               struct ust_app_stream *stream)
+                                  struct ust_app_stream *stream)
 {
        int ret;
 
@@ -3090,11 +3147,12 @@ static int duplicate_stream_object(struct buffer_reg_stream *reg_stream,
        }
 
        /* Duplicate object for stream once the original is in the registry. */
-       ret = lttng_ust_ctl_duplicate_ust_object_data(&stream->obj,
-                       reg_stream->obj.ust);
+       ret = lttng_ust_ctl_duplicate_ust_object_data(&stream->obj, reg_stream->obj.ust);
        if (ret < 0) {
                ERR("Duplicate stream obj from %p to %p failed with ret %d",
-                               reg_stream->obj.ust, stream->obj, ret);
+                   reg_stream->obj.ust,
+                   stream->obj,
+                   ret);
                lttng_fd_put(LTTNG_FD_APPS, 2);
                goto error;
        }
@@ -3111,7 +3169,7 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int duplicate_channel_object(struct buffer_reg_channel *buf_reg_chan,
-               struct ust_app_channel *ua_chan)
+                                   struct ust_app_channel *ua_chan)
 {
        int ret;
 
@@ -3129,7 +3187,9 @@ static int duplicate_channel_object(struct buffer_reg_channel *buf_reg_chan,
        ret = lttng_ust_ctl_duplicate_ust_object_data(&ua_chan->obj, buf_reg_chan->obj.ust);
        if (ret < 0) {
                ERR("Duplicate channel obj from %p to %p failed with ret: %d",
-                               buf_reg_chan->obj.ust, ua_chan->obj, ret);
+                   buf_reg_chan->obj.ust,
+                   ua_chan->obj,
+                   ret);
                goto error;
        }
        ua_chan->handle = ua_chan->obj->handle;
@@ -3149,8 +3209,8 @@ error_fd_get:
  * Return 0 on success or else a negative value.
  */
 static int setup_buffer_reg_streams(struct buffer_reg_channel *buf_reg_chan,
-               struct ust_app_channel *ua_chan,
-               struct ust_app *app)
+                                   struct ust_app_channel *ua_chan,
+                                   struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_stream *stream, *stmp;
@@ -3161,7 +3221,7 @@ static int setup_buffer_reg_streams(struct buffer_reg_channel *buf_reg_chan,
        DBG2("UST app setup buffer registry stream");
 
        /* Send all streams to application. */
-       cds_list_for_each_entry_safe(stream, stmp, &ua_chan->streams.head, list) {
+       cds_list_for_each_entry_safe (stream, stmp, &ua_chan->streams.head, list) {
                struct buffer_reg_stream *reg_stream;
 
                ret = buffer_reg_stream_create(&reg_stream);
@@ -3174,7 +3234,7 @@ static int setup_buffer_reg_streams(struct buffer_reg_channel *buf_reg_chan,
                 * stream call does not release the object.
                 */
                reg_stream->obj.ust = stream->obj;
-               stream->obj = NULL;
+               stream->obj = nullptr;
                buffer_reg_stream_add(reg_stream, buf_reg_chan);
 
                /* We don't need the streams anymore. */
@@ -3195,10 +3255,11 @@ error:
  * Return 0 on success else a negative value.
  */
 static int create_buffer_reg_channel(struct buffer_reg_session *reg_sess,
-               struct ust_app_channel *ua_chan, struct buffer_reg_channel **regp)
+                                    struct ust_app_channel *ua_chan,
+                                    struct buffer_reg_channel **regp)
 {
        int ret;
-       struct buffer_reg_channel *buf_reg_chan = NULL;
+       struct buffer_reg_channel *buf_reg_chan = nullptr;
 
        LTTNG_ASSERT(reg_sess);
        LTTNG_ASSERT(ua_chan);
@@ -3216,11 +3277,15 @@ static int create_buffer_reg_channel(struct buffer_reg_session *reg_sess,
        buf_reg_chan->num_subbuf = ua_chan->attr.num_subbuf;
 
        /* Create and add a channel registry to session. */
-       ret = ust_registry_channel_add(reg_sess->reg.ust,
-                       ua_chan->tracing_channel_id);
-       if (ret < 0) {
+       try {
+               reg_sess->reg.ust->add_channel(ua_chan->tracing_channel_id);
+       } catch (const std::exception& ex) {
+               ERR("Failed to add a channel registry to userspace registry session: %s",
+                   ex.what());
+               ret = -1;
                goto error;
        }
+
        buffer_reg_channel_add(reg_sess, buf_reg_chan);
 
        if (regp) {
@@ -3243,8 +3308,9 @@ error_create:
  * Return 0 on success else a negative value.
  */
 static int setup_buffer_reg_channel(struct buffer_reg_session *reg_sess,
-               struct ust_app_channel *ua_chan, struct buffer_reg_channel *buf_reg_chan,
-               struct ust_app *app)
+                                   struct ust_app_channel *ua_chan,
+                                   struct buffer_reg_channel *buf_reg_chan,
+                                   struct ust_app *app)
 {
        int ret;
 
@@ -3262,7 +3328,7 @@ static int setup_buffer_reg_channel(struct buffer_reg_session *reg_sess,
        }
 
        buf_reg_chan->obj.ust = ua_chan->obj;
-       ua_chan->obj = NULL;
+       ua_chan->obj = nullptr;
 
        return 0;
 
@@ -3278,8 +3344,9 @@ error:
  * Return 0 on success else a negative value.
  */
 static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
-               struct ust_app *app, struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan)
+                                  struct ust_app *app,
+                                  struct ust_app_session *ua_sess,
+                                  struct ust_app_channel *ua_chan)
 {
        int ret;
        struct buffer_reg_stream *reg_stream;
@@ -3299,12 +3366,15 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
        /* Send channel to the application. */
        ret = ust_consumer_send_channel_to_ust(app, ua_sess, ua_chan);
        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
-               ret = -ENOTCONN;        /* Caused by app exiting. */
+               ret = -ENOTCONN; /* Caused by app exiting. */
                goto error;
        } else if (ret == -EAGAIN) {
                /* Caused by timeout. */
-               WARN("Communication with application %d timed out on send_channel for channel \"%s\" of session \"%" PRIu64 "\".",
-                               app->pid, ua_chan->name, ua_sess->tracing_id);
+               WARN("Communication with application %d timed out on send_channel for channel \"%s\" of session \"%" PRIu64
+                    "\".",
+                    app->pid,
+                    ua_chan->name,
+                    ua_sess->tracing_id);
                /* Treat this the same way as an application that is exiting. */
                ret = -ENOTCONN;
                goto error;
@@ -3316,8 +3386,8 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
 
        /* Send all streams to application. */
        pthread_mutex_lock(&buf_reg_chan->stream_list_lock);
-       cds_list_for_each_entry(reg_stream, &buf_reg_chan->streams, lnode) {
-               struct ust_app_stream stream;
+       cds_list_for_each_entry (reg_stream, &buf_reg_chan->streams, lnode) {
+               struct ust_app_stream stream = {};
 
                ret = duplicate_stream_object(reg_stream, &stream);
                if (ret < 0) {
@@ -3334,10 +3404,11 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
                                 * Treat this the same way as an application
                                 * that is exiting.
                                 */
-                               WARN("Communication with application %d timed out on send_stream for stream \"%s\" of channel \"%s\" of session \"%" PRIu64 "\".",
-                                               app->pid, stream.name,
-                                               ua_chan->name,
-                                               ua_sess->tracing_id);
+                               WARN("Communication with application %d timed out on send_stream for stream of channel \"%s\" of session \"%" PRIu64
+                                    "\".",
+                                    app->pid,
+                                    ua_chan->name,
+                                    ua_sess->tracing_id);
                                ret = -ENOTCONN;
                        }
                        (void) release_ust_app_stream(-1, &stream, app);
@@ -3350,7 +3421,6 @@ static int send_channel_uid_to_ust(struct buffer_reg_channel *buf_reg_chan,
                 */
                (void) release_ust_app_stream(-1, &stream, app);
        }
-       ua_chan->is_sent = 1;
 
 error_stream_unlock:
        pthread_mutex_unlock(&buf_reg_chan->stream_list_lock);
@@ -3367,24 +3437,25 @@ error:
  * Return 0 on success else a negative value.
  */
 static int create_channel_per_uid(struct ust_app *app,
-               struct ltt_ust_session *usess, struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan)
+                                 struct ltt_ust_session *usess,
+                                 struct ust_app_session *ua_sess,
+                                 struct ust_app_channel *ua_chan)
 {
        int ret;
        struct buffer_reg_uid *reg_uid;
        struct buffer_reg_channel *buf_reg_chan;
-       struct ltt_session *session = NULL;
+       struct ltt_session *session = nullptr;
        enum lttng_error_code notification_ret;
-       struct ust_registry_channel *ust_reg_chan;
 
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        DBG("UST app creating channel %s with per UID buffers", ua_chan->name);
 
-       reg_uid = buffer_reg_uid_find(usess->id, app->bits_per_long, app->uid);
+       reg_uid = buffer_reg_uid_find(usess->id, app->abi.bits_per_long, app->uid);
        /*
         * The session creation handles the creation of this global registry
         * object. If none can be find, there is a code flow problem or a
@@ -3392,8 +3463,7 @@ static int create_channel_per_uid(struct ust_app *app,
         */
        LTTNG_ASSERT(reg_uid);
 
-       buf_reg_chan = buffer_reg_channel_find(ua_chan->tracing_channel_id,
-                       reg_uid);
+       buf_reg_chan = buffer_reg_channel_find(ua_chan->tracing_channel_id, reg_uid);
        if (buf_reg_chan) {
                goto send_channel;
        }
@@ -3401,33 +3471,34 @@ static int create_channel_per_uid(struct ust_app *app,
        /* Create the buffer registry channel object. */
        ret = create_buffer_reg_channel(reg_uid->registry, ua_chan, &buf_reg_chan);
        if (ret < 0) {
-               ERR("Error creating the UST channel \"%s\" registry instance",
-                               ua_chan->name);
+               ERR("Error creating the UST channel \"%s\" registry instance", ua_chan->name);
                goto error;
        }
 
        session = session_find_by_id(ua_sess->tracing_id);
        LTTNG_ASSERT(session);
-       LTTNG_ASSERT(pthread_mutex_trylock(&session->lock));
-       LTTNG_ASSERT(session_trylock_list());
+       ASSERT_LOCKED(session->lock);
+       ASSERT_SESSION_LIST_LOCKED();
 
        /*
         * Create the buffers on the consumer side. This call populates the
         * ust app channel object with all streams and data object.
         */
-       ret = do_consumer_create_channel(usess, ua_sess, ua_chan,
-                       app->bits_per_long, reg_uid->registry->reg.ust,
-                       session->most_recent_chunk_id.value);
+       ret = do_consumer_create_channel(
+               usess, ua_sess, ua_chan, app->abi.bits_per_long, reg_uid->registry->reg.ust);
        if (ret < 0) {
-               ERR("Error creating UST channel \"%s\" on the consumer daemon",
-                               ua_chan->name);
+               ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name);
 
                /*
                 * Let's remove the previously created buffer registry channel so
                 * it's not visible anymore in the session registry.
                 */
-               ust_registry_channel_del_free(reg_uid->registry->reg.ust,
-                               ua_chan->tracing_channel_id, false);
+               auto locked_registry = reg_uid->registry->reg.ust->lock();
+               try {
+                       locked_registry->remove_channel(ua_chan->tracing_channel_id, false);
+               } catch (const std::exception& ex) {
+                       DBG("Could not find channel for removal: %s", ex.what());
+               }
                buffer_reg_channel_remove(reg_uid->registry, buf_reg_chan);
                buffer_reg_channel_destroy(buf_reg_chan, LTTNG_DOMAIN_UST);
                goto error;
@@ -3436,32 +3507,29 @@ static int create_channel_per_uid(struct ust_app *app,
        /*
         * Setup the streams and add it to the session registry.
         */
-       ret = setup_buffer_reg_channel(reg_uid->registry,
-                       ua_chan, buf_reg_chan, app);
+       ret = setup_buffer_reg_channel(reg_uid->registry, ua_chan, buf_reg_chan, app);
        if (ret < 0) {
                ERR("Error setting up UST channel \"%s\"", ua_chan->name);
                goto error;
        }
 
-       /* Notify the notification subsystem of the channel's creation. */
-       pthread_mutex_lock(&reg_uid->registry->reg.ust->lock);
-       ust_reg_chan = ust_registry_channel_find(reg_uid->registry->reg.ust,
-                       ua_chan->tracing_channel_id);
-       LTTNG_ASSERT(ust_reg_chan);
-       ust_reg_chan->consumer_key = ua_chan->key;
-       ust_reg_chan = NULL;
-       pthread_mutex_unlock(&reg_uid->registry->reg.ust->lock);
+       {
+               auto locked_registry = reg_uid->registry->reg.ust->lock();
+               auto& ust_reg_chan = locked_registry->channel(ua_chan->tracing_channel_id);
+
+               ust_reg_chan._consumer_key = ua_chan->key;
+       }
 
+       /* Notify the notification subsystem of the channel's creation. */
        notification_ret = notification_thread_command_add_channel(
-                       the_notification_thread_handle, session->name,
-                       lttng_credentials_get_uid(
-                                       &ua_sess->effective_credentials),
-                       lttng_credentials_get_gid(
-                                       &ua_sess->effective_credentials),
-                       ua_chan->name, ua_chan->key, LTTNG_DOMAIN_UST,
-                       ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
+               the_notification_thread_handle,
+               session->id,
+               ua_chan->name,
+               ua_chan->key,
+               LTTNG_DOMAIN_UST,
+               ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
        if (notification_ret != LTTNG_OK) {
-               ret = - (int) notification_ret;
+               ret = -(int) notification_ret;
                ERR("Failed to add channel to notification thread");
                goto error;
        }
@@ -3492,15 +3560,15 @@ error:
  * Return 0 on success else a negative value.
  */
 static int create_channel_per_pid(struct ust_app *app,
-               struct ltt_ust_session *usess, struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan)
+                                 struct ltt_ust_session *usess,
+                                 struct ust_app_session *ua_sess,
+                                 struct ust_app_channel *ua_chan)
 {
        int ret;
-       struct ust_registry_session *registry;
+       lsu::registry_session *registry;
        enum lttng_error_code cmd_ret;
-       struct ltt_session *session = NULL;
+       struct ltt_session *session = nullptr;
        uint64_t chan_reg_key;
-       struct ust_registry_channel *ust_reg_chan;
 
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(usess);
@@ -3509,33 +3577,32 @@ static int create_channel_per_pid(struct ust_app *app,
 
        DBG("UST app creating channel %s with per PID buffers", ua_chan->name);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        registry = get_session_registry(ua_sess);
        /* The UST app session lock is held, registry shall not be null. */
        LTTNG_ASSERT(registry);
 
        /* Create and add a new channel registry to session. */
-       ret = ust_registry_channel_add(registry, ua_chan->key);
-       if (ret < 0) {
-               ERR("Error creating the UST channel \"%s\" registry instance",
-                       ua_chan->name);
+       try {
+               registry->add_channel(ua_chan->key);
+       } catch (const std::exception& ex) {
+               ERR("Error creating the UST channel \"%s\" registry instance: %s",
+                   ua_chan->name,
+                   ex.what());
+               ret = -1;
                goto error;
        }
 
        session = session_find_by_id(ua_sess->tracing_id);
        LTTNG_ASSERT(session);
-
-       LTTNG_ASSERT(pthread_mutex_trylock(&session->lock));
-       LTTNG_ASSERT(session_trylock_list());
+       ASSERT_LOCKED(session->lock);
+       ASSERT_SESSION_LIST_LOCKED();
 
        /* Create and get channel on the consumer side. */
-       ret = do_consumer_create_channel(usess, ua_sess, ua_chan,
-                       app->bits_per_long, registry,
-                       session->most_recent_chunk_id.value);
+       ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->abi.bits_per_long, registry);
        if (ret < 0) {
-               ERR("Error creating UST channel \"%s\" on the consumer daemon",
-                       ua_chan->name);
+               ERR("Error creating UST channel \"%s\" on the consumer daemon", ua_chan->name);
                goto error_remove_from_registry;
        }
 
@@ -3548,32 +3615,36 @@ static int create_channel_per_pid(struct ust_app *app,
        }
 
        chan_reg_key = ua_chan->key;
-       pthread_mutex_lock(&registry->lock);
-       ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key);
-       LTTNG_ASSERT(ust_reg_chan);
-       ust_reg_chan->consumer_key = ua_chan->key;
-       pthread_mutex_unlock(&registry->lock);
-
-       cmd_ret = notification_thread_command_add_channel(
-                       the_notification_thread_handle, session->name,
-                       lttng_credentials_get_uid(
-                                       &ua_sess->effective_credentials),
-                       lttng_credentials_get_gid(
-                                       &ua_sess->effective_credentials),
-                       ua_chan->name, ua_chan->key, LTTNG_DOMAIN_UST,
-                       ua_chan->attr.subbuf_size * ua_chan->attr.num_subbuf);
+       {
+               auto locked_registry = registry->lock();
+
+               auto& ust_reg_chan = locked_registry->channel(chan_reg_key);
+               ust_reg_chan._consumer_key = ua_chan->key;
+       }
+
+       cmd_ret = notification_thread_command_add_channel(the_notification_thread_handle,
+                                                         session->id,
+                                                         ua_chan->name,
+                                                         ua_chan->key,
+                                                         LTTNG_DOMAIN_UST,
+                                                         ua_chan->attr.subbuf_size *
+                                                                 ua_chan->attr.num_subbuf);
        if (cmd_ret != LTTNG_OK) {
-               ret = - (int) cmd_ret;
+               ret = -(int) cmd_ret;
                ERR("Failed to add channel to notification thread");
                goto error_remove_from_registry;
        }
 
 error_remove_from_registry:
        if (ret) {
-               ust_registry_channel_del_free(registry, ua_chan->key, false);
+               try {
+                       auto locked_registry = registry->lock();
+                       locked_registry->remove_channel(ua_chan->key, false);
+               } catch (const std::exception& ex) {
+                       DBG("Could not find channel for removal: %s", ex.what());
+               }
        }
 error:
-       rcu_read_unlock();
        if (session) {
                session_put(session);
        }
@@ -3591,8 +3662,9 @@ error:
  * the application exited concurrently.
  */
 static int ust_app_channel_send(struct ust_app *app,
-               struct ltt_ust_session *usess, struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan)
+                               struct ltt_ust_session *usess,
+                               struct ust_app_session *ua_sess,
+                               struct ust_app_channel *ua_chan)
 {
        int ret;
 
@@ -3601,6 +3673,7 @@ static int ust_app_channel_send(struct ust_app *app,
        LTTNG_ASSERT(usess->active);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(ua_chan);
+       ASSERT_RCU_READ_LOCKED();
 
        /* Handle buffer type before sending the channel to the application. */
        switch (usess->buffer_type) {
@@ -3650,25 +3723,28 @@ error:
  * Return 0 on success or else a negative value.
  */
 static int ust_app_channel_allocate(struct ust_app_session *ua_sess,
-               struct ltt_ust_channel *uchan,
-               enum lttng_ust_abi_chan_type type, struct ltt_ust_session *usess,
-               struct ust_app_channel **ua_chanp)
+                                   struct ltt_ust_channel *uchan,
+                                   enum lttng_ust_abi_chan_type type,
+                                   struct ltt_ust_session *usess __attribute__((unused)),
+                                   struct ust_app_channel **ua_chanp)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
        struct lttng_ht_node_str *ua_chan_node;
        struct ust_app_channel *ua_chan;
 
+       ASSERT_RCU_READ_LOCKED();
+
        /* Lookup channel in the ust app session */
-       lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
+       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &iter);
        ua_chan_node = lttng_ht_iter_get_node_str(&iter);
-       if (ua_chan_node != NULL) {
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+       if (ua_chan_node != nullptr) {
+               ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
                goto end;
        }
 
        ua_chan = alloc_ust_app_channel(uchan->name, ua_sess, &uchan->attr);
-       if (ua_chan == NULL) {
+       if (ua_chan == nullptr) {
                /* Only malloc can fail here */
                ret = -ENOMEM;
                goto error;
@@ -3698,16 +3774,17 @@ error:
  * Must be called with the RCU read side lock held.
  * Called with ust app session mutex held.
  */
-static
-int create_ust_app_event(struct ust_app_session *ua_sess,
-               struct ust_app_channel *ua_chan, struct ltt_ust_event *uevent,
-               struct ust_app *app)
+static int create_ust_app_event(struct ust_app_channel *ua_chan,
+                               struct ltt_ust_event *uevent,
+                               struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_event *ua_event;
 
+       ASSERT_RCU_READ_LOCKED();
+
        ua_event = alloc_ust_app_event(uevent->attr.name, &uevent->attr);
-       if (ua_event == NULL) {
+       if (ua_event == nullptr) {
                /* Only failure mode of alloc_ust_app_event(). */
                ret = -ENOMEM;
                goto end;
@@ -3715,7 +3792,7 @@ int create_ust_app_event(struct ust_app_session *ua_sess,
        shadow_copy_event(ua_event, uevent);
 
        /* Create it on the tracer side */
-       ret = create_ust_event(app, ua_sess, ua_chan, ua_event);
+       ret = create_ust_event(app, ua_chan, ua_event);
        if (ret < 0) {
                /*
                 * Not found previously means that it does not exist on the
@@ -3725,18 +3802,19 @@ int create_ust_app_event(struct ust_app_session *ua_sess,
                 */
                if (ret == -LTTNG_UST_ERR_EXIST) {
                        ERR("Tracer for application reported that an event being created already existed: "
-                                       "event_name = \"%s\", pid = %d, ppid = %d, uid = %d, gid = %d",
-                                       uevent->attr.name,
-                                       app->pid, app->ppid, app->uid,
-                                       app->gid);
+                           "event_name = \"%s\", pid = %d, ppid = %d, uid = %d, gid = %d",
+                           uevent->attr.name,
+                           app->pid,
+                           app->ppid,
+                           app->uid,
+                           app->gid);
                }
                goto error;
        }
 
        add_unique_ust_app_event(ua_chan, ua_event);
 
-       DBG2("UST app create event completed: app = '%s' pid = %d",
-                       app->name, app->pid);
+       DBG2("UST app create event completed: app = '%s' pid = %d", app->name, app->pid);
 
 end:
        return ret;
@@ -3753,15 +3831,15 @@ error:
  * Must be called with the RCU read side lock held.
  * Called with ust app session mutex held.
  */
-static
-int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger,
-               struct ust_app *app)
+static int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger, struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_event_notifier_rule *ua_event_notifier_rule;
 
+       ASSERT_RCU_READ_LOCKED();
+
        ua_event_notifier_rule = alloc_ust_app_event_notifier_rule(trigger);
-       if (ua_event_notifier_rule == NULL) {
+       if (ua_event_notifier_rule == nullptr) {
                ret = -ENOMEM;
                goto end;
        }
@@ -3777,19 +3855,23 @@ int create_ust_app_event_notifier_rule(struct lttng_trigger *trigger,
                 */
                if (ret == -LTTNG_UST_ERR_EXIST) {
                        ERR("Tracer for application reported that an event notifier being created already exists: "
-                                       "token = \"%" PRIu64 "\", pid = %d, ppid = %d, uid = %d, gid = %d",
-                                       lttng_trigger_get_tracer_token(trigger),
-                                       app->pid, app->ppid, app->uid,
-                                       app->gid);
+                           "token = \"%" PRIu64 "\", pid = %d, ppid = %d, uid = %d, gid = %d",
+                           lttng_trigger_get_tracer_token(trigger),
+                           app->pid,
+                           app->ppid,
+                           app->uid,
+                           app->gid);
                }
                goto error;
        }
 
        lttng_ht_add_unique_u64(app->token_to_event_notifier_rule_ht,
-                       &ua_event_notifier_rule->node);
+                               &ua_event_notifier_rule->node);
 
        DBG2("UST app create token event rule completed: app = '%s', pid = %d, token = %" PRIu64,
-                       app->name, app->pid, lttng_trigger_get_tracer_token(trigger));
+            app->name,
+            app->pid,
+            lttng_trigger_get_tracer_token(trigger));
 
        goto end;
 
@@ -3806,32 +3888,31 @@ end:
  * Called with UST app session lock held and RCU read side lock.
  */
 static int create_ust_app_metadata(struct ust_app_session *ua_sess,
-               struct ust_app *app, struct consumer_output *consumer)
+                                  struct ust_app *app,
+                                  struct consumer_output *consumer)
 {
        int ret = 0;
        struct ust_app_channel *metadata;
        struct consumer_socket *socket;
-       struct ust_registry_session *registry;
-       struct ltt_session *session = NULL;
+       struct ltt_session *session = nullptr;
 
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(consumer);
+       ASSERT_RCU_READ_LOCKED();
 
-       registry = get_session_registry(ua_sess);
+       auto locked_registry = get_locked_session_registry(ua_sess);
        /* The UST app session is held registry shall not be null. */
-       LTTNG_ASSERT(registry);
-
-       pthread_mutex_lock(&registry->lock);
+       LTTNG_ASSERT(locked_registry);
 
        /* Metadata already exists for this registry or it was closed previously */
-       if (registry->metadata_key || registry->metadata_closed) {
+       if (locked_registry->_metadata_key || locked_registry->_metadata_closed) {
                ret = 0;
                goto error;
        }
 
        /* Allocate UST metadata */
-       metadata = alloc_ust_app_channel(DEFAULT_METADATA_NAME, ua_sess, NULL);
+       metadata = alloc_ust_app_channel(DEFAULT_METADATA_NAME, ua_sess, nullptr);
        if (!metadata) {
                /* malloc() failed */
                ret = -ENOMEM;
@@ -3848,7 +3929,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        }
 
        /* Get the right consumer socket for the application. */
-       socket = consumer_find_socket_by_bitness(app->bits_per_long, consumer);
+       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, consumer);
        if (!socket) {
                ret = -EINVAL;
                goto error_consumer;
@@ -3860,13 +3941,12 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         * consumer requesting the metadata and the ask_channel call on our side
         * did not returned yet.
         */
-       registry->metadata_key = metadata->key;
+       locked_registry->_metadata_key = metadata->key;
 
        session = session_find_by_id(ua_sess->tracing_id);
        LTTNG_ASSERT(session);
-
-       LTTNG_ASSERT(pthread_mutex_trylock(&session->lock));
-       LTTNG_ASSERT(session_trylock_list());
+       ASSERT_LOCKED(session->lock);
+       ASSERT_SESSION_LIST_LOCKED();
 
        /*
         * Ask the metadata channel creation to the consumer. The metadata object
@@ -3874,11 +3954,15 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
         * never added or monitored until we do a first push metadata to the
         * consumer.
         */
-       ret = ust_consumer_ask_channel(ua_sess, metadata, consumer, socket,
-                       registry, session->current_trace_chunk);
+       ret = ust_consumer_ask_channel(ua_sess,
+                                      metadata,
+                                      consumer,
+                                      socket,
+                                      locked_registry.get(),
+                                      session->current_trace_chunk);
        if (ret < 0) {
                /* Nullify the metadata key so we don't try to close it later on. */
-               registry->metadata_key = 0;
+               locked_registry->_metadata_key = 0;
                goto error_consumer;
        }
 
@@ -3891,18 +3975,16 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess,
        ret = consumer_setup_metadata(socket, metadata->key);
        if (ret < 0) {
                /* Nullify the metadata key so we don't try to close it later on. */
-               registry->metadata_key = 0;
+               locked_registry->_metadata_key = 0;
                goto error_consumer;
        }
 
-       DBG2("UST metadata with key %" PRIu64 " created for app pid %d",
-                       metadata->key, app->pid);
+       DBG2("UST metadata with key %" PRIu64 " created for app pid %d", metadata->key, app->pid);
 
 error_consumer:
        lttng_fd_put(LTTNG_FD_APPS, 1);
-       delete_ust_app_channel(-1, metadata, app);
+       delete_ust_app_channel(-1, metadata, app, locked_registry);
 error:
-       pthread_mutex_unlock(&registry->lock);
        if (session) {
                session_put(session);
        }
@@ -3915,20 +3997,20 @@ error:
  */
 struct ust_app *ust_app_find_by_pid(pid_t pid)
 {
-       struct ust_app *app = NULL;
+       struct ust_app *app = nullptr;
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
 
-       lttng_ht_lookup(ust_app_ht, (void *)((unsigned long) pid), &iter);
+       lttng_ht_lookup(ust_app_ht, (void *) ((unsigned long) pid), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                DBG2("UST app no found with pid %d", pid);
                goto error;
        }
 
        DBG2("Found UST app by pid %d", pid);
 
-       app = caa_container_of(node, struct ust_app, pid_n);
+       app = lttng::utils::container_of(node, &ust_app::pid_n);
 
 error:
        return app;
@@ -3944,23 +4026,21 @@ error:
 struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
 {
        int ret;
-       struct ust_app *lta = NULL;
-       struct lttng_pipe *event_notifier_event_source_pipe = NULL;
+       struct ust_app *lta = nullptr;
+       struct lttng_pipe *event_notifier_event_source_pipe = nullptr;
 
        LTTNG_ASSERT(msg);
        LTTNG_ASSERT(sock >= 0);
 
        DBG3("UST app creating application for socket %d", sock);
 
-       if ((msg->bits_per_long == 64 &&
-                           (uatomic_read(&the_ust_consumerd64_fd) ==
-                                           -EINVAL)) ||
-                       (msg->bits_per_long == 32 &&
-                                       (uatomic_read(&the_ust_consumerd32_fd) ==
-                                                       -EINVAL))) {
+       if ((msg->bits_per_long == 64 && (uatomic_read(&the_ust_consumerd64_fd) == -EINVAL)) ||
+           (msg->bits_per_long == 32 && (uatomic_read(&the_ust_consumerd32_fd) == -EINVAL))) {
                ERR("Registration failed: application \"%s\" (pid: %d) has "
-                               "%d-bit long, but no consumerd for this size is available.\n",
-                               msg->name, msg->pid, msg->bits_per_long);
+                   "%d-bit long, but no consumerd for this size is available.\n",
+                   msg->name,
+                   msg->pid,
+                   msg->bits_per_long);
                goto error;
        }
 
@@ -3972,36 +4052,44 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
        ret = lttng_fd_get(LTTNG_FD_APPS, 2);
        if (ret) {
                ERR("Failed to reserve two file descriptors for the event source pipe while creating a new application instance: app = '%s', pid = %d",
-                               msg->name, (int) msg->pid);
+                   msg->name,
+                   (int) msg->pid);
                goto error;
        }
 
        event_notifier_event_source_pipe = lttng_pipe_open(FD_CLOEXEC);
        if (!event_notifier_event_source_pipe) {
                PERROR("Failed to open application event source pipe: '%s' (pid = %d)",
-                               msg->name, msg->pid);
+                      msg->name,
+                      msg->pid);
                goto error;
        }
 
-       lta = (ust_app *) zmalloc(sizeof(struct ust_app));
-       if (lta == NULL) {
+       lta = zmalloc<ust_app>();
+       if (lta == nullptr) {
                PERROR("malloc");
                goto error_free_pipe;
        }
 
+       urcu_ref_init(&lta->ref);
+
        lta->event_notifier_group.event_pipe = event_notifier_event_source_pipe;
 
        lta->ppid = msg->ppid;
        lta->uid = msg->uid;
        lta->gid = msg->gid;
 
-       lta->bits_per_long = msg->bits_per_long;
-       lta->uint8_t_alignment = msg->uint8_t_alignment;
-       lta->uint16_t_alignment = msg->uint16_t_alignment;
-       lta->uint32_t_alignment = msg->uint32_t_alignment;
-       lta->uint64_t_alignment = msg->uint64_t_alignment;
-       lta->long_alignment = msg->long_alignment;
-       lta->byte_order = msg->byte_order;
+       lta->abi = {
+               .bits_per_long = msg->bits_per_long,
+               .long_alignment = msg->long_alignment,
+               .uint8_t_alignment = msg->uint8_t_alignment,
+               .uint16_t_alignment = msg->uint16_t_alignment,
+               .uint32_t_alignment = msg->uint32_t_alignment,
+               .uint64_t_alignment = msg->uint64_t_alignment,
+               .byte_order = msg->byte_order == LITTLE_ENDIAN ?
+                       lttng::sessiond::trace::byte_order::LITTLE_ENDIAN_ :
+                       lttng::sessiond::trace::byte_order::BIG_ENDIAN_,
+       };
 
        lta->v_major = msg->major;
        lta->v_minor = msg->minor;
@@ -4025,7 +4113,7 @@ struct ust_app *ust_app_create(struct ust_register_msg *msg, int sock)
        lta->pid = msg->pid;
        lttng_ht_node_init_ulong(&lta->pid_n, (unsigned long) lta->pid);
        lta->sock = sock;
-       pthread_mutex_init(&lta->sock_lock, NULL);
+       pthread_mutex_init(&lta->sock_lock, nullptr);
        lttng_ht_node_init_ulong(&lta->sock_n, (unsigned long) lta->sock);
 
        CDS_INIT_LIST_HEAD(&lta->teardown_head);
@@ -4035,7 +4123,7 @@ error_free_pipe:
        lttng_pipe_destroy(event_notifier_event_source_pipe);
        lttng_fd_put(LTTNG_FD_APPS, 2);
 error:
-       return NULL;
+       return nullptr;
 }
 
 /*
@@ -4046,9 +4134,9 @@ void ust_app_add(struct ust_app *app)
        LTTNG_ASSERT(app);
        LTTNG_ASSERT(app->notify_sock >= 0);
 
-       app->registration_time = time(NULL);
+       app->registration_time = time(nullptr);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        /*
         * On a re-registration, we want to kick out the previous registration of
@@ -4068,11 +4156,16 @@ void ust_app_add(struct ust_app *app)
        lttng_ht_add_unique_ulong(ust_app_ht_by_notify_sock, &app->notify_sock_n);
 
        DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock =%d name:%s "
-                       "notify_sock =%d (version %d.%d)", app->pid, app->ppid, app->uid,
-                       app->gid, app->sock, app->name, app->notify_sock, app->v_major,
-                       app->v_minor);
-
-       rcu_read_unlock();
+           "notify_sock =%d (version %d.%d)",
+           app->pid,
+           app->ppid,
+           app->uid,
+           app->gid,
+           app->sock,
+           app->name,
+           app->notify_sock,
+           app->v_major,
+           app->v_minor);
 }
 
 /*
@@ -4093,13 +4186,17 @@ int ust_app_version(struct ust_app *app)
        if (ret < 0) {
                if (ret == -LTTNG_UST_ERR_EXITING || ret == -EPIPE) {
                        DBG3("UST app version failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app version failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app version failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
        }
 
@@ -4126,7 +4223,7 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
 {
        int ret;
        int event_pipe_write_fd;
-       struct lttng_ust_abi_object_data *event_notifier_group = NULL;
+       struct lttng_ust_abi_object_data *event_notifier_group = nullptr;
        enum lttng_error_code lttng_ret;
        enum event_notifier_error_accounting_status event_notifier_error_accounting_status;
 
@@ -4138,25 +4235,29 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
        }
 
        /* Get the write side of the pipe. */
-       event_pipe_write_fd = lttng_pipe_get_writefd(
-                       app->event_notifier_group.event_pipe);
+       event_pipe_write_fd = lttng_pipe_get_writefd(app->event_notifier_group.event_pipe);
 
        pthread_mutex_lock(&app->sock_lock);
-       ret = lttng_ust_ctl_create_event_notifier_group(app->sock,
-                       event_pipe_write_fd, &event_notifier_group);
+       ret = lttng_ust_ctl_create_event_notifier_group(
+               app->sock, event_pipe_write_fd, &event_notifier_group);
        pthread_mutex_unlock(&app->sock_lock);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        ret = 0;
                        DBG3("UST app create event notifier group failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        ret = 0;
                        WARN("UST app create event notifier group failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app create event notifier group failed with ret %d: pid = %d, sock = %d, event_pipe_write_fd: %d",
-                                       ret, app->pid, app->sock, event_pipe_write_fd);
+                           ret,
+                           app->pid,
+                           app->sock,
+                           event_pipe_write_fd);
                }
                goto error;
        }
@@ -4164,7 +4265,8 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
        ret = lttng_pipe_write_close(app->event_notifier_group.event_pipe);
        if (ret) {
                ERR("Failed to close write end of the application's event source pipe: app = '%s' (pid = %d)",
-                               app->name, app->pid);
+                   app->name,
+                   app->pid);
                goto error;
        }
 
@@ -4175,32 +4277,34 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
        lttng_fd_put(LTTNG_FD_APPS, 1);
 
        lttng_ret = notification_thread_command_add_tracer_event_source(
-                       the_notification_thread_handle,
-                       lttng_pipe_get_readfd(
-                                       app->event_notifier_group.event_pipe),
-                       LTTNG_DOMAIN_UST);
+               the_notification_thread_handle,
+               lttng_pipe_get_readfd(app->event_notifier_group.event_pipe),
+               LTTNG_DOMAIN_UST);
        if (lttng_ret != LTTNG_OK) {
                ERR("Failed to add tracer event source to notification thread");
-               ret = - 1;
+               ret = -1;
                goto error;
        }
 
        /* Assign handle only when the complete setup is valid. */
        app->event_notifier_group.object = event_notifier_group;
 
-       event_notifier_error_accounting_status =
-                       event_notifier_error_accounting_register_app(app);
+       event_notifier_error_accounting_status = event_notifier_error_accounting_register_app(app);
        switch (event_notifier_error_accounting_status) {
        case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK:
                break;
        case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_UNSUPPORTED:
                DBG3("Failed to setup event notifier error accounting (application does not support notifier error accounting): app socket fd = %d, app name = '%s', app pid = %d",
-                               app->sock, app->name, (int) app->pid);
+                    app->sock,
+                    app->name,
+                    (int) app->pid);
                ret = 0;
                goto error_accounting;
        case EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_APP_DEAD:
                DBG3("Failed to setup event notifier error accounting (application is dead): app socket fd = %d, app name = '%s', app pid = %d",
-                               app->sock, app->name, (int) app->pid);
+                    app->sock,
+                    app->name,
+                    (int) app->pid);
                ret = 0;
                goto error_accounting;
        default:
@@ -4213,9 +4317,8 @@ int ust_app_setup_event_notifier_group(struct ust_app *app)
 
 error_accounting:
        lttng_ret = notification_thread_command_remove_tracer_event_source(
-                       the_notification_thread_handle,
-                       lttng_pipe_get_readfd(
-                                       app->event_notifier_group.event_pipe));
+               the_notification_thread_handle,
+               lttng_pipe_get_readfd(app->event_notifier_group.event_pipe));
        if (lttng_ret != LTTNG_OK) {
                ERR("Failed to remove application tracer event source from notification thread");
        }
@@ -4223,34 +4326,16 @@ error_accounting:
 error:
        lttng_ust_ctl_release_object(app->sock, app->event_notifier_group.object);
        free(app->event_notifier_group.object);
-       app->event_notifier_group.object = NULL;
+       app->event_notifier_group.object = nullptr;
        return ret;
 }
 
-/*
- * Unregister app by removing it from the global traceable app list and freeing
- * the data struct.
- *
- * The socket is already closed at this point so no close to sock.
- */
-void ust_app_unregister(int sock)
+static void ust_app_unregister(ust_app& app)
 {
-       struct ust_app *lta;
-       struct lttng_ht_node_ulong *node;
-       struct lttng_ht_iter ust_app_sock_iter;
        struct lttng_ht_iter iter;
        struct ust_app_session *ua_sess;
-       int ret;
-
-       rcu_read_lock();
-
-       /* Get the node reference for a call_rcu */
-       lttng_ht_lookup(ust_app_ht_by_sock, (void *)((unsigned long) sock), &ust_app_sock_iter);
-       node = lttng_ht_iter_get_node_ulong(&ust_app_sock_iter);
-       LTTNG_ASSERT(node);
 
-       lta = caa_container_of(node, struct ust_app, sock_n);
-       DBG("PID %d unregistering with sock %d", lta->pid, sock);
+       lttng::urcu::read_lock_guard read_lock;
 
        /*
         * For per-PID buffers, perform "push metadata" and flush all
@@ -4258,28 +4343,24 @@ void ust_app_unregister(int sock)
         * ensuring proper behavior of data_pending check.
         * Remove sessions so they are not visible during deletion.
         */
-       cds_lfht_for_each_entry(lta->sessions->ht, &iter.iter, ua_sess,
-                       node.node) {
-               struct ust_registry_session *registry;
-
-               ret = lttng_ht_del(lta->sessions, &iter);
-               if (ret) {
+       cds_lfht_for_each_entry (app.sessions->ht, &iter.iter, ua_sess, node.node) {
+               const auto del_ret = lttng_ht_del(app.sessions, &iter);
+               if (del_ret) {
                        /* The session was already removed so scheduled for teardown. */
                        continue;
                }
 
                if (ua_sess->buffer_type == LTTNG_BUFFER_PER_PID) {
-                       (void) ust_app_flush_app_session(lta, ua_sess);
+                       (void) ust_app_flush_app_session(app, *ua_sess);
                }
 
                /*
                 * Add session to list for teardown. This is safe since at this point we
                 * are the only one using this list.
                 */
-               pthread_mutex_lock(&ua_sess->lock);
+               lttng::pthread::lock_guard ust_app_session_lock(ua_sess->lock);
 
                if (ua_sess->deleted) {
-                       pthread_mutex_unlock(&ua_sess->lock);
                        continue;
                }
 
@@ -4294,10 +4375,10 @@ void ust_app_unregister(int sock)
                 * The close metadata below nullifies the metadata pointer in the
                 * session so the delete session will NOT push/close a second time.
                 */
-               registry = get_session_registry(ua_sess);
-               if (registry) {
+               auto locked_registry = get_locked_session_registry(ua_sess);
+               if (locked_registry) {
                        /* Push metadata for application before freeing the application. */
-                       (void) push_metadata(registry, ua_sess->consumer);
+                       (void) push_metadata(locked_registry, ua_sess->consumer);
 
                        /*
                         * Don't ask to close metadata for global per UID buffers. Close
@@ -4306,26 +4387,33 @@ void ust_app_unregister(int sock)
                         * close so don't send a close command if closed.
                         */
                        if (ua_sess->buffer_type != LTTNG_BUFFER_PER_UID) {
-                               /* And ask to close it for this session registry. */
-                               (void) close_metadata(registry, ua_sess->consumer);
+                               const auto metadata_key = locked_registry->_metadata_key;
+                               const auto consumer_bitness = locked_registry->abi.bits_per_long;
+
+                               if (!locked_registry->_metadata_closed && metadata_key != 0) {
+                                       locked_registry->_metadata_closed = true;
+                               }
+
+                               /* Release lock before communication, see comments in
+                                * close_metadata(). */
+                               locked_registry.reset();
+                               (void) close_metadata(
+                                       metadata_key, consumer_bitness, ua_sess->consumer);
+                       } else {
+                               locked_registry.reset();
                        }
                }
-               cds_list_add(&ua_sess->teardown_node, &lta->teardown_head);
 
-               pthread_mutex_unlock(&ua_sess->lock);
+               cds_list_add(&ua_sess->teardown_node, &app.teardown_head);
        }
 
-       /* Remove application from PID hash table */
-       ret = lttng_ht_del(ust_app_ht_by_sock, &ust_app_sock_iter);
-       LTTNG_ASSERT(!ret);
-
        /*
         * Remove application from notify hash table. The thread handling the
         * notify socket could have deleted the node so ignore on error because
         * either way it's valid. The close of that socket is handled by the
         * apps_notify_thread.
         */
-       iter.iter.node = &lta->notify_sock_n.node;
+       iter.iter.node = &app.notify_sock_n.node;
        (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter);
 
        /*
@@ -4333,18 +4421,47 @@ void ust_app_unregister(int sock)
         * add replace during app registration because the PID can be reassigned by
         * the OS.
         */
-       iter.iter.node = &lta->pid_n.node;
-       ret = lttng_ht_del(ust_app_ht, &iter);
-       if (ret) {
-               DBG3("Unregister app by PID %d failed. This can happen on pid reuse",
-                               lta->pid);
+       iter.iter.node = &app.pid_n.node;
+       if (lttng_ht_del(ust_app_ht, &iter)) {
+               DBG3("Unregister app by PID %d failed. This can happen on pid reuse", app.pid);
        }
+}
+
+/*
+ * Unregister app by removing it from the global traceable app list and freeing
+ * the data struct.
+ *
+ * The socket is already closed at this point, so there is no need to close it.
+ */
+void ust_app_unregister_by_socket(int sock_fd)
+{
+       struct ust_app *app;
+       struct lttng_ht_node_ulong *node;
+       struct lttng_ht_iter ust_app_sock_iter;
+       int ret;
 
-       /* Free memory */
-       call_rcu(&lta->pid_n.head, delete_ust_app_rcu);
+       lttng::urcu::read_lock_guard read_lock;
 
-       rcu_read_unlock();
-       return;
+       /* Get the node reference for a call_rcu */
+       lttng_ht_lookup(ust_app_ht_by_sock, (void *) ((unsigned long) sock_fd), &ust_app_sock_iter);
+       node = lttng_ht_iter_get_node_ulong(&ust_app_sock_iter);
+       assert(node);
+
+       app = caa_container_of(node, struct ust_app, sock_n);
+
+       DBG_FMT("Application unregistering after socket activity: pid={}, socket_fd={}",
+               app->pid,
+               sock_fd);
+
+       /* Remove application from socket hash table */
+       ret = lttng_ht_del(ust_app_ht_by_sock, &ust_app_sock_iter);
+       assert(!ret);
+
+       /*
+        * The socket is closed: release its reference to the application
+        * to trigger its eventual teardown.
+        */
+       ust_app_put(app);
 }
 
 /*
@@ -4359,113 +4476,137 @@ int ust_app_list_events(struct lttng_event **events)
        struct lttng_event *tmp_event;
 
        nbmem = UST_APP_EVENT_LIST_SIZE;
-       tmp_event = (lttng_event *) zmalloc(nbmem * sizeof(struct lttng_event));
-       if (tmp_event == NULL) {
+       tmp_event = calloc<lttng_event>(nbmem);
+       if (tmp_event == nullptr) {
                PERROR("zmalloc ust app events");
                ret = -ENOMEM;
                goto error;
        }
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               struct lttng_ust_abi_tracepoint_iter uiter;
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct lttng_ust_abi_tracepoint_iter uiter;
 
-               health_code_update();
+                       health_code_update();
 
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               pthread_mutex_lock(&app->sock_lock);
-               handle = lttng_ust_ctl_tracepoint_list(app->sock);
-               if (handle < 0) {
-                       if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) {
-                               ERR("UST app list events getting handle failed for app pid %d",
-                                               app->pid);
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
                        }
-                       pthread_mutex_unlock(&app->sock_lock);
-                       continue;
-               }
-
-               while ((ret = lttng_ust_ctl_tracepoint_list_get(app->sock, handle,
-                                       &uiter)) != -LTTNG_UST_ERR_NOENT) {
-                       /* Handle ustctl error. */
-                       if (ret < 0) {
-                               int release_ret;
 
-                               if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
-                                       ERR("UST app tp list get failed for app %d with ret %d",
-                                                       app->sock, ret);
-                               } else {
-                                       DBG3("UST app tp list get failed. Application is dead");
-                                       break;
-                               }
-                               free(tmp_event);
-                               release_ret = lttng_ust_ctl_release_handle(app->sock, handle);
-                               if (release_ret < 0 &&
-                                               release_ret != -LTTNG_UST_ERR_EXITING &&
-                                               release_ret != -EPIPE) {
-                                       ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret);
+                       pthread_mutex_lock(&app->sock_lock);
+                       handle = lttng_ust_ctl_tracepoint_list(app->sock);
+                       if (handle < 0) {
+                               if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) {
+                                       ERR("UST app list events getting handle failed for app pid %d",
+                                           app->pid);
                                }
                                pthread_mutex_unlock(&app->sock_lock);
-                               goto rcu_error;
+                               continue;
                        }
 
-                       health_code_update();
-                       if (count >= nbmem) {
-                               /* In case the realloc fails, we free the memory */
-                               struct lttng_event *new_tmp_event;
-                               size_t new_nbmem;
-
-                               new_nbmem = nbmem << 1;
-                               DBG2("Reallocating event list from %zu to %zu entries",
-                                               nbmem, new_nbmem);
-                               new_tmp_event = (lttng_event *) realloc(tmp_event,
-                                       new_nbmem * sizeof(struct lttng_event));
-                               if (new_tmp_event == NULL) {
+                       while ((ret = lttng_ust_ctl_tracepoint_list_get(
+                                       app->sock, handle, &uiter)) != -LTTNG_UST_ERR_NOENT) {
+                               /* Handle ustctl error. */
+                               if (ret < 0) {
                                        int release_ret;
 
-                                       PERROR("realloc ust app events");
+                                       if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
+                                               ERR("UST app tp list get failed for app %d with ret %d",
+                                                   app->sock,
+                                                   ret);
+                                       } else {
+                                               DBG3("UST app tp list get failed. Application is dead");
+                                               break;
+                                       }
+
                                        free(tmp_event);
-                                       ret = -ENOMEM;
-                                       release_ret = lttng_ust_ctl_release_handle(app->sock, handle);
+                                       release_ret =
+                                               lttng_ust_ctl_release_handle(app->sock, handle);
                                        if (release_ret < 0 &&
-                                                       release_ret != -LTTNG_UST_ERR_EXITING &&
-                                                       release_ret != -EPIPE) {
-                                               ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret);
+                                           release_ret != -LTTNG_UST_ERR_EXITING &&
+                                           release_ret != -EPIPE) {
+                                               ERR("Error releasing app handle for app %d with ret %d",
+                                                   app->sock,
+                                                   release_ret);
                                        }
+
                                        pthread_mutex_unlock(&app->sock_lock);
                                        goto rcu_error;
                                }
-                               /* Zero the new memory */
-                               memset(new_tmp_event + nbmem, 0,
-                                       (new_nbmem - nbmem) * sizeof(struct lttng_event));
-                               nbmem = new_nbmem;
-                               tmp_event = new_tmp_event;
+
+                               health_code_update();
+                               if (count >= nbmem) {
+                                       /* In case the realloc fails, we free the memory */
+                                       struct lttng_event *new_tmp_event;
+                                       size_t new_nbmem;
+
+                                       new_nbmem = nbmem << 1;
+                                       DBG2("Reallocating event list from %zu to %zu entries",
+                                            nbmem,
+                                            new_nbmem);
+                                       new_tmp_event = (lttng_event *) realloc(
+                                               tmp_event, new_nbmem * sizeof(struct lttng_event));
+                                       if (new_tmp_event == nullptr) {
+                                               int release_ret;
+
+                                               PERROR("realloc ust app events");
+                                               free(tmp_event);
+                                               ret = -ENOMEM;
+                                               release_ret = lttng_ust_ctl_release_handle(
+                                                       app->sock, handle);
+                                               if (release_ret < 0 &&
+                                                   release_ret != -LTTNG_UST_ERR_EXITING &&
+                                                   release_ret != -EPIPE) {
+                                                       ERR("Error releasing app handle for app %d with ret %d",
+                                                           app->sock,
+                                                           release_ret);
+                                               }
+
+                                               pthread_mutex_unlock(&app->sock_lock);
+                                               goto rcu_error;
+                                       }
+                                       /* Zero the new memory */
+                                       memset(new_tmp_event + nbmem,
+                                              0,
+                                              (new_nbmem - nbmem) * sizeof(struct lttng_event));
+                                       nbmem = new_nbmem;
+                                       tmp_event = new_tmp_event;
+                               }
+
+                               memcpy(tmp_event[count].name,
+                                      uiter.name,
+                                      LTTNG_UST_ABI_SYM_NAME_LEN);
+                               tmp_event[count].loglevel = uiter.loglevel;
+                               tmp_event[count].type =
+                                       (enum lttng_event_type) LTTNG_UST_ABI_TRACEPOINT;
+                               tmp_event[count].pid = app->pid;
+                               tmp_event[count].enabled = -1;
+                               count++;
                        }
-                       memcpy(tmp_event[count].name, uiter.name, LTTNG_UST_ABI_SYM_NAME_LEN);
-                       tmp_event[count].loglevel = uiter.loglevel;
-                       tmp_event[count].type = (enum lttng_event_type) LTTNG_UST_ABI_TRACEPOINT;
-                       tmp_event[count].pid = app->pid;
-                       tmp_event[count].enabled = -1;
-                       count++;
-               }
-               ret = lttng_ust_ctl_release_handle(app->sock, handle);
-               pthread_mutex_unlock(&app->sock_lock);
-               if (ret < 0) {
-                       if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
-                               DBG3("Error releasing app handle. Application died: pid = %d, sock = %d",
-                                               app->pid, app->sock);
-                       } else if (ret == -EAGAIN) {
-                               WARN("Error releasing app handle. Communication time out: pid = %d, sock = %d",
-                                               app->pid, app->sock);
-                       } else {
-                               ERR("Error releasing app handle with ret %d: pid = %d, sock = %d",
-                                               ret, app->pid, app->sock);
+
+                       ret = lttng_ust_ctl_release_handle(app->sock, handle);
+                       pthread_mutex_unlock(&app->sock_lock);
+                       if (ret < 0) {
+                               if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
+                                       DBG3("Error releasing app handle. Application died: pid = %d, sock = %d",
+                                            app->pid,
+                                            app->sock);
+                               } else if (ret == -EAGAIN) {
+                                       WARN("Error releasing app handle. Communication time out: pid = %d, sock = %d",
+                                            app->pid,
+                                            app->sock);
+                               } else {
+                                       ERR("Error releasing app handle with ret %d: pid = %d, sock = %d",
+                                           ret,
+                                           app->pid,
+                                           app->sock);
+                               }
                        }
                }
        }
@@ -4476,7 +4617,6 @@ int ust_app_list_events(struct lttng_event **events)
        DBG2("UST app list events done (%zu events)", count);
 
 rcu_error:
-       rcu_read_unlock();
 error:
        health_code_update();
        return ret;
@@ -4494,113 +4634,136 @@ int ust_app_list_event_fields(struct lttng_event_field **fields)
        struct lttng_event_field *tmp_event;
 
        nbmem = UST_APP_EVENT_LIST_SIZE;
-       tmp_event = (lttng_event_field *) zmalloc(nbmem * sizeof(struct lttng_event_field));
-       if (tmp_event == NULL) {
+       tmp_event = calloc<lttng_event_field>(nbmem);
+       if (tmp_event == nullptr) {
                PERROR("zmalloc ust app event fields");
                ret = -ENOMEM;
                goto error;
        }
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               struct lttng_ust_abi_field_iter uiter;
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct lttng_ust_abi_field_iter uiter;
 
-               health_code_update();
+                       health_code_update();
 
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               pthread_mutex_lock(&app->sock_lock);
-               handle = lttng_ust_ctl_tracepoint_field_list(app->sock);
-               if (handle < 0) {
-                       if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) {
-                               ERR("UST app list field getting handle failed for app pid %d",
-                                               app->pid);
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
                        }
-                       pthread_mutex_unlock(&app->sock_lock);
-                       continue;
-               }
 
-               while ((ret = lttng_ust_ctl_tracepoint_field_list_get(app->sock, handle,
-                                       &uiter)) != -LTTNG_UST_ERR_NOENT) {
-                       /* Handle ustctl error. */
-                       if (ret < 0) {
-                               int release_ret;
-
-                               if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
-                                       ERR("UST app tp list field failed for app %d with ret %d",
-                                                       app->sock, ret);
-                               } else {
-                                       DBG3("UST app tp list field failed. Application is dead");
-                                       break;
+                       pthread_mutex_lock(&app->sock_lock);
+                       handle = lttng_ust_ctl_tracepoint_field_list(app->sock);
+                       if (handle < 0) {
+                               if (handle != -EPIPE && handle != -LTTNG_UST_ERR_EXITING) {
+                                       ERR("UST app list field getting handle failed for app pid %d",
+                                           app->pid);
                                }
-                               free(tmp_event);
-                               release_ret = lttng_ust_ctl_release_handle(app->sock, handle);
                                pthread_mutex_unlock(&app->sock_lock);
-                               if (release_ret < 0 &&
-                                               release_ret != -LTTNG_UST_ERR_EXITING &&
-                                               release_ret != -EPIPE) {
-                                       ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret);
-                               }
-                               goto rcu_error;
+                               continue;
                        }
 
-                       health_code_update();
-                       if (count >= nbmem) {
-                               /* In case the realloc fails, we free the memory */
-                               struct lttng_event_field *new_tmp_event;
-                               size_t new_nbmem;
-
-                               new_nbmem = nbmem << 1;
-                               DBG2("Reallocating event field list from %zu to %zu entries",
-                                               nbmem, new_nbmem);
-                               new_tmp_event = (lttng_event_field *) realloc(tmp_event,
-                                       new_nbmem * sizeof(struct lttng_event_field));
-                               if (new_tmp_event == NULL) {
+                       while ((ret = lttng_ust_ctl_tracepoint_field_list_get(
+                                       app->sock, handle, &uiter)) != -LTTNG_UST_ERR_NOENT) {
+                               /* Handle ustctl error. */
+                               if (ret < 0) {
                                        int release_ret;
 
-                                       PERROR("realloc ust app event fields");
+                                       if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
+                                               ERR("UST app tp list field failed for app %d with ret %d",
+                                                   app->sock,
+                                                   ret);
+                                       } else {
+                                               DBG3("UST app tp list field failed. Application is dead");
+                                               break;
+                                       }
+
                                        free(tmp_event);
-                                       ret = -ENOMEM;
-                                       release_ret = lttng_ust_ctl_release_handle(app->sock, handle);
+                                       release_ret =
+                                               lttng_ust_ctl_release_handle(app->sock, handle);
                                        pthread_mutex_unlock(&app->sock_lock);
-                                       if (release_ret &&
-                                                       release_ret != -LTTNG_UST_ERR_EXITING &&
-                                                       release_ret != -EPIPE) {
-                                               ERR("Error releasing app handle for app %d with ret %d", app->sock, release_ret);
+                                       if (release_ret < 0 &&
+                                           release_ret != -LTTNG_UST_ERR_EXITING &&
+                                           release_ret != -EPIPE) {
+                                               ERR("Error releasing app handle for app %d with ret %d",
+                                                   app->sock,
+                                                   release_ret);
                                        }
+
                                        goto rcu_error;
                                }
-                               /* Zero the new memory */
-                               memset(new_tmp_event + nbmem, 0,
-                                       (new_nbmem - nbmem) * sizeof(struct lttng_event_field));
-                               nbmem = new_nbmem;
-                               tmp_event = new_tmp_event;
-                       }
 
-                       memcpy(tmp_event[count].field_name, uiter.field_name, LTTNG_UST_ABI_SYM_NAME_LEN);
-                       /* Mapping between these enums matches 1 to 1. */
-                       tmp_event[count].type = (enum lttng_event_field_type) uiter.type;
-                       tmp_event[count].nowrite = uiter.nowrite;
+                               health_code_update();
+                               if (count >= nbmem) {
+                                       /* In case the realloc fails, we free the memory */
+                                       struct lttng_event_field *new_tmp_event;
+                                       size_t new_nbmem;
+
+                                       new_nbmem = nbmem << 1;
+                                       DBG2("Reallocating event field list from %zu to %zu entries",
+                                            nbmem,
+                                            new_nbmem);
+                                       new_tmp_event = (lttng_event_field *) realloc(
+                                               tmp_event,
+                                               new_nbmem * sizeof(struct lttng_event_field));
+                                       if (new_tmp_event == nullptr) {
+                                               int release_ret;
+
+                                               PERROR("realloc ust app event fields");
+                                               free(tmp_event);
+                                               ret = -ENOMEM;
+                                               release_ret = lttng_ust_ctl_release_handle(
+                                                       app->sock, handle);
+                                               pthread_mutex_unlock(&app->sock_lock);
+                                               if (release_ret &&
+                                                   release_ret != -LTTNG_UST_ERR_EXITING &&
+                                                   release_ret != -EPIPE) {
+                                                       ERR("Error releasing app handle for app %d with ret %d",
+                                                           app->sock,
+                                                           release_ret);
+                                               }
+
+                                               goto rcu_error;
+                                       }
 
-                       memcpy(tmp_event[count].event.name, uiter.event_name, LTTNG_UST_ABI_SYM_NAME_LEN);
-                       tmp_event[count].event.loglevel = uiter.loglevel;
-                       tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT;
-                       tmp_event[count].event.pid = app->pid;
-                       tmp_event[count].event.enabled = -1;
-                       count++;
-               }
-               ret = lttng_ust_ctl_release_handle(app->sock, handle);
-               pthread_mutex_unlock(&app->sock_lock);
-               if (ret < 0 &&
-                               ret != -LTTNG_UST_ERR_EXITING &&
-                               ret != -EPIPE) {
-                       ERR("Error releasing app handle for app %d with ret %d", app->sock, ret);
+                                       /* Zero the new memory */
+                                       memset(new_tmp_event + nbmem,
+                                              0,
+                                              (new_nbmem - nbmem) *
+                                                      sizeof(struct lttng_event_field));
+                                       nbmem = new_nbmem;
+                                       tmp_event = new_tmp_event;
+                               }
+
+                               memcpy(tmp_event[count].field_name,
+                                      uiter.field_name,
+                                      LTTNG_UST_ABI_SYM_NAME_LEN);
+                               /* Mapping between these enums matches 1 to 1. */
+                               tmp_event[count].type = (enum lttng_event_field_type) uiter.type;
+                               tmp_event[count].nowrite = uiter.nowrite;
+
+                               memcpy(tmp_event[count].event.name,
+                                      uiter.event_name,
+                                      LTTNG_UST_ABI_SYM_NAME_LEN);
+                               tmp_event[count].event.loglevel = uiter.loglevel;
+                               tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT;
+                               tmp_event[count].event.pid = app->pid;
+                               tmp_event[count].event.enabled = -1;
+                               count++;
+                       }
+
+                       ret = lttng_ust_ctl_release_handle(app->sock, handle);
+                       pthread_mutex_unlock(&app->sock_lock);
+                       if (ret < 0 && ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
+                               ERR("Error releasing app handle for app %d with ret %d",
+                                   app->sock,
+                                   ret);
+                       }
                }
        }
 
@@ -4610,7 +4773,6 @@ int ust_app_list_event_fields(struct lttng_event_field **fields)
        DBG2("UST app list event fields done (%zu events)", count);
 
 rcu_error:
-       rcu_read_unlock();
 error:
        health_code_update();
        return ret;
@@ -4618,10 +4780,8 @@ error:
 
 /*
  * Free and clean all traceable apps of the global list.
- *
- * Should _NOT_ be called with RCU read-side lock held.
  */
-void ust_app_clean_list(void)
+void ust_app_clean_list()
 {
        int ret;
        struct ust_app *app;
@@ -4629,57 +4789,48 @@ void ust_app_clean_list(void)
 
        DBG2("UST app cleaning registered apps hash table");
 
-       rcu_read_lock();
-
        /* Cleanup notify socket hash table */
        if (ust_app_ht_by_notify_sock) {
-               cds_lfht_for_each_entry(ust_app_ht_by_notify_sock->ht, &iter.iter, app,
-                               notify_sock_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (
+                       ust_app_ht_by_notify_sock->ht, &iter.iter, app, notify_sock_n.node) {
                        /*
                         * Assert that all notifiers are gone as all triggers
                         * are unregistered prior to this clean-up.
                         */
                        LTTNG_ASSERT(lttng_ht_get_count(app->token_to_event_notifier_rule_ht) == 0);
-
                        ust_app_notify_sock_unregister(app->notify_sock);
                }
        }
 
-       if (ust_app_ht) {
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-                       ret = lttng_ht_del(ust_app_ht, &iter);
-                       LTTNG_ASSERT(!ret);
-                       call_rcu(&app->pid_n.head, delete_ust_app_rcu);
-               }
-       }
-
        /* Cleanup socket hash table */
        if (ust_app_ht_by_sock) {
-               cds_lfht_for_each_entry(ust_app_ht_by_sock->ht, &iter.iter, app,
-                               sock_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ust_app_ht_by_sock->ht, &iter.iter, app, sock_n.node) {
                        ret = lttng_ht_del(ust_app_ht_by_sock, &iter);
                        LTTNG_ASSERT(!ret);
+                       ust_app_put(app);
                }
        }
 
-       rcu_read_unlock();
-
        /* Destroy is done only when the ht is empty */
        if (ust_app_ht) {
-               ht_cleanup_push(ust_app_ht);
+               lttng_ht_destroy(ust_app_ht);
        }
        if (ust_app_ht_by_sock) {
-               ht_cleanup_push(ust_app_ht_by_sock);
+               lttng_ht_destroy(ust_app_ht_by_sock);
        }
        if (ust_app_ht_by_notify_sock) {
-               ht_cleanup_push(ust_app_ht_by_notify_sock);
+               lttng_ht_destroy(ust_app_ht_by_notify_sock);
        }
 }
 
 /*
  * Init UST app hash table.
  */
-int ust_app_ht_alloc(void)
+int ust_app_ht_alloc()
 {
        ust_app_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
        if (!ust_app_ht) {
@@ -4699,8 +4850,7 @@ int ust_app_ht_alloc(void)
 /*
  * For a specific UST session, disable the channel for all registered apps.
  */
-int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan)
+int ust_app_disable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
@@ -4711,52 +4861,53 @@ int ust_app_disable_channel_glb(struct ltt_ust_session *usess,
 
        LTTNG_ASSERT(usess->active);
        DBG2("UST app disabling channel %s from global domain for session id %" PRIu64,
-                       uchan->name, usess->id);
+            uchan->name,
+            usess->id);
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       /* For every registered applications */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               struct lttng_ht_iter uiter;
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (ua_sess == NULL) {
-                       continue;
-               }
+               /* For every registered applications */
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       struct lttng_ht_iter uiter;
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (ua_sess == nullptr) {
+                               continue;
+                       }
 
-               /* Get channel */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
-               ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
-               /* If the session if found for the app, the channel must be there */
-               LTTNG_ASSERT(ua_chan_node);
+                       /* Get channel */
+                       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
+                       ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
+                       /* If the session if found for the app, the channel must be there */
+                       LTTNG_ASSERT(ua_chan_node);
 
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
-               /* The channel must not be already disabled */
-               LTTNG_ASSERT(ua_chan->enabled == 1);
+                       ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
+                       /* The channel must not be already disabled */
+                       LTTNG_ASSERT(ua_chan->enabled);
 
-               /* Disable channel onto application */
-               ret = disable_ust_app_channel(ua_sess, ua_chan, app);
-               if (ret < 0) {
-                       /* XXX: We might want to report this error at some point... */
-                       continue;
+                       /* Disable channel onto application */
+                       ret = disable_ust_app_channel(ua_sess, ua_chan, app);
+                       if (ret < 0) {
+                               /* XXX: We might want to report this error at some point... */
+                               continue;
+                       }
                }
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
 /*
  * For a specific UST session, enable the channel for all registered apps.
  */
-int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan)
+int ust_app_enable_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
@@ -4765,33 +4916,35 @@ int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
 
        LTTNG_ASSERT(usess->active);
        DBG2("UST app enabling channel %s to global domain for session id %" PRIu64,
-                       uchan->name, usess->id);
+            uchan->name,
+            usess->id);
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       /* For every registered applications */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (ua_sess == NULL) {
-                       continue;
-               }
+               /* For every registered applications */
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (ua_sess == nullptr) {
+                               continue;
+                       }
 
-               /* Enable channel onto application */
-               ret = enable_ust_app_channel(ua_sess, uchan, app);
-               if (ret < 0) {
-                       /* XXX: We might want to report this error at some point... */
-                       continue;
+                       /* Enable channel onto application */
+                       ret = enable_ust_app_channel(ua_sess, uchan, app);
+                       if (ret < 0) {
+                               /* XXX: We might want to report this error at some point... */
+                               continue;
+                       }
                }
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
@@ -4799,7 +4952,8 @@ int ust_app_enable_channel_glb(struct ltt_ust_session *usess,
  * Disable an event in a channel and for a specific session.
  */
 int ust_app_disable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+                             struct ltt_ust_channel *uchan,
+                             struct ltt_ust_event *uevent)
 {
        int ret = 0;
        struct lttng_ht_iter iter, uiter;
@@ -4811,98 +4965,107 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess,
 
        LTTNG_ASSERT(usess->active);
        DBG("UST app disabling event %s for all apps in channel "
-                       "%s for session id %" PRIu64,
-                       uevent->attr.name, uchan->name, usess->id);
-
-       rcu_read_lock();
+           "%s for session id %" PRIu64,
+           uevent->attr.name,
+           uchan->name,
+           usess->id);
 
-       /* For all registered applications */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (ua_sess == NULL) {
-                       /* Next app */
-                       continue;
-               }
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-               /* Lookup channel in the ust app session */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
-               ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
-               if (ua_chan_node == NULL) {
-                       DBG2("Channel %s not found in session id %" PRIu64 " for app pid %d."
-                                       "Skipping", uchan->name, usess->id, app->pid);
-                       continue;
-               }
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+               /* For all registered applications */
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (ua_sess == nullptr) {
+                               /* Next app */
+                               continue;
+                       }
 
-               ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
-                               uevent->filter, uevent->attr.loglevel,
+                       /* Lookup channel in the ust app session */
+                       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
+                       ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
+                       if (ua_chan_node == nullptr) {
+                               DBG2("Channel %s not found in session id %" PRIu64
+                                    " for app pid %d."
+                                    "Skipping",
+                                    uchan->name,
+                                    usess->id,
+                                    app->pid);
+                               continue;
+                       }
+                       ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
+
+                       ua_event = find_ust_app_event(
+                               ua_chan->events,
+                               uevent->attr.name,
+                               uevent->filter,
+                               (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type,
+                               uevent->attr.loglevel,
                                uevent->exclusion);
-               if (ua_event == NULL) {
-                       DBG2("Event %s not found in channel %s for app pid %d."
-                                       "Skipping", uevent->attr.name, uchan->name, app->pid);
-                       continue;
-               }
+                       if (ua_event == nullptr) {
+                               DBG2("Event %s not found in channel %s for app pid %d."
+                                    "Skipping",
+                                    uevent->attr.name,
+                                    uchan->name,
+                                    app->pid);
+                               continue;
+                       }
 
-               ret = disable_ust_app_event(ua_sess, ua_event, app);
-               if (ret < 0) {
-                       /* XXX: Report error someday... */
-                       continue;
+                       ret = disable_ust_app_event(ua_event, app);
+                       if (ret < 0) {
+                               /* XXX: Report error someday... */
+                               continue;
+                       }
                }
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
 /* The ua_sess lock must be held by the caller.  */
-static
-int ust_app_channel_create(struct ltt_ust_session *usess,
-               struct ust_app_session *ua_sess,
-               struct ltt_ust_channel *uchan, struct ust_app *app,
-               struct ust_app_channel **_ua_chan)
+static int ust_app_channel_create(struct ltt_ust_session *usess,
+                                 struct ust_app_session *ua_sess,
+                                 struct ltt_ust_channel *uchan,
+                                 struct ust_app *app,
+                                 struct ust_app_channel **_ua_chan)
 {
        int ret = 0;
-       struct ust_app_channel *ua_chan = NULL;
+       struct ust_app_channel *ua_chan = nullptr;
 
        LTTNG_ASSERT(ua_sess);
        ASSERT_LOCKED(ua_sess->lock);
 
-       if (!strncmp(uchan->name, DEFAULT_METADATA_NAME,
-                    sizeof(uchan->name))) {
-               copy_channel_attr_to_ustctl(&ua_sess->metadata_attr,
-                       &uchan->attr);
+       if (!strncmp(uchan->name, DEFAULT_METADATA_NAME, sizeof(uchan->name))) {
+               copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &uchan->attr);
                ret = 0;
        } else {
-               struct ltt_ust_context *uctx = NULL;
+               struct ltt_ust_context *uctx = nullptr;
 
                /*
                 * Create channel onto application and synchronize its
                 * configuration.
                 */
-               ret = ust_app_channel_allocate(ua_sess, uchan,
-                       LTTNG_UST_ABI_CHAN_PER_CPU, usess,
-                       &ua_chan);
+               ret = ust_app_channel_allocate(
+                       ua_sess, uchan, LTTNG_UST_ABI_CHAN_PER_CPU, usess, &ua_chan);
                if (ret < 0) {
                        goto error;
                }
 
-               ret = ust_app_channel_send(app, usess,
-                       ua_sess, ua_chan);
+               ret = ust_app_channel_send(app, usess, ua_sess, ua_chan);
                if (ret) {
                        goto error;
                }
 
                /* Add contexts. */
-               cds_list_for_each_entry(uctx, &uchan->ctx_list, list) {
-                       ret = create_ust_app_channel_context(ua_chan,
-                               &uctx->ctx, app);
+               cds_list_for_each_entry (uctx, &uchan->ctx_list, list) {
+                       ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app);
                        if (ret) {
                                goto error;
                        }
@@ -4918,7 +5081,7 @@ error:
                         * or a timeout on it. We can't inform the caller that for a
                         * specific app, the session failed so lets continue here.
                         */
-                       ret = 0;        /* Not an error. */
+                       ret = 0; /* Not an error. */
                        break;
                case -ENOMEM:
                default:
@@ -4941,7 +5104,8 @@ error:
  * Enable event for a specific session and channel on the tracer.
  */
 int ust_app_enable_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+                            struct ltt_ust_channel *uchan,
+                            struct ltt_ust_event *uevent)
 {
        int ret = 0;
        struct lttng_ht_iter iter, uiter;
@@ -4953,7 +5117,8 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess,
 
        LTTNG_ASSERT(usess->active);
        DBG("UST app enabling event %s for all apps for session id %" PRIu64,
-                       uevent->attr.name, usess->id);
+           uevent->attr.name,
+           usess->id);
 
        /*
         * NOTE: At this point, this function is called only if the session and
@@ -4961,65 +5126,72 @@ int ust_app_enable_event_glb(struct ltt_ust_session *usess,
         * tracer also.
         */
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       /* For all registered applications */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (!ua_sess) {
-                       /* The application has problem or is probably dead. */
-                       continue;
-               }
+               /* For all registered applications */
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (!ua_sess) {
+                               /* The application has problem or is probably dead. */
+                               continue;
+                       }
 
-               pthread_mutex_lock(&ua_sess->lock);
+                       pthread_mutex_lock(&ua_sess->lock);
 
-               if (ua_sess->deleted) {
-                       pthread_mutex_unlock(&ua_sess->lock);
-                       continue;
-               }
+                       if (ua_sess->deleted) {
+                               pthread_mutex_unlock(&ua_sess->lock);
+                               continue;
+                       }
 
-               /* Lookup channel in the ust app session */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
-               ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
-               /*
-                * It is possible that the channel cannot be found is
-                * the channel/event creation occurs concurrently with
-                * an application exit.
-                */
-               if (!ua_chan_node) {
-                       pthread_mutex_unlock(&ua_sess->lock);
-                       continue;
-               }
+                       /* Lookup channel in the ust app session */
+                       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
+                       ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
+                       /*
+                        * It is possible that the channel cannot be found is
+                        * the channel/event creation occurs concurrently with
+                        * an application exit.
+                        */
+                       if (!ua_chan_node) {
+                               pthread_mutex_unlock(&ua_sess->lock);
+                               continue;
+                       }
 
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+                       ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
 
-               /* Get event node */
-               ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
-                               uevent->filter, uevent->attr.loglevel, uevent->exclusion);
-               if (ua_event == NULL) {
-                       DBG3("UST app enable event %s not found for app PID %d."
-                                       "Skipping app", uevent->attr.name, app->pid);
-                       goto next_app;
-               }
+                       /* Get event node */
+                       ua_event = find_ust_app_event(
+                               ua_chan->events,
+                               uevent->attr.name,
+                               uevent->filter,
+                               (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type,
+                               uevent->attr.loglevel,
+                               uevent->exclusion);
+                       if (ua_event == nullptr) {
+                               DBG3("UST app enable event %s not found for app PID %d."
+                                    "Skipping app",
+                                    uevent->attr.name,
+                                    app->pid);
+                               goto next_app;
+                       }
 
-               ret = enable_ust_app_event(ua_sess, ua_event, app);
-               if (ret < 0) {
+                       ret = enable_ust_app_event(ua_event, app);
+                       if (ret < 0) {
+                               pthread_mutex_unlock(&ua_sess->lock);
+                               goto error;
+                       }
+               next_app:
                        pthread_mutex_unlock(&ua_sess->lock);
-                       goto error;
                }
-       next_app:
-               pthread_mutex_unlock(&ua_sess->lock);
        }
-
 error:
-       rcu_read_unlock();
        return ret;
 }
 
@@ -5028,7 +5200,8 @@ error:
  * all registered apps.
  */
 int ust_app_create_event_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+                            struct ltt_ust_channel *uchan,
+                            struct ltt_ust_event *uevent)
 {
        int ret = 0;
        struct lttng_ht_iter iter, uiter;
@@ -5039,54 +5212,59 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess,
 
        LTTNG_ASSERT(usess->active);
        DBG("UST app creating event %s for all apps for session id %" PRIu64,
-                       uevent->attr.name, usess->id);
+           uevent->attr.name,
+           usess->id);
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       /* For all registered applications */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (!ua_sess) {
-                       /* The application has problem or is probably dead. */
-                       continue;
-               }
+               /* For all registered applications */
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (!ua_sess) {
+                               /* The application has problem or is probably dead. */
+                               continue;
+                       }
 
-               pthread_mutex_lock(&ua_sess->lock);
+                       pthread_mutex_lock(&ua_sess->lock);
 
-               if (ua_sess->deleted) {
-                       pthread_mutex_unlock(&ua_sess->lock);
-                       continue;
-               }
+                       if (ua_sess->deleted) {
+                               pthread_mutex_unlock(&ua_sess->lock);
+                               continue;
+                       }
 
-               /* Lookup channel in the ust app session */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
-               ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
-               /* If the channel is not found, there is a code flow error */
-               LTTNG_ASSERT(ua_chan_node);
+                       /* Lookup channel in the ust app session */
+                       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
+                       ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
+                       /* If the channel is not found, there is a code flow error */
+                       LTTNG_ASSERT(ua_chan_node);
 
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+                       ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
 
-               ret = create_ust_app_event(ua_sess, ua_chan, uevent, app);
-               pthread_mutex_unlock(&ua_sess->lock);
-               if (ret < 0) {
-                       if (ret != -LTTNG_UST_ERR_EXIST) {
-                               /* Possible value at this point: -ENOMEM. If so, we stop! */
-                               break;
+                       ret = create_ust_app_event(ua_chan, uevent, app);
+                       pthread_mutex_unlock(&ua_sess->lock);
+                       if (ret < 0) {
+                               if (ret != -LTTNG_UST_ERR_EXIST) {
+                                       /* Possible value at this point: -ENOMEM. If so, we stop! */
+                                       break;
+                               }
+
+                               DBG2("UST app event %s already exist on app PID %d",
+                                    uevent->attr.name,
+                                    app->pid);
+                               continue;
                        }
-                       DBG2("UST app event %s already exist on app PID %d",
-                                       uevent->attr.name, app->pid);
-                       continue;
                }
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
@@ -5096,22 +5274,21 @@ int ust_app_create_event_glb(struct ltt_ust_session *usess,
  * Called with UST app session lock held.
  *
  */
-static
-int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
+static int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_session *ua_sess;
 
        DBG("Starting tracing for ust app pid %d", app->pid);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        if (!app->compatible) {
                goto end;
        }
 
        ua_sess = lookup_session_by_app(usess, app);
-       if (ua_sess == NULL) {
+       if (ua_sess == nullptr) {
                /* The session is in teardown process. Ignore and continue. */
                goto end;
        }
@@ -5143,25 +5320,29 @@ skip_setup:
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app start session failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                        pthread_mutex_unlock(&ua_sess->lock);
                        goto end;
                } else if (ret == -EAGAIN) {
                        WARN("UST app start session failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                        pthread_mutex_unlock(&ua_sess->lock);
                        goto end;
 
                } else {
                        ERR("UST app start session failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error_unlock;
        }
 
        /* Indicate that the session has been started once */
-       ua_sess->started = 1;
-       ua_sess->enabled = 1;
+       ua_sess->started = true;
+       ua_sess->enabled = true;
 
        pthread_mutex_unlock(&ua_sess->lock);
 
@@ -5174,24 +5355,26 @@ skip_setup:
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app wait quiescent failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app wait quiescent failed. Communication time out: pid =  %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app wait quiescent failed with ret %d: pid %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
        }
 
 end:
-       rcu_read_unlock();
        health_code_update();
        return 0;
 
 error_unlock:
        pthread_mutex_unlock(&ua_sess->lock);
-       rcu_read_unlock();
        health_code_update();
        return -1;
 }
@@ -5199,23 +5382,21 @@ error_unlock:
 /*
  * Stop tracing for a specific UST session and app.
  */
-static
-int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
+static int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_session *ua_sess;
-       struct ust_registry_session *registry;
 
        DBG("Stopping tracing for ust app pid %d", app->pid);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        if (!app->compatible) {
                goto end_no_session;
        }
 
        ua_sess = lookup_session_by_app(usess, app);
-       if (ua_sess == NULL) {
+       if (ua_sess == nullptr) {
                goto end_no_session;
        }
 
@@ -5245,22 +5426,26 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app stop session failed. Application is dead: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                        goto end_unlock;
                } else if (ret == -EAGAIN) {
                        WARN("UST app stop session failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                        goto end_unlock;
 
                } else {
                        ERR("UST app stop session failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                goto error_rcu_unlock;
        }
 
        health_code_update();
-       ua_sess->enabled = 0;
+       ua_sess->enabled = false;
 
        /* Quiescent wait after stopping trace */
        pthread_mutex_lock(&app->sock_lock);
@@ -5269,74 +5454,75 @@ int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
        }
 
        health_code_update();
 
-       registry = get_session_registry(ua_sess);
+       {
+               auto locked_registry = get_locked_session_registry(ua_sess);
 
-       /* The UST app session is held registry shall not be null. */
-       LTTNG_ASSERT(registry);
+               /* The UST app session is held registry shall not be null. */
+               LTTNG_ASSERT(locked_registry);
 
-       /* Push metadata for application before freeing the application. */
-       (void) push_metadata(registry, ua_sess->consumer);
+               /* Push metadata for application before freeing the application. */
+               (void) push_metadata(locked_registry, ua_sess->consumer);
+       }
 
 end_unlock:
        pthread_mutex_unlock(&ua_sess->lock);
 end_no_session:
-       rcu_read_unlock();
        health_code_update();
        return 0;
 
 error_rcu_unlock:
        pthread_mutex_unlock(&ua_sess->lock);
-       rcu_read_unlock();
        health_code_update();
        return -1;
 }
 
-static
-int ust_app_flush_app_session(struct ust_app *app,
-               struct ust_app_session *ua_sess)
+static int ust_app_flush_app_session(ust_app& app, ust_app_session& ua_sess)
 {
        int ret, retval = 0;
        struct lttng_ht_iter iter;
        struct ust_app_channel *ua_chan;
        struct consumer_socket *socket;
 
-       DBG("Flushing app session buffers for ust app pid %d", app->pid);
-
-       rcu_read_lock();
+       DBG("Flushing app session buffers for ust app pid %d", app.pid);
 
-       if (!app->compatible) {
+       if (!app.compatible) {
                goto end_not_compatible;
        }
 
-       pthread_mutex_lock(&ua_sess->lock);
+       pthread_mutex_lock(&ua_sess.lock);
 
-       if (ua_sess->deleted) {
+       if (ua_sess.deleted) {
                goto end_deleted;
        }
 
        health_code_update();
 
        /* Flushing buffers */
-       socket = consumer_find_socket_by_bitness(app->bits_per_long,
-                       ua_sess->consumer);
+       socket = consumer_find_socket_by_bitness(app.abi.bits_per_long, ua_sess.consumer);
 
        /* Flush buffers and push metadata. */
-       switch (ua_sess->buffer_type) {
+       switch (ua_sess.buffer_type) {
        case LTTNG_BUFFER_PER_PID:
-               cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan,
-                               node.node) {
+       {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ua_sess.channels->ht, &iter.iter, ua_chan, node.node) {
                        health_code_update();
                        ret = consumer_flush_channel(socket, ua_chan->key);
                        if (ret) {
@@ -5345,7 +5531,9 @@ int ust_app_flush_app_session(struct ust_app *app,
                                continue;
                        }
                }
+
                break;
+       }
        case LTTNG_BUFFER_PER_UID:
        default:
                abort();
@@ -5355,10 +5543,9 @@ int ust_app_flush_app_session(struct ust_app *app,
        health_code_update();
 
 end_deleted:
-       pthread_mutex_unlock(&ua_sess->lock);
+       pthread_mutex_unlock(&ua_sess.lock);
 
 end_not_compatible:
-       rcu_read_unlock();
        health_code_update();
        return retval;
 }
@@ -5367,16 +5554,13 @@ end_not_compatible:
  * Flush buffers for all applications for a specific UST session.
  * Called with UST session lock held.
  */
-static
-int ust_app_flush_session(struct ltt_ust_session *usess)
+static int ust_app_flush_session(struct ltt_ust_session *usess)
 
 {
        int ret = 0;
 
        DBG("Flushing session buffers for all ust apps");
 
-       rcu_read_lock();
-
        /* Flush buffers and push metadata. */
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
@@ -5385,21 +5569,22 @@ int ust_app_flush_session(struct ltt_ust_session *usess)
                struct lttng_ht_iter iter;
 
                /* Flush all per UID buffers associated to that session. */
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
-                       struct ust_registry_session *ust_session_reg;
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
+                       lttng::urcu::read_lock_guard read_lock;
+                       lsu::registry_session *ust_session_reg;
                        struct buffer_reg_channel *buf_reg_chan;
                        struct consumer_socket *socket;
 
                        /* Get consumer socket to use to push the metadata.*/
                        socket = consumer_find_socket_by_bitness(reg->bits_per_long,
-                                       usess->consumer);
+                                                                usess->consumer);
                        if (!socket) {
                                /* Ignore request if no consumer is found for the session. */
                                continue;
                        }
 
-                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
-                                       buf_reg_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
                                /*
                                 * The following call will print error values so the return
                                 * code is of little importance because whatever happens, we
@@ -5410,8 +5595,10 @@ int ust_app_flush_session(struct ltt_ust_session *usess)
 
                        ust_session_reg = reg->registry->reg.ust;
                        /* Push metadata. */
-                       (void) push_metadata(ust_session_reg, usess->consumer);
+                       auto locked_registry = ust_session_reg->lock();
+                       (void) push_metadata(locked_registry, usess->consumer);
                }
+
                break;
        }
        case LTTNG_BUFFER_PER_PID:
@@ -5419,14 +5606,17 @@ int ust_app_flush_session(struct ltt_ust_session *usess)
                struct ust_app_session *ua_sess;
                struct lttng_ht_iter iter;
                struct ust_app *app;
+               lttng::urcu::read_lock_guard read_lock;
 
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        ua_sess = lookup_session_by_app(usess, app);
-                       if (ua_sess == NULL) {
+                       if (ua_sess == nullptr) {
                                continue;
                        }
-                       (void) ust_app_flush_app_session(app, ua_sess);
+
+                       (void) ust_app_flush_app_session(*app, *ua_sess);
                }
+
                break;
        }
        default:
@@ -5435,14 +5625,11 @@ int ust_app_flush_session(struct ltt_ust_session *usess)
                break;
        }
 
-       rcu_read_unlock();
        health_code_update();
        return ret;
 }
 
-static
-int ust_app_clear_quiescent_app_session(struct ust_app *app,
-               struct ust_app_session *ua_sess)
+static int ust_app_clear_quiescent_app_session(struct ust_app *app, struct ust_app_session *ua_sess)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
@@ -5451,7 +5638,7 @@ int ust_app_clear_quiescent_app_session(struct ust_app *app,
 
        DBG("Clearing stream quiescent state for ust app pid %d", app->pid);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        if (!app->compatible) {
                goto end_not_compatible;
@@ -5465,11 +5652,9 @@ int ust_app_clear_quiescent_app_session(struct ust_app *app,
 
        health_code_update();
 
-       socket = consumer_find_socket_by_bitness(app->bits_per_long,
-                       ua_sess->consumer);
+       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, ua_sess->consumer);
        if (!socket) {
-               ERR("Failed to find consumer (%" PRIu32 ") socket",
-                               app->bits_per_long);
+               ERR("Failed to find consumer (%" PRIu32 ") socket", app->abi.bits_per_long);
                ret = -1;
                goto end_unlock;
        }
@@ -5477,11 +5662,9 @@ int ust_app_clear_quiescent_app_session(struct ust_app *app,
        /* Clear quiescent state. */
        switch (ua_sess->buffer_type) {
        case LTTNG_BUFFER_PER_PID:
-               cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter,
-                               ua_chan, node.node) {
+               cds_lfht_for_each_entry (ua_sess->channels->ht, &iter.iter, ua_chan, node.node) {
                        health_code_update();
-                       ret = consumer_clear_quiescent_channel(socket,
-                                       ua_chan->key);
+                       ret = consumer_clear_quiescent_channel(socket, ua_chan->key);
                        if (ret) {
                                ERR("Error clearing quiescent state for consumer channel");
                                ret = -1;
@@ -5502,7 +5685,6 @@ end_unlock:
        pthread_mutex_unlock(&ua_sess->lock);
 
 end_not_compatible:
-       rcu_read_unlock();
        health_code_update();
        return ret;
 }
@@ -5512,16 +5694,13 @@ end_not_compatible:
  * specific UST session.
  * Called with UST session lock held.
  */
-static
-int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
+static int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
 
 {
        int ret = 0;
 
        DBG("Clearing stream quiescent state for all ust apps");
 
-       rcu_read_lock();
-
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
@@ -5532,13 +5711,14 @@ int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                 * Clear quiescent for all per UID buffers associated to
                 * that session.
                 */
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct consumer_socket *socket;
                        struct buffer_reg_channel *buf_reg_chan;
+                       lttng::urcu::read_lock_guard read_lock;
 
                        /* Get associated consumer socket.*/
-                       socket = consumer_find_socket_by_bitness(
-                                       reg->bits_per_long, usess->consumer);
+                       socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+                                                                usess->consumer);
                        if (!socket) {
                                /*
                                 * Ignore request if no consumer is found for
@@ -5547,8 +5727,8 @@ int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                                continue;
                        }
 
-                       cds_lfht_for_each_entry(reg->registry->channels->ht,
-                                       &iter.iter, buf_reg_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
                                /*
                                 * The following call will print error values so
                                 * the return code is of little importance
@@ -5556,9 +5736,10 @@ int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                                 * all.
                                 */
                                (void) consumer_clear_quiescent_channel(socket,
-                                               buf_reg_chan->consumer_key);
+                                                                       buf_reg_chan->consumer_key);
                        }
                }
+
                break;
        }
        case LTTNG_BUFFER_PER_PID:
@@ -5566,16 +5747,16 @@ int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                struct ust_app_session *ua_sess;
                struct lttng_ht_iter iter;
                struct ust_app *app;
+               lttng::urcu::read_lock_guard read_lock;
 
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app,
-                               pid_n.node) {
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        ua_sess = lookup_session_by_app(usess, app);
-                       if (ua_sess == NULL) {
+                       if (ua_sess == nullptr) {
                                continue;
                        }
-                       (void) ust_app_clear_quiescent_app_session(app,
-                                       ua_sess);
+                       (void) ust_app_clear_quiescent_app_session(app, ua_sess);
                }
+
                break;
        }
        default:
@@ -5584,7 +5765,6 @@ int ust_app_clear_quiescent_session(struct ltt_ust_session *usess)
                break;
        }
 
-       rcu_read_unlock();
        health_code_update();
        return ret;
 }
@@ -5601,7 +5781,7 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app)
 
        DBG("Destroy tracing for ust app pid %d", app->pid);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        if (!app->compatible) {
                goto end;
@@ -5609,11 +5789,11 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app)
 
        __lookup_session_by_app(usess, app, &iter);
        node = lttng_ht_iter_get_node_u64(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                /* Session is being or is deleted. */
                goto end;
        }
-       ua_sess = caa_container_of(node, struct ust_app_session, node);
+       ua_sess = lttng::utils::container_of(node, &ust_app_session::node);
 
        health_code_update();
        destroy_app_session(app, ua_sess);
@@ -5627,17 +5807,20 @@ static int destroy_trace(struct ltt_ust_session *usess, struct ust_app *app)
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app wait quiescent failed. Application is dead: pid= %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app wait quiescent failed. Communication time out: pid= %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app wait quiescent failed with ret %d: pid= %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
        }
 end:
-       rcu_read_unlock();
        health_code_update();
        return 0;
 }
@@ -5656,9 +5839,7 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess)
         * Even though the start trace might fail, flag this session active so
         * other application coming in are started by default.
         */
-       usess->active = 1;
-
-       rcu_read_lock();
+       usess->active = true;
 
        /*
         * In a start-stop-start use-case, we need to clear the quiescent state
@@ -5668,11 +5849,13 @@ int ust_app_start_trace_all(struct ltt_ust_session *usess)
         */
        (void) ust_app_clear_quiescent_session(usess);
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               ust_app_global_update(usess, app);
-       }
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       rcu_read_unlock();
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       ust_app_global_update(usess, app);
+               }
+       }
 
        return 0;
 }
@@ -5693,22 +5876,22 @@ int ust_app_stop_trace_all(struct ltt_ust_session *usess)
         * Even though the stop trace might fail, flag this session inactive so
         * other application coming in are not started by default.
         */
-       usess->active = 0;
+       usess->active = false;
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               ret = ust_app_stop_trace(usess, app);
-               if (ret < 0) {
-                       /* Continue to next apps even on error */
-                       continue;
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       ret = ust_app_stop_trace(usess, app);
+                       if (ret < 0) {
+                               /* Continue to next apps even on error */
+                               continue;
+                       }
                }
        }
 
        (void) ust_app_flush_session(usess);
 
-       rcu_read_unlock();
-
        return 0;
 }
 
@@ -5723,29 +5906,27 @@ int ust_app_destroy_trace_all(struct ltt_ust_session *usess)
 
        DBG("Destroy all UST traces");
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               ret = destroy_trace(usess, app);
-               if (ret < 0) {
-                       /* Continue to next apps even on error */
-                       continue;
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       ret = destroy_trace(usess, app);
+                       if (ret < 0) {
+                               /* Continue to next apps even on error */
+                               continue;
+                       }
                }
        }
 
-       rcu_read_unlock();
-
        return 0;
 }
 
 /* The ua_sess lock must be held by the caller. */
-static
-int find_or_create_ust_app_channel(
-               struct ltt_ust_session *usess,
-               struct ust_app_session *ua_sess,
-               struct ust_app *app,
-               struct ltt_ust_channel *uchan,
-               struct ust_app_channel **ua_chan)
+static int find_or_create_ust_app_channel(struct ltt_ust_session *usess,
+                                         struct ust_app_session *ua_sess,
+                                         struct ust_app *app,
+                                         struct ltt_ust_channel *uchan,
+                                         struct ust_app_channel **ua_chan)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
@@ -5754,8 +5935,7 @@ int find_or_create_ust_app_channel(
        lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &iter);
        ua_chan_node = lttng_ht_iter_get_node_str(&iter);
        if (ua_chan_node) {
-               *ua_chan = caa_container_of(ua_chan_node,
-                       struct ust_app_channel, node);
+               *ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
                goto end;
        }
 
@@ -5767,26 +5947,28 @@ end:
        return ret;
 }
 
-static
-int ust_app_channel_synchronize_event(struct ust_app_channel *ua_chan,
-               struct ltt_ust_event *uevent, struct ust_app_session *ua_sess,
-               struct ust_app *app)
+static int ust_app_channel_synchronize_event(struct ust_app_channel *ua_chan,
+                                            struct ltt_ust_event *uevent,
+                                            struct ust_app *app)
 {
        int ret = 0;
-       struct ust_app_event *ua_event = NULL;
-
-       ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
-               uevent->filter, uevent->attr.loglevel, uevent->exclusion);
+       struct ust_app_event *ua_event = nullptr;
+
+       ua_event = find_ust_app_event(ua_chan->events,
+                                     uevent->attr.name,
+                                     uevent->filter,
+                                     (enum lttng_ust_abi_loglevel_type) uevent->attr.loglevel_type,
+                                     uevent->attr.loglevel,
+                                     uevent->exclusion);
        if (!ua_event) {
-               ret = create_ust_app_event(ua_sess, ua_chan, uevent, app);
+               ret = create_ust_app_event(ua_chan, uevent, app);
                if (ret < 0) {
                        goto end;
                }
        } else {
                if (ua_event->enabled != uevent->enabled) {
-                       ret = uevent->enabled ?
-                               enable_ust_app_event(ua_sess, ua_event, app) :
-                               disable_ust_app_event(ua_sess, ua_event, app);
+                       ret = uevent->enabled ? enable_ust_app_event(ua_event, app) :
+                                               disable_ust_app_event(ua_event, app);
                }
        }
 
@@ -5795,17 +5977,18 @@ end:
 }
 
 /* Called with RCU read-side lock held. */
-static
-void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
+static void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
 {
        int ret = 0;
        enum lttng_error_code ret_code;
        enum lttng_trigger_status t_status;
        struct lttng_ht_iter app_trigger_iter;
-       struct lttng_triggers *triggers = NULL;
+       struct lttng_triggers *triggers = nullptr;
        struct ust_app_event_notifier_rule *event_notifier_rule;
        unsigned int count, i;
 
+       ASSERT_RCU_READ_LOCKED();
+
        if (!ust_app_supports_notifiers(app)) {
                goto end;
        }
@@ -5829,7 +6012,7 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
 
        /* Get all triggers using uid 0 (root) */
        ret_code = notification_thread_command_list_triggers(
-                       the_notification_thread_handle, 0, &triggers);
+               the_notification_thread_handle, 0, &triggers);
        if (ret_code != LTTNG_OK) {
                goto end;
        }
@@ -5856,14 +6039,13 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
                condition = lttng_trigger_get_condition(trigger);
 
                if (lttng_condition_get_type(condition) !=
-                               LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES) {
+                   LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES) {
                        /* Does not apply */
                        continue;
                }
 
-               condition_status =
-                               lttng_condition_event_rule_matches_borrow_rule_mutable(
-                                               condition, &event_rule);
+               condition_status = lttng_condition_event_rule_matches_borrow_rule_mutable(
+                       condition, &event_rule);
                LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK);
 
                if (lttng_event_rule_get_domain_type(event_rule) == LTTNG_DOMAIN_KERNEL) {
@@ -5877,7 +6059,7 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
                 * explicitly acquiring it here.
                 */
                looked_up_event_notifier_rule = find_ust_app_event_notifier_rule(
-                               app->token_to_event_notifier_rule_ht, token);
+                       app->token_to_event_notifier_rule_ht, token);
                if (!looked_up_event_notifier_rule) {
                        ret = create_ust_app_event_notifier_rule(trigger, app);
                        if (ret < 0) {
@@ -5886,57 +6068,55 @@ void ust_app_synchronize_event_notifier_rules(struct ust_app *app)
                }
        }
 
-       rcu_read_lock();
-       /* Remove all unknown event sources from the app. */
-       cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
-                       &app_trigger_iter.iter, event_notifier_rule,
-                       node.node) {
-               const uint64_t app_token = event_notifier_rule->token;
-               bool found = false;
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-               /*
-                * Check if the app event trigger still exists on the
-                * notification side.
-                */
-               for (i = 0; i < count; i++) {
-                       uint64_t notification_thread_token;
-                       const struct lttng_trigger *trigger =
-                                       lttng_triggers_get_at_index(
-                                                       triggers, i);
+               /* Remove all unknown event sources from the app. */
+               cds_lfht_for_each_entry (app->token_to_event_notifier_rule_ht->ht,
+                                        &app_trigger_iter.iter,
+                                        event_notifier_rule,
+                                        node.node) {
+                       const uint64_t app_token = event_notifier_rule->token;
+                       bool found = false;
 
-                       LTTNG_ASSERT(trigger);
+                       /*
+                        * Check if the app event trigger still exists on the
+                        * notification side.
+                        */
+                       for (i = 0; i < count; i++) {
+                               uint64_t notification_thread_token;
+                               const struct lttng_trigger *trigger =
+                                       lttng_triggers_get_at_index(triggers, i);
 
-                       notification_thread_token =
-                                       lttng_trigger_get_tracer_token(trigger);
+                               LTTNG_ASSERT(trigger);
 
-                       if (notification_thread_token == app_token) {
-                               found = true;
-                               break;
+                               notification_thread_token = lttng_trigger_get_tracer_token(trigger);
+
+                               if (notification_thread_token == app_token) {
+                                       found = true;
+                                       break;
+                               }
                        }
-               }
 
-               if (found) {
-                       /* Still valid. */
-                       continue;
-               }
+                       if (found) {
+                               /* Still valid. */
+                               continue;
+                       }
 
-               /*
-                * This trigger was unregistered, disable it on the tracer's
-                * side.
-                */
-               ret = lttng_ht_del(app->token_to_event_notifier_rule_ht,
-                               &app_trigger_iter);
-               LTTNG_ASSERT(ret == 0);
+                       /*
+                        * This trigger was unregistered, disable it on the tracer's
+                        * side.
+                        */
+                       ret = lttng_ht_del(app->token_to_event_notifier_rule_ht, &app_trigger_iter);
+                       LTTNG_ASSERT(ret == 0);
 
-               /* Callee logs errors. */
-               (void) disable_ust_object(app, event_notifier_rule->obj);
+                       /* Callee logs errors. */
+                       (void) disable_ust_object(app, event_notifier_rule->obj);
 
-               delete_ust_app_event_notifier_rule(
-                               app->sock, event_notifier_rule, app);
+                       delete_ust_app_event_notifier_rule(app->sock, event_notifier_rule, app);
+               }
        }
 
-       rcu_read_unlock();
-
 end:
        lttng_triggers_destroy(triggers);
        return;
@@ -5945,10 +6125,9 @@ end:
 /*
  * RCU read lock must be held by the caller.
  */
-static
-void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
-               struct ust_app_session *ua_sess,
-               struct ust_app *app)
+static void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
+                                            struct ust_app_session *ua_sess,
+                                            struct ust_app *app)
 {
        int ret = 0;
        struct cds_lfht_iter uchan_iter;
@@ -5957,9 +6136,9 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(ua_sess);
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
-       cds_lfht_for_each_entry(usess->domain_global.channels->ht, &uchan_iter,
-                       uchan, node.node) {
+       cds_lfht_for_each_entry (usess->domain_global.channels->ht, &uchan_iter, uchan, node.node) {
                struct ust_app_channel *ua_chan;
                struct cds_lfht_iter uevent_iter;
                struct ltt_ust_event *uevent;
@@ -5971,8 +6150,7 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
                 * allocated (if necessary) and sent to the application, and
                 * all enabled contexts will be added to the channel.
                 */
-               ret = find_or_create_ust_app_channel(usess, ua_sess,
-                       app, uchan, &ua_chan);
+               ret = find_or_create_ust_app_channel(usess, ua_sess, app, uchan, &ua_chan);
                if (ret) {
                        /* Tracer is probably gone or ENOMEM. */
                        goto end;
@@ -5983,19 +6161,16 @@ void ust_app_synchronize_all_channels(struct ltt_ust_session *usess,
                        continue;
                }
 
-               cds_lfht_for_each_entry(uchan->events->ht, &uevent_iter, uevent,
-                               node.node) {
-                       ret = ust_app_channel_synchronize_event(ua_chan,
-                               uevent, ua_sess, app);
+               cds_lfht_for_each_entry (uchan->events->ht, &uevent_iter, uevent, node.node) {
+                       ret = ust_app_channel_synchronize_event(ua_chan, uevent, app);
                        if (ret) {
                                goto end;
                        }
                }
 
                if (ua_chan->enabled != uchan->enabled) {
-                       ret = uchan->enabled ?
-                               enable_ust_app_channel(ua_sess, uchan, app) :
-                               disable_ust_app_channel(ua_sess, ua_chan, app);
+                       ret = uchan->enabled ? enable_ust_app_channel(ua_sess, uchan, app) :
+                                              disable_ust_app_channel(ua_sess, ua_chan, app);
                        if (ret) {
                                goto end;
                        }
@@ -6009,12 +6184,10 @@ end:
  * The caller must ensure that the application is compatible and is tracked
  * by the process attribute trackers.
  */
-static
-void ust_app_synchronize(struct ltt_ust_session *usess,
-               struct ust_app *app)
+static void ust_app_synchronize(struct ltt_ust_session *usess, struct ust_app *app)
 {
        int ret = 0;
-       struct ust_app_session *ua_sess = NULL;
+       struct ust_app_session *ua_sess = nullptr;
 
        /*
         * The application's configuration should only be synchronized for
@@ -6022,14 +6195,12 @@ void ust_app_synchronize(struct ltt_ust_session *usess,
         */
        LTTNG_ASSERT(usess->active);
 
-       ret = find_or_create_ust_app_session(usess, app, &ua_sess, NULL);
+       ret = find_or_create_ust_app_session(usess, app, &ua_sess, nullptr);
        if (ret < 0) {
                /* Tracer is probably gone or ENOMEM. */
-               if (ua_sess) {
-                       destroy_app_session(app, ua_sess);
-               }
                goto end;
        }
+
        LTTNG_ASSERT(ua_sess);
 
        pthread_mutex_lock(&ua_sess->lock);
@@ -6037,40 +6208,40 @@ void ust_app_synchronize(struct ltt_ust_session *usess,
                goto deleted_session;
        }
 
-       rcu_read_lock();
+       {
+               lttng::urcu::read_lock_guard read_lock;
 
-       ust_app_synchronize_all_channels(usess, ua_sess, app);
+               ust_app_synchronize_all_channels(usess, ua_sess, app);
 
-       /*
-        * Create the metadata for the application. This returns gracefully if a
-        * metadata was already set for the session.
-        *
-        * The metadata channel must be created after the data channels as the
-        * consumer daemon assumes this ordering. When interacting with a relay
-        * daemon, the consumer will use this assumption to send the
-        * "STREAMS_SENT" message to the relay daemon.
-        */
-       ret = create_ust_app_metadata(ua_sess, app, usess->consumer);
-       if (ret < 0) {
-               ERR("Metadata creation failed for app sock %d for session id %" PRIu64,
-                               app->sock, usess->id);
+               /*
+                * Create the metadata for the application. This returns gracefully if a
+                * metadata was already set for the session.
+                *
+                * The metadata channel must be created after the data channels as the
+                * consumer daemon assumes this ordering. When interacting with a relay
+                * daemon, the consumer will use this assumption to send the
+                * "STREAMS_SENT" message to the relay daemon.
+                */
+               ret = create_ust_app_metadata(ua_sess, app, usess->consumer);
+               if (ret < 0) {
+                       ERR("Metadata creation failed for app sock %d for session id %" PRIu64,
+                           app->sock,
+                           usess->id);
+               }
        }
 
-       rcu_read_unlock();
-
 deleted_session:
        pthread_mutex_unlock(&ua_sess->lock);
 end:
        return;
 }
 
-static
-void ust_app_global_destroy(struct ltt_ust_session *usess, struct ust_app *app)
+static void ust_app_global_destroy(struct ltt_ust_session *usess, struct ust_app *app)
 {
        struct ust_app_session *ua_sess;
 
        ua_sess = lookup_session_by_app(usess, app);
-       if (ua_sess == NULL) {
+       if (ua_sess == nullptr) {
                return;
        }
        destroy_app_session(app, ua_sess);
@@ -6086,21 +6257,16 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
 {
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(usess->active);
+       ASSERT_RCU_READ_LOCKED();
 
-       DBG2("UST app global update for app sock %d for session id %" PRIu64,
-                       app->sock, usess->id);
+       DBG2("UST app global update for app sock %d for session id %" PRIu64, app->sock, usess->id);
 
        if (!app->compatible) {
                return;
        }
-       if (trace_ust_id_tracker_lookup(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID,
-                           usess, app->pid) &&
-                       trace_ust_id_tracker_lookup(
-                                       LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID,
-                                       usess, app->uid) &&
-                       trace_ust_id_tracker_lookup(
-                                       LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID,
-                                       usess, app->gid)) {
+       if (trace_ust_id_tracker_lookup(LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, usess, app->pid) &&
+           trace_ust_id_tracker_lookup(LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID, usess, app->uid) &&
+           trace_ust_id_tracker_lookup(LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID, usess, app->gid)) {
                /*
                 * Synchronize the application's internal tracing configuration
                 * and start tracing.
@@ -6120,16 +6286,20 @@ void ust_app_global_update(struct ltt_ust_session *usess, struct ust_app *app)
  */
 void ust_app_global_update_event_notifier_rules(struct ust_app *app)
 {
+       ASSERT_RCU_READ_LOCKED();
+
        DBG2("UST application global event notifier rules update: app = '%s', pid = %d",
-                       app->name, app->pid);
+            app->name,
+            app->pid);
 
        if (!app->compatible || !ust_app_supports_notifiers(app)) {
                return;
        }
 
-       if (app->event_notifier_group.object == NULL) {
+       if (app->event_notifier_group.object == nullptr) {
                WARN("UST app global update of event notifiers for app skipped since communication handle is null: app = '%s', pid = %d",
-                               app->name, app->pid);
+                    app->name,
+                    app->pid);
                return;
        }
 
@@ -6144,79 +6314,80 @@ void ust_app_global_update_all(struct ltt_ust_session *usess)
        struct lttng_ht_iter iter;
        struct ust_app *app;
 
-       rcu_read_lock();
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               ust_app_global_update(usess, app);
+       {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       ust_app_global_update(usess, app);
+               }
        }
-       rcu_read_unlock();
 }
 
-void ust_app_global_update_all_event_notifier_rules(void)
+void ust_app_global_update_all_event_notifier_rules()
 {
        struct lttng_ht_iter iter;
        struct ust_app *app;
 
-       rcu_read_lock();
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+       lttng::urcu::read_lock_guard read_lock;
+       cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                ust_app_global_update_event_notifier_rules(app);
        }
-
-       rcu_read_unlock();
 }
 
 /*
  * Add context to a specific channel for global UST domain.
  */
 int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx)
+                               struct ltt_ust_channel *uchan,
+                               struct ltt_ust_context *uctx)
 {
        int ret = 0;
        struct lttng_ht_node_str *ua_chan_node;
        struct lttng_ht_iter iter, uiter;
-       struct ust_app_channel *ua_chan = NULL;
+       struct ust_app_channel *ua_chan = nullptr;
        struct ust_app_session *ua_sess;
        struct ust_app *app;
 
        LTTNG_ASSERT(usess->active);
 
-       rcu_read_lock();
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
-               if (!app->compatible) {
-                       /*
-                        * TODO: In time, we should notice the caller of this error by
-                        * telling him that this is a version error.
-                        */
-                       continue;
-               }
-               ua_sess = lookup_session_by_app(usess, app);
-               if (ua_sess == NULL) {
-                       continue;
-               }
+       {
+               lttng::urcu::read_lock_guard read_lock;
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+                       if (!app->compatible) {
+                               /*
+                                * TODO: In time, we should notice the caller of this error by
+                                * telling him that this is a version error.
+                                */
+                               continue;
+                       }
+                       ua_sess = lookup_session_by_app(usess, app);
+                       if (ua_sess == nullptr) {
+                               continue;
+                       }
 
-               pthread_mutex_lock(&ua_sess->lock);
+                       pthread_mutex_lock(&ua_sess->lock);
 
-               if (ua_sess->deleted) {
-                       pthread_mutex_unlock(&ua_sess->lock);
-                       continue;
-               }
+                       if (ua_sess->deleted) {
+                               pthread_mutex_unlock(&ua_sess->lock);
+                               continue;
+                       }
 
-               /* Lookup channel in the ust app session */
-               lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
-               ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
-               if (ua_chan_node == NULL) {
-                       goto next_app;
-               }
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel,
-                               node);
-               ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app);
-               if (ret < 0) {
-                       goto next_app;
+                       /* Lookup channel in the ust app session */
+                       lttng_ht_lookup(ua_sess->channels, (void *) uchan->name, &uiter);
+                       ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
+                       if (ua_chan_node == nullptr) {
+                               goto next_app;
+                       }
+                       ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+                       ret = create_ust_app_channel_context(ua_chan, &uctx->ctx, app);
+                       if (ret < 0) {
+                               goto next_app;
+                       }
+               next_app:
+                       pthread_mutex_unlock(&ua_sess->lock);
                }
-       next_app:
-               pthread_mutex_unlock(&ua_sess->lock);
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
@@ -6232,16 +6403,22 @@ int ust_app_recv_registration(int sock, struct ust_register_msg *msg)
 
        LTTNG_ASSERT(msg);
 
-       ret = lttng_ust_ctl_recv_reg_msg(sock, &msg->type, &msg->major, &msg->minor,
-                       &pid, &ppid, &uid, &gid,
-                       &msg->bits_per_long,
-                       &msg->uint8_t_alignment,
-                       &msg->uint16_t_alignment,
-                       &msg->uint32_t_alignment,
-                       &msg->uint64_t_alignment,
-                       &msg->long_alignment,
-                       &msg->byte_order,
-                       msg->name);
+       ret = lttng_ust_ctl_recv_reg_msg(sock,
+                                        &msg->type,
+                                        &msg->major,
+                                        &msg->minor,
+                                        &pid,
+                                        &ppid,
+                                        &uid,
+                                        &gid,
+                                        &msg->bits_per_long,
+                                        &msg->uint8_t_alignment,
+                                        &msg->uint16_t_alignment,
+                                        &msg->uint32_t_alignment,
+                                        &msg->uint64_t_alignment,
+                                        &msg->long_alignment,
+                                        &msg->byte_order,
+                                        msg->name);
        if (ret < 0) {
                switch (-ret) {
                case EPIPE:
@@ -6251,8 +6428,10 @@ int ust_app_recv_registration(int sock, struct ust_register_msg *msg)
                        break;
                case LTTNG_UST_ERR_UNSUP_MAJOR:
                        ERR("UST app recv reg unsupported version %d.%d. Supporting %d.%d",
-                                       msg->major, msg->minor, LTTNG_UST_ABI_MAJOR_VERSION,
-                                       LTTNG_UST_ABI_MINOR_VERSION);
+                           msg->major,
+                           msg->minor,
+                           LTTNG_UST_ABI_MAJOR_VERSION,
+                           LTTNG_UST_ABI_MINOR_VERSION);
                        break;
                default:
                        ERR("UST app recv reg message failed with ret %d", ret);
@@ -6273,24 +6452,24 @@ error:
  * Return a ust app session object using the application object and the
  * session object descriptor has a key. If not found, NULL is returned.
  * A RCU read side lock MUST be acquired when calling this function.
-*/
-static struct ust_app_session *find_session_by_objd(struct ust_app *app,
-               int objd)
+ */
+static struct ust_app_session *find_session_by_objd(struct ust_app *app, int objd)
 {
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
-       struct ust_app_session *ua_sess = NULL;
+       struct ust_app_session *ua_sess = nullptr;
 
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
-       lttng_ht_lookup(app->ust_sessions_objd, (void *)((unsigned long) objd), &iter);
+       lttng_ht_lookup(app->ust_sessions_objd, (void *) ((unsigned long) objd), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                DBG2("UST app session find by objd %d not found", objd);
                goto error;
        }
 
-       ua_sess = caa_container_of(node, struct ust_app_session, ust_objd_node);
+       ua_sess = lttng::utils::container_of(node, &ust_app_session::ust_objd_node);
 
 error:
        return ua_sess;
@@ -6301,23 +6480,23 @@ error:
  * object descriptor has a key. If not found, NULL is returned. A RCU read side
  * lock MUST be acquired before calling this function.
  */
-static struct ust_app_channel *find_channel_by_objd(struct ust_app *app,
-               int objd)
+static struct ust_app_channel *find_channel_by_objd(struct ust_app *app, int objd)
 {
        struct lttng_ht_node_ulong *node;
        struct lttng_ht_iter iter;
-       struct ust_app_channel *ua_chan = NULL;
+       struct ust_app_channel *ua_chan = nullptr;
 
        LTTNG_ASSERT(app);
+       ASSERT_RCU_READ_LOCKED();
 
-       lttng_ht_lookup(app->ust_objd, (void *)((unsigned long) objd), &iter);
+       lttng_ht_lookup(app->ust_objd, (void *) ((unsigned long) objd), &iter);
        node = lttng_ht_iter_get_node_ulong(&iter);
-       if (node == NULL) {
+       if (node == nullptr) {
                DBG2("UST app channel find by objd %d not found", objd);
                goto error;
        }
 
-       ua_chan = caa_container_of(node, struct ust_app_channel, ust_objd_node);
+       ua_chan = lttng::utils::container_of(node, &ust_app_channel::ust_objd_node);
 
 error:
        return ua_chan;
@@ -6331,47 +6510,45 @@ error:
  *
  * On success 0 is returned else a negative value.
  */
-static int reply_ust_register_channel(int sock, int cobjd,
-               size_t nr_fields, struct lttng_ust_ctl_field *fields)
+static int handle_app_register_channel_notification(int sock,
+                                                   int cobjd,
+                                                   struct lttng_ust_ctl_field *raw_context_fields,
+                                                   size_t context_field_count)
 {
        int ret, ret_code = 0;
        uint32_t chan_id;
        uint64_t chan_reg_key;
-       enum lttng_ust_ctl_channel_header type;
        struct ust_app *app;
        struct ust_app_channel *ua_chan;
        struct ust_app_session *ua_sess;
-       struct ust_registry_session *registry;
-       struct ust_registry_channel *ust_reg_chan;
+       auto ust_ctl_context_fields =
+               lttng::make_unique_wrapper<lttng_ust_ctl_field, lttng::memory::free>(
+                       raw_context_fields);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock_guard;
 
        /* Lookup application. If not found, there is a code flow error. */
        app = find_app_by_notify_sock(sock);
        if (!app) {
-               DBG("Application socket %d is being torn down. Abort event notify",
-                               sock);
-               ret = -1;
-               goto error_rcu_unlock;
+               DBG("Application socket %d is being torn down. Abort event notify", sock);
+               return -1;
        }
 
        /* Lookup channel by UST object descriptor. */
        ua_chan = find_channel_by_objd(app, cobjd);
        if (!ua_chan) {
                DBG("Application channel is being torn down. Abort event notify");
-               ret = 0;
-               goto error_rcu_unlock;
+               return 0;
        }
 
        LTTNG_ASSERT(ua_chan->session);
        ua_sess = ua_chan->session;
 
        /* Get right session registry depending on the session buffer type. */
-       registry = get_session_registry(ua_sess);
-       if (!registry) {
+       auto locked_registry_session = get_locked_session_registry(ua_sess);
+       if (!locked_registry_session) {
                DBG("Application session is being torn down. Abort event notify");
-               ret = 0;
-               goto error_rcu_unlock;
+               return 0;
        };
 
        /* Depending on the buffer type, a different channel key is used. */
@@ -6381,79 +6558,106 @@ static int reply_ust_register_channel(int sock, int cobjd,
                chan_reg_key = ua_chan->key;
        }
 
-       pthread_mutex_lock(&registry->lock);
-
-       ust_reg_chan = ust_registry_channel_find(registry, chan_reg_key);
-       LTTNG_ASSERT(ust_reg_chan);
+       auto& ust_reg_chan = locked_registry_session->channel(chan_reg_key);
 
        /* Channel id is set during the object creation. */
-       chan_id = ust_reg_chan->chan_id;
+       chan_id = ust_reg_chan.id;
 
-       if (!ust_reg_chan->register_done) {
-               /*
-                * TODO: eventually use the registry event count for
-                * this channel to better guess header type for per-pid
-                * buffers.
-                */
-               type = LTTNG_UST_CTL_CHANNEL_HEADER_LARGE;
-               ust_reg_chan->nr_ctx_fields = nr_fields;
-               ust_reg_chan->ctx_fields = fields;
-               fields = NULL;
-               ust_reg_chan->header_type = type;
-       } else {
-               /* Get current already assigned values. */
-               type = ust_reg_chan->header_type;
-               /*
-                * Validate that the context fields match between
-                * registry and newcoming application.
-                */
-               if (!match_lttng_ust_ctl_field_array(ust_reg_chan->ctx_fields,
-                               ust_reg_chan->nr_ctx_fields,
-                               fields, nr_fields)) {
-                       ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
-                               app->pid, app->sock);
-                       ret_code = -EINVAL;
-                       goto reply;
-               }
-       }
+       /*
+        * The application returns the typing information of the channel's
+        * context fields. In per-PID buffering mode, this is the first and only
+        * time we get this information. It is our chance to finalize the
+        * initialiation of the channel and serialize it's layout's description
+        * to the trace's metadata.
+        *
+        * However, in per-UID buffering mode, every application will provide
+        * this information (redundantly). The first time will allow us to
+        * complete the initialization. The following times, we simply validate
+        * that all apps provide the same typing for the context fields as a
+        * sanity check.
+        */
+       try {
+               auto app_context_fields = lsu::create_trace_fields_from_ust_ctl_fields(
+                       *locked_registry_session,
+                       ust_ctl_context_fields.get(),
+                       context_field_count,
+                       lst::field_location::root::EVENT_RECORD_COMMON_CONTEXT,
+                       lsu::ctl_field_quirks::UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS);
+
+               if (!ust_reg_chan.is_registered()) {
+                       lst::type::cuptr event_context = app_context_fields.size() ?
+                               lttng::make_unique<lst::structure_type>(
+                                       0, std::move(app_context_fields)) :
+                               nullptr;
+
+                       ust_reg_chan.event_context(std::move(event_context));
+               } else {
+                       /*
+                        * Validate that the context fields match between
+                        * registry and newcoming application.
+                        */
+                       bool context_fields_match;
+                       const auto *previous_event_context = ust_reg_chan.event_context();
 
-       /* Append to metadata */
-       if (!ust_reg_chan->metadata_dumped) {
-               ret_code = ust_metadata_channel_statedump(registry, ust_reg_chan);
-               if (ret_code) {
-                       ERR("Error appending channel metadata (errno = %d)", ret_code);
-                       goto reply;
+                       if (!previous_event_context) {
+                               context_fields_match = app_context_fields.size() == 0;
+                       } else {
+                               const lst::structure_type app_event_context_struct(
+                                       0, std::move(app_context_fields));
+
+                               context_fields_match = *previous_event_context ==
+                                       app_event_context_struct;
+                       }
+
+                       if (!context_fields_match) {
+                               ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
+                                   app->pid,
+                                   app->sock);
+                               ret_code = -EINVAL;
+                               goto reply;
+                       }
                }
+       } catch (const std::exception& ex) {
+               ERR("Failed to handle application context: %s", ex.what());
+               ret_code = -EINVAL;
+               goto reply;
        }
 
 reply:
-       DBG3("UST app replying to register channel key %" PRIu64
-                       " with id %u, type = %d, ret = %d", chan_reg_key, chan_id, type,
-                       ret_code);
-
-       ret = lttng_ust_ctl_reply_register_channel(sock, chan_id, type, ret_code);
+       DBG3("UST app replying to register channel key %" PRIu64 " with id %u, ret = %d",
+            chan_reg_key,
+            chan_id,
+            ret_code);
+
+       ret = lttng_ust_ctl_reply_register_channel(
+               sock,
+               chan_id,
+               ust_reg_chan.header_type_ == lst::stream_class::header_type::COMPACT ?
+                       LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT :
+                       LTTNG_UST_CTL_CHANNEL_HEADER_LARGE,
+               ret_code);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app reply channel failed. Application died: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app reply channel failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app reply channel failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
-               goto error;
+
+               return ret;
        }
 
-       /* This channel registry registration is completed. */
-       ust_reg_chan->register_done = 1;
+       /* This channel registry's registration is completed. */
+       ust_reg_chan.set_as_registered();
 
-error:
-       pthread_mutex_unlock(&registry->lock);
-error_rcu_unlock:
-       rcu_read_unlock();
-       free(fields);
        return ret;
 }
 
@@ -6466,9 +6670,15 @@ error_rcu_unlock:
  *
  * On success 0 is returned else a negative value.
  */
-static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
-               char *sig, size_t nr_fields, struct lttng_ust_ctl_field *fields,
-               int loglevel_value, char *model_emf_uri)
+static int add_event_ust_registry(int sock,
+                                 int sobjd,
+                                 int cobjd,
+                                 const char *name,
+                                 char *raw_signature,
+                                 size_t nr_fields,
+                                 struct lttng_ust_ctl_field *raw_fields,
+                                 int loglevel_value,
+                                 char *raw_model_emf_uri)
 {
        int ret, ret_code;
        uint32_t event_id = 0;
@@ -6476,57 +6686,80 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        struct ust_app *app;
        struct ust_app_channel *ua_chan;
        struct ust_app_session *ua_sess;
-       struct ust_registry_session *registry;
-
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard rcu_lock;
+       auto signature = lttng::make_unique_wrapper<char, lttng::memory::free>(raw_signature);
+       auto fields =
+               lttng::make_unique_wrapper<lttng_ust_ctl_field, lttng::memory::free>(raw_fields);
+       auto model_emf_uri =
+               lttng::make_unique_wrapper<char, lttng::memory::free>(raw_model_emf_uri);
 
        /* Lookup application. If not found, there is a code flow error. */
        app = find_app_by_notify_sock(sock);
        if (!app) {
-               DBG("Application socket %d is being torn down. Abort event notify",
-                               sock);
-               ret = -1;
-               goto error_rcu_unlock;
+               DBG("Application socket %d is being torn down. Abort event notify", sock);
+               return -1;
        }
 
        /* Lookup channel by UST object descriptor. */
        ua_chan = find_channel_by_objd(app, cobjd);
        if (!ua_chan) {
                DBG("Application channel is being torn down. Abort event notify");
-               ret = 0;
-               goto error_rcu_unlock;
+               return 0;
        }
 
        LTTNG_ASSERT(ua_chan->session);
        ua_sess = ua_chan->session;
 
-       registry = get_session_registry(ua_sess);
-       if (!registry) {
-               DBG("Application session is being torn down. Abort event notify");
-               ret = 0;
-               goto error_rcu_unlock;
-       }
-
        if (ua_sess->buffer_type == LTTNG_BUFFER_PER_UID) {
                chan_reg_key = ua_chan->tracing_channel_id;
        } else {
                chan_reg_key = ua_chan->key;
        }
 
-       pthread_mutex_lock(&registry->lock);
-
-       /*
-        * From this point on, this call acquires the ownership of the sig, fields
-        * and model_emf_uri meaning any free are done inside it if needed. These
-        * three variables MUST NOT be read/write after this.
-        */
-       ret_code = ust_registry_create_event(registry, chan_reg_key,
-                       sobjd, cobjd, name, sig, nr_fields, fields,
-                       loglevel_value, model_emf_uri, ua_sess->buffer_type,
-                       &event_id, app);
-       sig = NULL;
-       fields = NULL;
-       model_emf_uri = NULL;
+       {
+               auto locked_registry = get_locked_session_registry(ua_sess);
+               if (locked_registry) {
+                       /*
+                        * From this point on, this call acquires the ownership of the signature,
+                        * fields and model_emf_uri meaning any free are done inside it if needed.
+                        * These three variables MUST NOT be read/write after this.
+                        */
+                       try {
+                               auto& channel = locked_registry->channel(chan_reg_key);
+
+                               /* event_id is set on success. */
+                               channel.add_event(
+                                       sobjd,
+                                       cobjd,
+                                       name,
+                                       signature.get(),
+                                       lsu::create_trace_fields_from_ust_ctl_fields(
+                                               *locked_registry,
+                                               fields.get(),
+                                               nr_fields,
+                                               lst::field_location::root::EVENT_RECORD_PAYLOAD,
+                                               lsu::ctl_field_quirks::
+                                                       UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS),
+                                       loglevel_value,
+                                       model_emf_uri.get() ?
+                                               nonstd::optional<std::string>(model_emf_uri.get()) :
+                                               nonstd::nullopt,
+                                       ua_sess->buffer_type,
+                                       *app,
+                                       event_id);
+                               ret_code = 0;
+                       } catch (const std::exception& ex) {
+                               ERR("Failed to add event `%s` to registry session: %s",
+                                   name,
+                                   ex.what());
+                               /* Inform the application of the error; don't return directly. */
+                               ret_code = -EINVAL;
+                       }
+               } else {
+                       DBG("Application session is being torn down. Abort event notify");
+                       return 0;
+               }
+       }
 
        /*
         * The return value is returned to ustctl so in case of an error, the
@@ -6537,31 +6770,26 @@ static int add_event_ust_registry(int sock, int sobjd, int cobjd, char *name,
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app reply event failed. Application died: pid = %d, sock = %d.",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app reply event failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app reply event failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                /*
                 * No need to wipe the create event since the application socket will
                 * get close on error hence cleaning up everything by itself.
                 */
-               goto error;
+               return ret;
        }
 
-       DBG3("UST registry event %s with id %" PRId32 " added successfully",
-                       name, event_id);
-
-error:
-       pthread_mutex_unlock(&registry->lock);
-error_rcu_unlock:
-       rcu_read_unlock();
-       free(sig);
-       free(fields);
-       free(model_emf_uri);
+       DBG3("UST registry event %s with id %" PRId32 " added successfully", name, event_id);
        return ret;
 }
 
@@ -6573,26 +6801,27 @@ error_rcu_unlock:
  *
  * On success 0 is returned else a negative value.
  */
-static int add_enum_ust_registry(int sock, int sobjd, char *name,
-               struct lttng_ust_ctl_enum_entry *entries, size_t nr_entries)
+static int add_enum_ust_registry(int sock,
+                                int sobjd,
+                                const char *name,
+                                struct lttng_ust_ctl_enum_entry *raw_entries,
+                                size_t nr_entries)
 {
-       int ret = 0, ret_code;
+       int ret = 0;
        struct ust_app *app;
        struct ust_app_session *ua_sess;
-       struct ust_registry_session *registry;
        uint64_t enum_id = -1ULL;
-
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock_guard;
+       auto entries =
+               lttng::make_unique_wrapper<struct lttng_ust_ctl_enum_entry, lttng::memory::free>(
+                       raw_entries);
 
        /* Lookup application. If not found, there is a code flow error. */
        app = find_app_by_notify_sock(sock);
        if (!app) {
                /* Return an error since this is not an error */
-               DBG("Application socket %d is being torn down. Aborting enum registration",
-                               sock);
-               free(entries);
-               ret = -1;
-               goto error_rcu_unlock;
+               DBG("Application socket %d is being torn down. Aborting enum registration", sock);
+               return -1;
        }
 
        /* Lookup session by UST object descriptor. */
@@ -6600,59 +6829,66 @@ static int add_enum_ust_registry(int sock, int sobjd, char *name,
        if (!ua_sess) {
                /* Return an error since this is not an error */
                DBG("Application session is being torn down (session not found). Aborting enum registration.");
-               free(entries);
-               goto error_rcu_unlock;
+               return 0;
        }
 
-       registry = get_session_registry(ua_sess);
-       if (!registry) {
+       auto locked_registry = get_locked_session_registry(ua_sess);
+       if (!locked_registry) {
                DBG("Application session is being torn down (registry not found). Aborting enum registration.");
-               free(entries);
-               goto error_rcu_unlock;
+               return 0;
        }
 
-       pthread_mutex_lock(&registry->lock);
-
        /*
         * From this point on, the callee acquires the ownership of
         * entries. The variable entries MUST NOT be read/written after
         * call.
         */
-       ret_code = ust_registry_create_or_find_enum(registry, sobjd, name,
-                       entries, nr_entries, &enum_id);
-       entries = NULL;
+       int application_reply_code;
+       try {
+               locked_registry->create_or_find_enum(
+                       sobjd, name, entries.release(), nr_entries, &enum_id);
+               application_reply_code = 0;
+       } catch (const std::exception& ex) {
+               ERR("%s: %s",
+                   lttng::format(
+                           "Failed to create or find enumeration provided by application: app = {}, enumeration name = {}",
+                           *app,
+                           name)
+                           .c_str(),
+                   ex.what());
+               application_reply_code = -1;
+       }
 
        /*
         * The return value is returned to ustctl so in case of an error, the
         * application can be notified. In case of an error, it's important not to
         * return a negative error or else the application will get closed.
         */
-       ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, ret_code);
+       ret = lttng_ust_ctl_reply_register_enum(sock, enum_id, application_reply_code);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                        DBG3("UST app reply enum failed. Application died: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else if (ret == -EAGAIN) {
                        WARN("UST app reply enum failed. Communication time out: pid = %d, sock = %d",
-                                       app->pid, app->sock);
+                            app->pid,
+                            app->sock);
                } else {
                        ERR("UST app reply enum failed with ret %d: pid = %d, sock = %d",
-                                       ret, app->pid, app->sock);
+                           ret,
+                           app->pid,
+                           app->sock);
                }
                /*
                 * No need to wipe the create enum since the application socket will
                 * get close on error hence cleaning up everything by itself.
                 */
-               goto error;
+               return ret;
        }
 
        DBG3("UST registry enum %s added successfully or already found", name);
-
-error:
-       pthread_mutex_unlock(&registry->lock);
-error_rcu_unlock:
-       rcu_read_unlock();
-       return ret;
+       return 0;
 }
 
 /*
@@ -6670,14 +6906,11 @@ int ust_app_recv_notify(int sock)
        ret = lttng_ust_ctl_recv_notify(sock, &cmd);
        if (ret < 0) {
                if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
-                       DBG3("UST app recv notify failed. Application died: sock = %d",
-                                       sock);
+                       DBG3("UST app recv notify failed. Application died: sock = %d", sock);
                } else if (ret == -EAGAIN) {
-                       WARN("UST app recv notify failed. Communication time out: sock = %d",
-                                       sock);
+                       WARN("UST app recv notify failed. Communication time out: sock = %d", sock);
                } else {
-                       ERR("UST app recv notify failed with ret %d: sock = %d",
-                                       ret, sock);
+                       ERR("UST app recv notify failed with ret %d: sock = %d", ret, sock);
                }
                goto error;
        }
@@ -6692,31 +6925,63 @@ int ust_app_recv_notify(int sock)
 
                DBG2("UST app ustctl register event received");
 
-               ret = lttng_ust_ctl_recv_register_event(sock, &sobjd, &cobjd, name,
-                               &loglevel_value, &sig, &nr_fields, &fields,
-                               &model_emf_uri);
+               ret = lttng_ust_ctl_recv_register_event(sock,
+                                                       &sobjd,
+                                                       &cobjd,
+                                                       name,
+                                                       &loglevel_value,
+                                                       &sig,
+                                                       &nr_fields,
+                                                       &fields,
+                                                       &model_emf_uri);
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app recv event failed. Application died: sock = %d",
-                                               sock);
+                                    sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app recv event failed. Communication time out: sock = %d",
-                                               sock);
+                                    sock);
                        } else {
-                               ERR("UST app recv event failed with ret %d: sock = %d",
-                                               ret, sock);
+                               ERR("UST app recv event failed with ret %d: sock = %d", ret, sock);
                        }
                        goto error;
                }
 
+               {
+                       lttng::urcu::read_lock_guard rcu_lock;
+                       const struct ust_app *app = find_app_by_notify_sock(sock);
+                       if (!app) {
+                               DBG("Application socket %d is being torn down. Abort event notify",
+                                   sock);
+                               ret = -1;
+                               goto error;
+                       }
+               }
+
+               if ((!fields && nr_fields > 0) || (fields && nr_fields == 0)) {
+                       ERR("Invalid return value from lttng_ust_ctl_recv_register_event: fields = %p, nr_fields = %zu",
+                           fields,
+                           nr_fields);
+                       ret = -1;
+                       free(fields);
+                       goto error;
+               }
+
                /*
                 * Add event to the UST registry coming from the notify socket. This
                 * call will free if needed the sig, fields and model_emf_uri. This
                 * code path loses the ownsership of these variables and transfer them
                 * to the this function.
                 */
-               ret = add_event_ust_registry(sock, sobjd, cobjd, name, sig, nr_fields,
-                               fields, loglevel_value, model_emf_uri);
+               ret = add_event_ust_registry(sock,
+                                            sobjd,
+                                            cobjd,
+                                            name,
+                                            sig,
+                                            nr_fields,
+                                            fields,
+                                            loglevel_value,
+                                            model_emf_uri);
                if (ret < 0) {
                        goto error;
                }
@@ -6726,23 +6991,24 @@ int ust_app_recv_notify(int sock)
        case LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL:
        {
                int sobjd, cobjd;
-               size_t nr_fields;
-               struct lttng_ust_ctl_field *fields;
+               size_t field_count;
+               struct lttng_ust_ctl_field *context_fields;
 
                DBG2("UST app ustctl register channel received");
 
-               ret = lttng_ust_ctl_recv_register_channel(sock, &sobjd, &cobjd, &nr_fields,
-                               &fields);
+               ret = lttng_ust_ctl_recv_register_channel(
+                       sock, &sobjd, &cobjd, &field_count, &context_fields);
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
                                DBG3("UST app recv channel failed. Application died: sock = %d",
-                                               sock);
+                                    sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app recv channel failed. Communication time out: sock = %d",
-                                               sock);
+                                    sock);
                        } else {
                                ERR("UST app recv channel failed with ret %d: sock = %d",
-                                               ret, sock);
+                                   ret,
+                                   sock);
                        }
                        goto error;
                }
@@ -6750,10 +7016,10 @@ int ust_app_recv_notify(int sock)
                /*
                 * The fields ownership are transfered to this function call meaning
                 * that if needed it will be freed. After this, it's invalid to access
-                * fields or clean it up.
+                * fields or clean them up.
                 */
-               ret = reply_ust_register_channel(sock, cobjd, nr_fields,
-                               fields);
+               ret = handle_app_register_channel_notification(
+                       sock, cobjd, context_fields, field_count);
                if (ret < 0) {
                        goto error;
                }
@@ -6769,25 +7035,21 @@ int ust_app_recv_notify(int sock)
 
                DBG2("UST app ustctl register enum received");
 
-               ret = lttng_ust_ctl_recv_register_enum(sock, &sobjd, name,
-                               &entries, &nr_entries);
+               ret = lttng_ust_ctl_recv_register_enum(sock, &sobjd, name, &entries, &nr_entries);
                if (ret < 0) {
                        if (ret == -EPIPE || ret == -LTTNG_UST_ERR_EXITING) {
-                               DBG3("UST app recv enum failed. Application died: sock = %d",
-                                               sock);
+                               DBG3("UST app recv enum failed. Application died: sock = %d", sock);
                        } else if (ret == -EAGAIN) {
                                WARN("UST app recv enum failed. Communication time out: sock = %d",
-                                               sock);
+                                    sock);
                        } else {
-                               ERR("UST app recv enum failed with ret %d: sock = %d",
-                                               ret, sock);
+                               ERR("UST app recv enum failed with ret %d: sock = %d", ret, sock);
                        }
                        goto error;
                }
 
-               /* Callee assumes ownership of entries */
-               ret = add_enum_ust_registry(sock, sobjd, name,
-                               entries, nr_entries);
+               /* Callee assumes ownership of entries. */
+               ret = add_enum_ust_registry(sock, sobjd, name, entries, nr_entries);
                if (ret < 0) {
                        goto error;
                }
@@ -6821,9 +7083,9 @@ void ust_app_notify_sock_unregister(int sock)
 
        LTTNG_ASSERT(sock >= 0);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
-       obj = (ust_app_notify_sock_obj *) zmalloc(sizeof(*obj));
+       obj = zmalloc<ust_app_notify_sock_obj>();
        if (!obj) {
                /*
                 * An ENOMEM is kind of uncool. If this strikes we continue the
@@ -6868,7 +7130,6 @@ void ust_app_notify_sock_unregister(int sock)
        (void) lttng_ht_del(ust_app_ht_by_notify_sock, &iter);
 
 close_socket:
-       rcu_read_unlock();
 
        /*
         * Close socket after a grace period to avoid for the socket to be reused
@@ -6883,13 +7144,9 @@ close_socket:
 /*
  * Destroy a ust app data structure and free its memory.
  */
-void ust_app_destroy(struct ust_app *app)
+static void ust_app_destroy(ust_app& app)
 {
-       if (!app) {
-               return;
-       }
-
-       call_rcu(&app->pid_n.head, delete_ust_app_rcu);
+       call_rcu(&app.pid_n.head, delete_ust_app_rcu);
 }
 
 /*
@@ -6898,50 +7155,51 @@ void ust_app_destroy(struct ust_app *app)
  *
  * Returns LTTNG_OK on success or a LTTNG_ERR error code.
  */
-enum lttng_error_code ust_app_snapshot_record(
-               const struct ltt_ust_session *usess,
-               const struct consumer_output *output, int wait,
-               uint64_t nb_packets_per_stream)
+enum lttng_error_code ust_app_snapshot_record(const struct ltt_ust_session *usess,
+                                             const struct consumer_output *output,
+                                             uint64_t nb_packets_per_stream)
 {
        int ret = 0;
        enum lttng_error_code status = LTTNG_OK;
        struct lttng_ht_iter iter;
        struct ust_app *app;
-       char *trace_path = NULL;
+       char *trace_path = nullptr;
 
        LTTNG_ASSERT(usess);
        LTTNG_ASSERT(output);
 
-       rcu_read_lock();
-
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
                struct buffer_reg_uid *reg;
 
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *buf_reg_chan;
                        struct consumer_socket *socket;
                        char pathname[PATH_MAX];
                        size_t consumer_path_offset = 0;
 
-                       if (!reg->registry->reg.ust->metadata_key) {
+                       if (!reg->registry->reg.ust->_metadata_key) {
                                /* Skip since no metadata is present */
                                continue;
                        }
 
                        /* Get consumer socket to use to push the metadata.*/
                        socket = consumer_find_socket_by_bitness(reg->bits_per_long,
-                                       usess->consumer);
+                                                                usess->consumer);
                        if (!socket) {
                                status = LTTNG_ERR_INVALID;
                                goto error;
                        }
 
                        memset(pathname, 0, sizeof(pathname));
-                       ret = snprintf(pathname, sizeof(pathname),
-                                       DEFAULT_UST_TRACE_UID_PATH,
-                                       reg->uid, reg->bits_per_long);
+                       ret = snprintf(pathname,
+                                      sizeof(pathname),
+                                      DEFAULT_UST_TRACE_UID_PATH,
+                                      reg->uid,
+                                      reg->bits_per_long);
                        if (ret < 0) {
                                PERROR("snprintf snapshot path");
                                status = LTTNG_ERR_INVALID;
@@ -6949,42 +7207,49 @@ enum lttng_error_code ust_app_snapshot_record(
                        }
                        /* Free path allowed on previous iteration. */
                        free(trace_path);
-                       trace_path = setup_channel_trace_path(usess->consumer, pathname,
-                                               &consumer_path_offset);
+                       trace_path = setup_channel_trace_path(
+                               usess->consumer, pathname, &consumer_path_offset);
                        if (!trace_path) {
                                status = LTTNG_ERR_INVALID;
                                goto error;
                        }
                        /* Add the UST default trace dir to path. */
-                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
-                                       buf_reg_chan, node.node) {
-                               status = consumer_snapshot_channel(socket,
-                                               buf_reg_chan->consumer_key,
-                                               output, 0, usess->uid,
-                                               usess->gid, &trace_path[consumer_path_offset], wait,
-                                               nb_packets_per_stream);
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
+                               status =
+                                       consumer_snapshot_channel(socket,
+                                                                 buf_reg_chan->consumer_key,
+                                                                 output,
+                                                                 0,
+                                                                 &trace_path[consumer_path_offset],
+                                                                 nb_packets_per_stream);
                                if (status != LTTNG_OK) {
                                        goto error;
                                }
                        }
                        status = consumer_snapshot_channel(socket,
-                                       reg->registry->reg.ust->metadata_key, output, 1,
-                                       usess->uid, usess->gid, &trace_path[consumer_path_offset],
-                                       wait, 0);
+                                                          reg->registry->reg.ust->_metadata_key,
+                                                          output,
+                                                          1,
+                                                          &trace_path[consumer_path_offset],
+                                                          0);
                        if (status != LTTNG_OK) {
                                goto error;
                        }
                }
+
                break;
        }
        case LTTNG_BUFFER_PER_PID:
        {
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        struct consumer_socket *socket;
                        struct lttng_ht_iter chan_iter;
                        struct ust_app_channel *ua_chan;
                        struct ust_app_session *ua_sess;
-                       struct ust_registry_session *registry;
+                       lsu::registry_session *registry;
                        char pathname[PATH_MAX];
                        size_t consumer_path_offset = 0;
 
@@ -6995,8 +7260,7 @@ enum lttng_error_code ust_app_snapshot_record(
                        }
 
                        /* Get the right consumer socket for the application. */
-                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
-                                       output);
+                       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long, output);
                        if (!socket) {
                                status = LTTNG_ERR_INVALID;
                                goto error;
@@ -7004,8 +7268,7 @@ enum lttng_error_code ust_app_snapshot_record(
 
                        /* Add the UST default trace dir to path. */
                        memset(pathname, 0, sizeof(pathname));
-                       ret = snprintf(pathname, sizeof(pathname), "%s",
-                                       ua_sess->path);
+                       ret = snprintf(pathname, sizeof(pathname), "%s", ua_sess->path);
                        if (ret < 0) {
                                status = LTTNG_ERR_INVALID;
                                PERROR("snprintf snapshot path");
@@ -7013,20 +7276,21 @@ enum lttng_error_code ust_app_snapshot_record(
                        }
                        /* Free path allowed on previous iteration. */
                        free(trace_path);
-                       trace_path = setup_channel_trace_path(usess->consumer, pathname,
-                                       &consumer_path_offset);
+                       trace_path = setup_channel_trace_path(
+                               usess->consumer, pathname, &consumer_path_offset);
                        if (!trace_path) {
                                status = LTTNG_ERR_INVALID;
                                goto error;
                        }
-                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
-                                       ua_chan, node.node) {
-                               status = consumer_snapshot_channel(socket,
-                                               ua_chan->key, output, 0,
-                                               lttng_credentials_get_uid(&ua_sess->effective_credentials),
-                                               lttng_credentials_get_gid(&ua_sess->effective_credentials),
-                                               &trace_path[consumer_path_offset], wait,
-                                               nb_packets_per_stream);
+                       cds_lfht_for_each_entry (
+                               ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) {
+                               status =
+                                       consumer_snapshot_channel(socket,
+                                                                 ua_chan->key,
+                                                                 output,
+                                                                 0,
+                                                                 &trace_path[consumer_path_offset],
+                                                                 nb_packets_per_stream);
                                switch (status) {
                                case LTTNG_OK:
                                        break;
@@ -7043,10 +7307,11 @@ enum lttng_error_code ust_app_snapshot_record(
                                continue;
                        }
                        status = consumer_snapshot_channel(socket,
-                                       registry->metadata_key, output, 1,
-                                       lttng_credentials_get_uid(&ua_sess->effective_credentials),
-                                       lttng_credentials_get_gid(&ua_sess->effective_credentials),
-                                       &trace_path[consumer_path_offset], wait, 0);
+                                                          registry->_metadata_key,
+                                                          output,
+                                                          1,
+                                                          &trace_path[consumer_path_offset],
+                                                          0);
                        switch (status) {
                        case LTTNG_OK:
                                break;
@@ -7065,15 +7330,14 @@ enum lttng_error_code ust_app_snapshot_record(
 
 error:
        free(trace_path);
-       rcu_read_unlock();
        return status;
 }
 
 /*
  * Return the size taken by one more packet per stream.
  */
-uint64_t ust_app_get_size_one_more_packet_per_stream(
-               const struct ltt_ust_session *usess, uint64_t cur_nr_packets)
+uint64_t ust_app_get_size_one_more_packet_per_stream(const struct ltt_ust_session *usess,
+                                                    uint64_t cur_nr_packets)
 {
        uint64_t tot_size = 0;
        struct ust_app *app;
@@ -7086,12 +7350,13 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(
        {
                struct buffer_reg_uid *reg;
 
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *buf_reg_chan;
 
-                       rcu_read_lock();
-                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
-                                       buf_reg_chan, node.node) {
+                       lttng::urcu::read_lock_guard read_lock;
+
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
                                if (cur_nr_packets >= buf_reg_chan->num_subbuf) {
                                        /*
                                         * Don't take channel into account if we
@@ -7101,14 +7366,14 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(
                                }
                                tot_size += buf_reg_chan->subbuf_size * buf_reg_chan->stream_count;
                        }
-                       rcu_read_unlock();
                }
                break;
        }
        case LTTNG_BUFFER_PER_PID:
        {
-               rcu_read_lock();
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        struct ust_app_channel *ua_chan;
                        struct ust_app_session *ua_sess;
                        struct lttng_ht_iter chan_iter;
@@ -7119,8 +7384,8 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(
                                continue;
                        }
 
-                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
-                                       ua_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) {
                                if (cur_nr_packets >= ua_chan->attr.num_subbuf) {
                                        /*
                                         * Don't take channel into account if we
@@ -7131,7 +7396,6 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(
                                tot_size += ua_chan->attr.subbuf_size * ua_chan->streams.count;
                        }
                }
-               rcu_read_unlock();
                break;
        }
        default:
@@ -7143,9 +7407,12 @@ uint64_t ust_app_get_size_one_more_packet_per_stream(
 }
 
 int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
-               struct cds_list_head *buffer_reg_uid_list,
-               struct consumer_output *consumer, uint64_t uchan_id,
-               int overwrite, uint64_t *discarded, uint64_t *lost)
+                                         struct cds_list_head *buffer_reg_uid_list,
+                                         struct consumer_output *consumer,
+                                         uint64_t uchan_id,
+                                         int overwrite,
+                                         uint64_t *discarded,
+                                         uint64_t *lost)
 {
        int ret;
        uint64_t consumer_chan_key;
@@ -7154,7 +7421,7 @@ int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
        *lost = 0;
 
        ret = buffer_reg_uid_consumer_channel_key(
-                       buffer_reg_uid_list, uchan_id, &consumer_chan_key);
+               buffer_reg_uid_list, uchan_id, &consumer_chan_key);
        if (ret < 0) {
                /* Not found */
                ret = 0;
@@ -7162,11 +7429,10 @@ int ust_app_uid_get_channel_runtime_stats(uint64_t ust_session_id,
        }
 
        if (overwrite) {
-               ret = consumer_get_lost_packets(ust_session_id,
-                               consumer_chan_key, consumer, lost);
+               ret = consumer_get_lost_packets(ust_session_id, consumer_chan_key, consumer, lost);
        } else {
-               ret = consumer_get_discarded_events(ust_session_id,
-                               consumer_chan_key, consumer, discarded);
+               ret = consumer_get_discarded_events(
+                       ust_session_id, consumer_chan_key, consumer, discarded);
        }
 
 end:
@@ -7174,9 +7440,11 @@ end:
 }
 
 int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
-               struct ltt_ust_channel *uchan,
-               struct consumer_output *consumer, int overwrite,
-               uint64_t *discarded, uint64_t *lost)
+                                         struct ltt_ust_channel *uchan,
+                                         struct consumer_output *consumer,
+                                         int overwrite,
+                                         uint64_t *discarded,
+                                         uint64_t *lost)
 {
        int ret = 0;
        struct lttng_ht_iter iter;
@@ -7188,16 +7456,17 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
        *discarded = 0;
        *lost = 0;
 
-       rcu_read_lock();
        /*
         * Iterate over every registered applications. Sum counters for
         * all applications containing requested session and channel.
         */
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+       lttng::urcu::read_lock_guard read_lock;
+
+       cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                struct lttng_ht_iter uiter;
 
                ua_sess = lookup_session_by_app(usess, app);
-               if (ua_sess == NULL) {
+               if (ua_sess == nullptr) {
                        continue;
                }
 
@@ -7207,13 +7476,12 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                /* If the session is found for the app, the channel must be there */
                LTTNG_ASSERT(ua_chan_node);
 
-               ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+               ua_chan = lttng::utils::container_of(ua_chan_node, &ust_app_channel::node);
 
                if (overwrite) {
                        uint64_t _lost;
 
-                       ret = consumer_get_lost_packets(usess->id, ua_chan->key,
-                                       consumer, &_lost);
+                       ret = consumer_get_lost_packets(usess->id, ua_chan->key, consumer, &_lost);
                        if (ret < 0) {
                                break;
                        }
@@ -7221,8 +7489,8 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                } else {
                        uint64_t _discarded;
 
-                       ret = consumer_get_discarded_events(usess->id,
-                                       ua_chan->key, consumer, &_discarded);
+                       ret = consumer_get_discarded_events(
+                               usess->id, ua_chan->key, consumer, &_discarded);
                        if (ret < 0) {
                                break;
                        }
@@ -7230,23 +7498,20 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess,
                }
        }
 
-       rcu_read_unlock();
        return ret;
 }
 
-static
-int ust_app_regenerate_statedump(struct ltt_ust_session *usess,
-               struct ust_app *app)
+static int ust_app_regenerate_statedump(struct ltt_ust_session *usess, struct ust_app *app)
 {
        int ret = 0;
        struct ust_app_session *ua_sess;
 
        DBG("Regenerating the metadata for ust app pid %d", app->pid);
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
        ua_sess = lookup_session_by_app(usess, app);
-       if (ua_sess == NULL) {
+       if (ua_sess == nullptr) {
                /* The session is in teardown process. Ignore and continue. */
                goto end;
        }
@@ -7265,7 +7530,6 @@ end_unlock:
        pthread_mutex_unlock(&ua_sess->lock);
 
 end:
-       rcu_read_unlock();
        health_code_update();
        return ret;
 }
@@ -7281,9 +7545,9 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
 
        DBG("Regenerating the metadata for all UST apps");
 
-       rcu_read_lock();
+       lttng::urcu::read_lock_guard read_lock;
 
-       cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+       cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                if (!app->compatible) {
                        continue;
                }
@@ -7295,8 +7559,6 @@ int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess)
                }
        }
 
-       rcu_read_unlock();
-
        return 0;
 }
 
@@ -7310,38 +7572,35 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
        int ret;
        enum lttng_error_code cmd_ret = LTTNG_OK;
        struct lttng_ht_iter iter;
-       struct ust_app *app;
        struct ltt_ust_session *usess = session->ust_session;
 
        LTTNG_ASSERT(usess);
 
-       rcu_read_lock();
-
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
                struct buffer_reg_uid *reg;
 
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *buf_reg_chan;
                        struct consumer_socket *socket;
+                       lttng::urcu::read_lock_guard read_lock;
 
                        /* Get consumer socket to use to push the metadata.*/
                        socket = consumer_find_socket_by_bitness(reg->bits_per_long,
-                                       usess->consumer);
+                                                                usess->consumer);
                        if (!socket) {
                                cmd_ret = LTTNG_ERR_INVALID;
                                goto error;
                        }
 
                        /* Rotate the data channels. */
-                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
-                                       buf_reg_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
                                ret = consumer_rotate_channel(socket,
-                                               buf_reg_chan->consumer_key,
-                                               usess->uid, usess->gid,
-                                               usess->consumer,
-                                               /* is_metadata_channel */ false);
+                                                             buf_reg_chan->consumer_key,
+                                                             usess->consumer,
+                                                             /* is_metadata_channel */ false);
                                if (ret < 0) {
                                        cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER;
                                        goto error;
@@ -7356,18 +7615,20 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
                         * operations (i.e add context) and lead to data
                         * channels created with no metadata channel.
                         */
-                       if (!reg->registry->reg.ust->metadata_key) {
+                       if (!reg->registry->reg.ust->_metadata_key) {
                                /* Skip since no metadata is present. */
                                continue;
                        }
 
-                       (void) push_metadata(reg->registry->reg.ust, usess->consumer);
+                       {
+                               auto locked_registry = reg->registry->reg.ust->lock();
+                               (void) push_metadata(locked_registry, usess->consumer);
+                       }
 
                        ret = consumer_rotate_channel(socket,
-                                       reg->registry->reg.ust->metadata_key,
-                                       usess->uid, usess->gid,
-                                       usess->consumer,
-                                       /* is_metadata_channel */ true);
+                                                     reg->registry->reg.ust->_metadata_key,
+                                                     usess->consumer,
+                                                     /* is_metadata_channel */ true);
                        if (ret < 0) {
                                cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER;
                                goto error;
@@ -7377,67 +7638,74 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
        }
        case LTTNG_BUFFER_PER_PID:
        {
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+               ust_app *raw_app;
+
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, raw_app, pid_n.node) {
                        struct consumer_socket *socket;
                        struct lttng_ht_iter chan_iter;
                        struct ust_app_channel *ua_chan;
                        struct ust_app_session *ua_sess;
-                       struct ust_registry_session *registry;
+                       lsu::registry_session *registry;
+                       bool app_reference_taken;
 
-                       ua_sess = lookup_session_by_app(usess, app);
+                       app_reference_taken = ust_app_get(*raw_app);
+                       if (!app_reference_taken) {
+                               /* Application unregistered concurrently, skip it. */
+                               DBG("Could not get application reference as it is being torn down; skipping application");
+                               continue;
+                       }
+
+                       ust_app_reference app(raw_app);
+                       raw_app = nullptr;
+
+                       ua_sess = lookup_session_by_app(usess, app.get());
                        if (!ua_sess) {
                                /* Session not associated with this app. */
                                continue;
                        }
 
                        /* Get the right consumer socket for the application. */
-                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
-                                       usess->consumer);
+                       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long,
+                                                                usess->consumer);
                        if (!socket) {
                                cmd_ret = LTTNG_ERR_INVALID;
                                goto error;
                        }
 
                        registry = get_session_registry(ua_sess);
-                       if (!registry) {
-                               DBG("Application session is being torn down. Skip application.");
-                               continue;
-                       }
+                       LTTNG_ASSERT(registry);
 
                        /* Rotate the data channels. */
-                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
-                                       ua_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) {
                                ret = consumer_rotate_channel(socket,
-                                               ua_chan->key,
-                                               lttng_credentials_get_uid(&ua_sess->effective_credentials),
-                                               lttng_credentials_get_gid(&ua_sess->effective_credentials),
-                                               ua_sess->consumer,
-                                               /* is_metadata_channel */ false);
+                                                             ua_chan->key,
+                                                             ua_sess->consumer,
+                                                             /* is_metadata_channel */ false);
                                if (ret < 0) {
-                                       /* Per-PID buffer and application going away. */
-                                       if (ret == -LTTNG_ERR_CHAN_NOT_FOUND)
-                                               continue;
                                        cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER;
                                        goto error;
                                }
                        }
 
                        /* Rotate the metadata channel. */
-                       (void) push_metadata(registry, usess->consumer);
+                       {
+                               auto locked_registry = registry->lock();
+
+                               (void) push_metadata(locked_registry, usess->consumer);
+                       }
+
                        ret = consumer_rotate_channel(socket,
-                                       registry->metadata_key,
-                                       lttng_credentials_get_uid(&ua_sess->effective_credentials),
-                                       lttng_credentials_get_gid(&ua_sess->effective_credentials),
-                                       ua_sess->consumer,
-                                       /* is_metadata_channel */ true);
+                                                     registry->_metadata_key,
+                                                     ua_sess->consumer,
+                                                     /* is_metadata_channel */ true);
                        if (ret < 0) {
-                               /* Per-PID buffer and application going away. */
-                               if (ret == -LTTNG_ERR_CHAN_NOT_FOUND)
-                                       continue;
                                cmd_ret = LTTNG_ERR_ROTATION_FAIL_CONSUMER;
                                goto error;
                        }
                }
+
                break;
        }
        default:
@@ -7448,12 +7716,10 @@ enum lttng_error_code ust_app_rotate_session(struct ltt_session *session)
        cmd_ret = LTTNG_OK;
 
 error:
-       rcu_read_unlock();
        return cmd_ret;
 }
 
-enum lttng_error_code ust_app_create_channel_subdirectories(
-               const struct ltt_ust_session *usess)
+enum lttng_error_code ust_app_create_channel_subdirectories(const struct ltt_ust_session *usess)
 {
        enum lttng_error_code ret = LTTNG_OK;
        struct lttng_ht_iter iter;
@@ -7462,17 +7728,19 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
        int fmt_ret;
 
        LTTNG_ASSERT(usess->current_trace_chunk);
-       rcu_read_lock();
 
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
                struct buffer_reg_uid *reg;
+               lttng::urcu::read_lock_guard read_lock;
 
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        fmt_ret = asprintf(&pathname_index,
-                                      DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR,
-                                      reg->uid, reg->bits_per_long);
+                                          DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH
+                                                                "/" DEFAULT_INDEX_DIR,
+                                          reg->uid,
+                                          reg->bits_per_long);
                        if (fmt_ret < 0) {
                                ERR("Failed to format channel index directory");
                                ret = LTTNG_ERR_CREATE_DIR_FAIL;
@@ -7484,8 +7752,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
                         * of implicitly creating the channel's path.
                         */
                        chunk_status = lttng_trace_chunk_create_subdirectory(
-                                       usess->current_trace_chunk,
-                                       pathname_index);
+                               usess->current_trace_chunk, pathname_index);
                        free(pathname_index);
                        if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                                ret = LTTNG_ERR_CREATE_DIR_FAIL;
@@ -7497,22 +7764,21 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
        case LTTNG_BUFFER_PER_PID:
        {
                struct ust_app *app;
+               lttng::urcu::read_lock_guard read_lock;
 
                /*
                 * Create the toplevel ust/ directory in case no apps are running.
                 */
-               chunk_status = lttng_trace_chunk_create_subdirectory(
-                               usess->current_trace_chunk,
-                               DEFAULT_UST_TRACE_DIR);
+               chunk_status = lttng_trace_chunk_create_subdirectory(usess->current_trace_chunk,
+                                                                    DEFAULT_UST_TRACE_DIR);
                if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                        ret = LTTNG_ERR_CREATE_DIR_FAIL;
                        goto error;
                }
 
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app,
-                               pid_n.node) {
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        struct ust_app_session *ua_sess;
-                       struct ust_registry_session *registry;
+                       lsu::registry_session *registry;
 
                        ua_sess = lookup_session_by_app(usess, app);
                        if (!ua_sess) {
@@ -7527,8 +7793,8 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
                        }
 
                        fmt_ret = asprintf(&pathname_index,
-                                       DEFAULT_UST_TRACE_DIR "/%s/" DEFAULT_INDEX_DIR,
-                                       ua_sess->path);
+                                          DEFAULT_UST_TRACE_DIR "/%s/" DEFAULT_INDEX_DIR,
+                                          ua_sess->path);
                        if (fmt_ret < 0) {
                                ERR("Failed to format channel index directory");
                                ret = LTTNG_ERR_CREATE_DIR_FAIL;
@@ -7539,8 +7805,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
                         * of implicitly creating the channel's path.
                         */
                        chunk_status = lttng_trace_chunk_create_subdirectory(
-                                       usess->current_trace_chunk,
-                                       pathname_index);
+                               usess->current_trace_chunk, pathname_index);
                        free(pathname_index);
                        if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
                                ret = LTTNG_ERR_CREATE_DIR_FAIL;
@@ -7555,7 +7820,6 @@ enum lttng_error_code ust_app_create_channel_subdirectories(
 
        ret = LTTNG_OK;
 error:
-       rcu_read_unlock();
        return ret;
 }
 
@@ -7574,8 +7838,6 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
 
        LTTNG_ASSERT(usess);
 
-       rcu_read_lock();
-
        if (usess->active) {
                ERR("Expecting inactive session %s (%" PRIu64 ")", session->name, session->id);
                cmd_ret = LTTNG_ERR_FATAL;
@@ -7586,38 +7848,40 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
        case LTTNG_BUFFER_PER_UID:
        {
                struct buffer_reg_uid *reg;
+               lttng::urcu::read_lock_guard read_lock;
 
-               cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *buf_reg_chan;
                        struct consumer_socket *socket;
 
                        /* Get consumer socket to use to push the metadata.*/
                        socket = consumer_find_socket_by_bitness(reg->bits_per_long,
-                                       usess->consumer);
+                                                                usess->consumer);
                        if (!socket) {
                                cmd_ret = LTTNG_ERR_INVALID;
                                goto error_socket;
                        }
 
                        /* Clear the data channels. */
-                       cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter,
-                                       buf_reg_chan, node.node) {
-                               ret = consumer_clear_channel(socket,
-                                               buf_reg_chan->consumer_key);
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
+                               ret = consumer_clear_channel(socket, buf_reg_chan->consumer_key);
                                if (ret < 0) {
                                        goto error;
                                }
                        }
 
-                       (void) push_metadata(reg->registry->reg.ust, usess->consumer);
+                       {
+                               auto locked_registry = reg->registry->reg.ust->lock();
+                               (void) push_metadata(locked_registry, usess->consumer);
+                       }
 
                        /*
                         * Clear the metadata channel.
                         * Metadata channel is not cleared per se but we still need to
                         * perform a rotation operation on it behind the scene.
                         */
-                       ret = consumer_clear_channel(socket,
-                                       reg->registry->reg.ust->metadata_key);
+                       ret = consumer_clear_channel(socket, reg->registry->reg.ust->_metadata_key);
                        if (ret < 0) {
                                goto error;
                        }
@@ -7626,12 +7890,14 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
        }
        case LTTNG_BUFFER_PER_PID:
        {
-               cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               lttng::urcu::read_lock_guard read_lock;
+
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        struct consumer_socket *socket;
                        struct lttng_ht_iter chan_iter;
                        struct ust_app_channel *ua_chan;
                        struct ust_app_session *ua_sess;
-                       struct ust_registry_session *registry;
+                       lsu::registry_session *registry;
 
                        ua_sess = lookup_session_by_app(usess, app);
                        if (!ua_sess) {
@@ -7640,8 +7906,8 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
                        }
 
                        /* Get the right consumer socket for the application. */
-                       socket = consumer_find_socket_by_bitness(app->bits_per_long,
-                                       usess->consumer);
+                       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long,
+                                                                usess->consumer);
                        if (!socket) {
                                cmd_ret = LTTNG_ERR_INVALID;
                                goto error_socket;
@@ -7654,8 +7920,8 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
                        }
 
                        /* Clear the data channels. */
-                       cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter,
-                                       ua_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) {
                                ret = consumer_clear_channel(socket, ua_chan->key);
                                if (ret < 0) {
                                        /* Per-PID buffer and application going away. */
@@ -7666,14 +7932,17 @@ enum lttng_error_code ust_app_clear_session(struct ltt_session *session)
                                }
                        }
 
-                       (void) push_metadata(registry, usess->consumer);
+                       {
+                               auto locked_registry = registry->lock();
+                               (void) push_metadata(locked_registry, usess->consumer);
+                       }
 
                        /*
                         * Clear the metadata channel.
                         * Metadata channel is not cleared per se but we still need to
                         * perform rotation operation on it behind the scene.
                         */
-                       ret = consumer_clear_channel(socket, registry->metadata_key);
+                       ret = consumer_clear_channel(socket, registry->_metadata_key);
                        if (ret < 0) {
                                /* Per-PID buffer and application going away. */
                                if (ret == -LTTNG_ERR_CHAN_NOT_FOUND) {
@@ -7703,7 +7972,6 @@ error:
 
 error_socket:
 end:
-       rcu_read_unlock();
        return cmd_ret;
 }
 
@@ -7731,31 +7999,27 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
 
        LTTNG_ASSERT(usess);
 
-       rcu_read_lock();
-
        switch (usess->buffer_type) {
        case LTTNG_BUFFER_PER_UID:
        {
                struct buffer_reg_uid *reg;
 
-               cds_list_for_each_entry (
-                               reg, &usess->buffer_reg_uid_list, lnode) {
+               cds_list_for_each_entry (reg, &usess->buffer_reg_uid_list, lnode) {
                        struct buffer_reg_channel *buf_reg_chan;
                        struct consumer_socket *socket;
+                       lttng::urcu::read_lock_guard read_lock;
 
-                       socket = consumer_find_socket_by_bitness(
-                                       reg->bits_per_long, usess->consumer);
+                       socket = consumer_find_socket_by_bitness(reg->bits_per_long,
+                                                                usess->consumer);
                        if (!socket) {
                                ret = LTTNG_ERR_FATAL;
                                goto error;
                        }
 
-                       cds_lfht_for_each_entry(reg->registry->channels->ht,
-                                       &iter.iter, buf_reg_chan, node.node) {
-                               const int open_ret =
-                                               consumer_open_channel_packets(
-                                                       socket,
-                                                       buf_reg_chan->consumer_key);
+                       cds_lfht_for_each_entry (
+                               reg->registry->channels->ht, &iter.iter, buf_reg_chan, node.node) {
+                               const int open_ret = consumer_open_channel_packets(
+                                       socket, buf_reg_chan->consumer_key);
 
                                if (open_ret < 0) {
                                        ret = LTTNG_ERR_UNK;
@@ -7768,14 +8032,14 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
        case LTTNG_BUFFER_PER_PID:
        {
                struct ust_app *app;
+               lttng::urcu::read_lock_guard read_lock;
 
-               cds_lfht_for_each_entry (
-                               ust_app_ht->ht, &iter.iter, app, pid_n.node) {
+               cds_lfht_for_each_entry (ust_app_ht->ht, &iter.iter, app, pid_n.node) {
                        struct consumer_socket *socket;
                        struct lttng_ht_iter chan_iter;
                        struct ust_app_channel *ua_chan;
                        struct ust_app_session *ua_sess;
-                       struct ust_registry_session *registry;
+                       lsu::registry_session *registry;
 
                        ua_sess = lookup_session_by_app(usess, app);
                        if (!ua_sess) {
@@ -7784,8 +8048,8 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
                        }
 
                        /* Get the right consumer socket for the application. */
-                       socket = consumer_find_socket_by_bitness(
-                                       app->bits_per_long, usess->consumer);
+                       socket = consumer_find_socket_by_bitness(app->abi.bits_per_long,
+                                                                usess->consumer);
                        if (!socket) {
                                ret = LTTNG_ERR_FATAL;
                                goto error;
@@ -7797,12 +8061,10 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
                                continue;
                        }
 
-                       cds_lfht_for_each_entry(ua_sess->channels->ht,
-                                       &chan_iter.iter, ua_chan, node.node) {
+                       cds_lfht_for_each_entry (
+                               ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) {
                                const int open_ret =
-                                               consumer_open_channel_packets(
-                                                       socket,
-                                                       ua_chan->key);
+                                       consumer_open_channel_packets(socket, ua_chan->key);
 
                                if (open_ret < 0) {
                                        /*
@@ -7826,6 +8088,54 @@ enum lttng_error_code ust_app_open_packets(struct ltt_session *session)
        }
 
 error:
-       rcu_read_unlock();
        return ret;
 }
+
+lsu::ctl_field_quirks ust_app::ctl_field_quirks() const
+{
+       /*
+        * Application contexts are expressed as variants. LTTng-UST announces
+        * those by registering an enumeration named `..._tag`. It then registers a
+        * variant as part of the event context that contains the various possible
+        * types.
+        *
+        * Unfortunately, the names used in the enumeration and variant don't
+        * match: the enumeration names are all prefixed with an underscore while
+        * the variant type tag fields aren't.
+        *
+        * While the CTF 1.8.3 specification mentions that
+        * underscores *should* (not *must*) be removed by CTF readers. Babeltrace
+        * 1.x (and possibly others) expect a perfect match between the names used
+        * by tags and variants.
+        *
+        * When the UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS quirk is enabled,
+        * the variant's fields are modified to match the mappings of its tag.
+        *
+        * From ABI version >= 10.x, the variant fields and tag mapping names
+        * correctly match, making this quirk unnecessary.
+        */
+       return v_major <= 9 ? lsu::ctl_field_quirks::UNDERSCORE_PREFIXED_VARIANT_TAG_MAPPINGS :
+                             lsu::ctl_field_quirks::NONE;
+}
+
+static void ust_app_release(urcu_ref *ref)
+{
+       auto& app = *lttng::utils::container_of(ref, &ust_app::ref);
+
+       ust_app_unregister(app);
+       ust_app_destroy(app);
+}
+
+bool ust_app_get(ust_app& app)
+{
+       return urcu_ref_get_unless_zero(&app.ref);
+}
+
+void ust_app_put(struct ust_app *app)
+{
+       if (!app) {
+               return;
+       }
+
+       urcu_ref_put(&app->ref, ust_app_release);
+}
This page took 0.196454 seconds and 4 git commands to generate.