+ pthread_mutex_lock(&ua_sess->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) {
+ goto next_app;
+ }
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel,
+ node);
+ ret = create_ust_app_channel_context(ua_sess, ua_chan, &uctx->ctx, app);
+ if (ret < 0) {
+ goto next_app;
+ }
+ next_app:
+ pthread_mutex_unlock(&ua_sess->lock);
+ }
+
+ rcu_read_unlock();
+ return ret;
+}
+
+/*
+ * Enable event for a channel from a UST session for a specific PID.
+ */
+int ust_app_enable_event_pid(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, pid_t pid)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter;
+ struct lttng_ht_node_str *ua_chan_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_channel *ua_chan;
+ struct ust_app_event *ua_event;
+
+ DBG("UST app enabling event %s for PID %d", uevent->attr.name, pid);
+
+ rcu_read_lock();
+
+ app = ust_app_find_by_pid(pid);
+ if (app == NULL) {
+ ERR("UST app enable event per PID %d not found", pid);
+ ret = -1;
+ goto end;
+ }
+
+ if (!app->compatible) {
+ ret = 0;
+ goto end;
+ }
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (!ua_sess) {
+ /* The application has problem or is probably dead. */
+ ret = 0;
+ goto end;
+ }
+
+ pthread_mutex_lock(&ua_sess->lock);
+ /* Lookup channel in the ust app session */
+ lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
+ ua_chan_node = lttng_ht_iter_get_node_str(&iter);
+ /* If the channel is not found, there is a code flow error */
+ assert(ua_chan_node);
+
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+
+ ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion);
+ if (ua_event == NULL) {
+ ret = create_ust_app_event(ua_sess, ua_chan, uevent, app);
+ if (ret < 0) {
+ goto end_unlock;
+ }
+ } else {
+ ret = enable_ust_app_event(ua_sess, ua_event, app);
+ if (ret < 0) {
+ goto end_unlock;
+ }
+ }
+
+end_unlock:
+ pthread_mutex_unlock(&ua_sess->lock);
+end:
+ rcu_read_unlock();
+ return ret;
+}
+
+/*
+ * Calibrate registered applications.
+ */
+int ust_app_calibrate_glb(struct lttng_ust_calibrate *calibrate)
+{
+ int ret = 0;
+ 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) {
+ if (!app->compatible) {
+ /*
+ * TODO: In time, we should notice the caller of this error by
+ * telling him that this is a version error.
+ */
+ continue;
+ }
+
+ health_code_update();
+
+ ret = ustctl_calibrate(app->sock, calibrate);
+ if (ret < 0) {
+ switch (ret) {
+ case -ENOSYS:
+ /* Means that it's not implemented on the tracer side. */
+ ret = 0;
+ break;
+ default:
+ DBG2("Calibrate app PID %d returned with error %d",
+ app->pid, ret);
+ break;
+ }
+ }
+ }
+
+ DBG("UST app global domain calibration finished");
+
+ rcu_read_unlock();
+
+ health_code_update();
+
+ return ret;
+}
+
+/*
+ * Receive registration and populate the given msg structure.
+ *
+ * On success return 0 else a negative value returned by the ustctl call.
+ */
+int ust_app_recv_registration(int sock, struct ust_register_msg *msg)
+{
+ int ret;
+ uint32_t pid, ppid, uid, gid;
+
+ assert(msg);
+
+ ret = ustctl_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:
+ case ECONNRESET:
+ case LTTNG_UST_ERR_EXITING:
+ DBG3("UST app recv reg message failed. Application died");
+ 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);
+ break;
+ default:
+ ERR("UST app recv reg message failed with ret %d", ret);
+ break;
+ }
+ goto error;
+ }
+ msg->pid = (pid_t) pid;
+ msg->ppid = (pid_t) ppid;
+ msg->uid = (uid_t) uid;
+ msg->gid = (gid_t) gid;
+
+error:
+ return ret;
+}
+
+/*
+ * Return a ust app channel object using the application object and the channel
+ * 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)
+{
+ struct lttng_ht_node_ulong *node;
+ struct lttng_ht_iter iter;
+ struct ust_app_channel *ua_chan = NULL;
+
+ assert(app);
+
+ lttng_ht_lookup(app->ust_objd, (void *)((unsigned long) objd), &iter);
+ node = lttng_ht_iter_get_node_ulong(&iter);
+ if (node == NULL) {
+ 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);
+
+error:
+ return ua_chan;
+}
+
+/*
+ * Reply to a register channel notification from an application on the notify
+ * socket. The channel metadata is also created.
+ *
+ * The session UST registry lock is acquired in this function.
+ *
+ * On success 0 is returned else a negative value.
+ */
+static int reply_ust_register_channel(int sock, int sobjd, int cobjd,
+ size_t nr_fields, struct ustctl_field *fields)
+{
+ int ret, ret_code = 0;
+ uint32_t chan_id, reg_count;
+ uint64_t chan_reg_key;
+ enum ustctl_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 *chan_reg;
+
+ rcu_read_lock();
+
+ /* 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 teardown. Abort event notify",
+ sock);
+ ret = 0;
+ free(fields);
+ goto error_rcu_unlock;
+ }
+
+ /* Lookup channel by UST object descriptor. */
+ ua_chan = find_channel_by_objd(app, cobjd);
+ if (!ua_chan) {
+ DBG("Application channel is being teardown. Abort event notify");
+ ret = 0;
+ free(fields);
+ goto error_rcu_unlock;
+ }
+
+ 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);
+ assert(registry);
+
+ /* Depending on the buffer type, a different channel key is used. */
+ 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(®istry->lock);
+
+ chan_reg = ust_registry_channel_find(registry, chan_reg_key);
+ assert(chan_reg);
+
+ if (!chan_reg->register_done) {
+ reg_count = ust_registry_get_event_count(chan_reg);
+ if (reg_count < 31) {
+ type = USTCTL_CHANNEL_HEADER_COMPACT;
+ } else {
+ type = USTCTL_CHANNEL_HEADER_LARGE;
+ }
+
+ chan_reg->nr_ctx_fields = nr_fields;
+ chan_reg->ctx_fields = fields;
+ chan_reg->header_type = type;
+ } else {
+ /* Get current already assigned values. */
+ type = chan_reg->header_type;
+ free(fields);
+ /* Set to NULL so the error path does not do a double free. */
+ fields = NULL;
+ }
+ /* Channel id is set during the object creation. */
+ chan_id = chan_reg->chan_id;
+
+ /* Append to metadata */
+ if (!chan_reg->metadata_dumped) {
+ ret_code = ust_metadata_channel_statedump(registry, chan_reg);
+ if (ret_code) {
+ ERR("Error appending channel metadata (errno = %d)", ret_code);
+ goto reply;