+ pthread_mutex_lock(&ua_sess->lock);
+
+ 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;
+ }
+
+ ua_chan = caa_container_of(ua_chan_node, struct 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,
+ uevent->attr.token);
+ 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;
+ }
+
+ ret = enable_ust_app_event(ua_sess, ua_event, app);
+ if (ret < 0) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ goto error;
+ }
+ next_app:
+ pthread_mutex_unlock(&ua_sess->lock);
+ }
+
+error:
+ rcu_read_unlock();
+ return ret;
+}
+
+/*
+ * Enable event for a specific session and map on the tracer.
+ */
+int ust_app_enable_map_event_glb(struct ltt_ust_session *usess,
+ struct ltt_ust_map *umap, struct ltt_ust_event *uevent)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter, uiter;
+ struct lttng_ht_node_str *ua_map_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_map *ua_map;
+ struct ust_app_event *ua_event;
+
+ assert(usess->active);
+ DBG("UST app enabling event %s for all apps for session id %" PRIu64,
+ uevent->attr.name, usess->id);
+
+ /*
+ * NOTE: At this point, this function is called only if the session and
+ * map passed are already created for all apps. and enabled on the
+ * tracer also.
+ */
+
+ rcu_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;
+ }
+
+ pthread_mutex_lock(&ua_sess->lock);
+
+ if (ua_sess->deleted) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
+ /* Lookup map in the ust app session */
+ lttng_ht_lookup(ua_sess->maps, (void *)umap->name, &uiter);
+ ua_map_node = lttng_ht_iter_get_node_str(&uiter);
+ /*
+ * It is possible that the map cannot be found is
+ * the map/event creation occurs concurrently with
+ * an application exit.
+ */
+ if (!ua_map_node) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ continue;
+ }
+
+ ua_map = caa_container_of(ua_map_node, struct ust_app_map, node);
+
+ /* Get event node */
+ ua_event = find_ust_app_event(ua_map->events, uevent->attr.name,
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion,
+ uevent->attr.token);
+ 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;
+ }
+
+ ret = enable_ust_app_event(ua_sess, ua_event, app);
+ if (ret < 0) {
+ pthread_mutex_unlock(&ua_sess->lock);
+ goto error;
+ }
+ next_app:
+ pthread_mutex_unlock(&ua_sess->lock);
+ }
+
+error:
+ rcu_read_unlock();
+ return ret;
+}
+
+/*
+ * For a specific existing UST session and UST channel, creates the event for
+ * all registered apps.
+ */
+int ust_app_create_channel_event_glb(struct ltt_ust_session *usess,
+ struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter, uiter;
+ struct lttng_ht_node_str *ua_chan_node;
+ struct ust_app *app;
+ struct ust_app_session *ua_sess;
+ struct ust_app_channel *ua_chan;
+
+ assert(usess->active);
+ DBG("UST app creating event %s for all apps for session id %" PRIu64,
+ uevent->attr.name, usess->id);
+
+ rcu_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;
+ }
+
+ pthread_mutex_lock(&ua_sess->lock);
+
+ 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 */
+ assert(ua_chan_node);
+
+ ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
+
+ ret = create_ust_app_channel_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;
+ }
+ DBG2("UST app event %s already exist on app PID %d",
+ uevent->attr.name, app->pid);
+ continue;
+ }
+ }
+
+ rcu_read_unlock();
+ return ret;
+}
+
+static
+int snapshot_key_values(struct ustctl_daemon_counter *map_handle,
+ struct lttng_ht *key_to_bucket_index_ht, int cpu,
+ const char *key_filter, struct lttng_ht *values)
+{
+ int ret;
+ struct lttng_ht_iter key_iter;
+ struct ust_registry_map_index_ht_entry *map_index_entry;
+
+ /* Iterate over all the formated_key -> counter index */
+ cds_lfht_for_each_entry(key_to_bucket_index_ht->ht,
+ &key_iter.iter, map_index_entry, node.node) {
+ bool overflow = 0, underflow = 0;
+ int64_t local_value = 0;
+ size_t dimension_indexes[1] = {map_index_entry->index};
+
+ if (key_filter && strcmp(key_filter,
+ map_index_entry->formated_key) != 0) {
+ continue;
+ }
+
+ ret = ustctl_counter_read(map_handle,
+ dimension_indexes, cpu, &local_value,
+ &overflow, &underflow);
+ if (ret) {
+ ERR("Error getting counter value from the tracer: key = '%s'",
+ map_index_entry->formated_key);
+ ret = -1;
+ goto end;
+ }
+
+ map_add_or_increment_map_values(values,
+ map_index_entry->formated_key, local_value,
+ underflow, overflow);
+ }
+ ret = 0;
+end:
+ return ret;
+}
+
+static
+int ust_app_map_list_values_per_uid_with_bitness_and_cpu(
+ const struct ltt_ust_session *usess,
+ const struct ltt_ust_map *umap,
+ uint32_t app_bitness,
+ uint32_t cpu,
+ const char *key_filter,
+ struct lttng_ht *values)
+{
+ int ret = 0;
+ struct lttng_ht_iter iter;
+ struct buffer_reg_uid *buf_reg_uid;
+ struct buffer_reg_map *buf_reg_map;
+ struct ust_registry_session *ust_reg_sess;
+ struct lttng_ht_node_u64 *ust_reg_map_node;
+ struct ust_registry_map *ust_reg_map;
+
+ buf_reg_uid = buffer_reg_uid_find(usess->id, app_bitness, usess->uid);
+ if (!buf_reg_uid) {
+ /*
+ * Buffer registry entry for uid not found. Probably no app for
+ * this UID at the moment.
+ */
+ DBG("No buffer registry entry found for uid: ust-sess-id = %"PRIu64", bitness = %"PRIu32", uid = %d",
+ usess->id, app_bitness, usess->uid);
+ /*
+ * Not an error. Leave the key value pair unchanged and return.
+ */
+ ret = 0;
+ goto end;
+ }
+
+ buf_reg_map = buffer_reg_map_find(umap->id, buf_reg_uid);
+ if (!buf_reg_uid) {
+ ERR("Error getting per-uid map buffer registry entry: map-id = %"PRIu64,
+ umap->id);
+ ret = -1;
+ goto end;
+ }
+
+ ust_reg_sess = buf_reg_uid->registry->reg.ust;
+
+ /* Get the ust_reg map object from the registry */
+ // FIXME: frdeso: This can be changed to ust_registry_map_find() right?
+
+ lttng_ht_lookup(ust_reg_sess->maps, (void *) &umap->id, &iter);
+ ust_reg_map_node = lttng_ht_iter_get_node_u64(&iter);
+ if (!ust_reg_map_node) {
+ ERR("Error getting per-uid map buffer registry entry: map-id = %"PRIu64,
+ umap->id);
+ ret = -1;
+ goto end;
+ }
+ ust_reg_map = caa_container_of(ust_reg_map_node,
+ struct ust_registry_map, node);
+
+ ret = snapshot_key_values(buf_reg_map->daemon_counter,
+ ust_reg_map->key_string_to_bucket_index_ht,
+ cpu, key_filter, values);
+ if (ret) {
+ abort();
+ }
+
+
+ ret = 0;
+end:
+ return ret;
+}
+
+static
+int ust_app_map_list_values_per_uid(const struct ltt_ust_session *usess,
+ const struct ltt_ust_map *umap,
+ const struct lttng_map_query *query,
+ struct lttng_map_content *map_content)
+{
+ int i, ret = 0;
+ enum lttng_map_query_status map_query_status;
+ const char *key_filter;
+ struct lttng_ht *values = NULL;
+ bool sum_cpus = lttng_map_query_get_config_sum_by_cpu(query);
+ enum lttng_map_query_config_buffer config_buffer;
+ enum lttng_map_query_config_cpu config_cpu;
+ int selected_cpu;
+
+ map_query_status = lttng_map_query_get_key_filter(query, &key_filter);
+ if (map_query_status == LTTNG_MAP_QUERY_STATUS_NONE) {
+ key_filter = NULL;
+ } else if (map_query_status != LTTNG_MAP_QUERY_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ config_cpu = lttng_map_query_get_config_cpu(query);
+ if (config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
+ unsigned int count;
+ map_query_status = lttng_map_query_get_cpu_count(query, &count);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+ assert(count == 1);
+
+ map_query_status = lttng_map_query_get_cpu_at_index(query, 0,
+ &selected_cpu);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+ }
+
+ config_buffer = lttng_map_query_get_config_buffer(query);
+ if (config_buffer == LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) {
+ unsigned int count;
+ uid_t selected_uid;
+
+ map_query_status = lttng_map_query_get_uid_count(query, &count);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+ assert(count == 1);
+
+ map_query_status = lttng_map_query_get_uid_at_index(query, 0,
+ &selected_uid);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+
+ if (selected_uid != usess->uid) {
+ ret = 0;
+ goto end;
+ }
+ }
+
+ if (sum_cpus) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ }
+
+ for (i = 0; i < umap->nr_cpu; i++) {
+ if (config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
+ if (selected_cpu != i) {
+ continue;
+ }
+ }
+
+ if (!sum_cpus) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ }
+
+ ret = ust_app_map_list_values_per_uid_with_bitness_and_cpu(
+ usess, umap, 32, i, key_filter,
+ values);
+ if (ret) {
+ abort();
+ }
+
+ ret = ust_app_map_list_values_per_uid_with_bitness_and_cpu(
+ usess, umap, 64, i, key_filter,
+ values);
+ if (ret) {
+ abort();
+ }
+ if (!sum_cpus) {
+ ret = map_new_content_section(map_content,
+ LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID,
+ sum_cpus, usess->uid, i, values);
+ if (ret) {
+ abort();
+ }
+
+ lttng_ht_destroy(values);
+ }
+ }
+
+ if (sum_cpus) {
+ ret = map_new_content_section(map_content,
+ LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_UID,
+ sum_cpus, usess->uid, 0, values);
+ if (ret) {
+ abort();
+ }
+ lttng_ht_destroy(values);
+ }
+
+end:
+ return ret;
+}
+
+static
+int append_dead_app_kv(struct ltt_ust_map *umap,
+ const char *key_filter,
+ struct lttng_map_content *map_content)
+{
+ int ret;
+ struct lttng_ht *dead_app_kv_ht;
+ struct map_kv_ht_entry *kv_entry;
+ struct lttng_ht_iter key_iter;
+
+ struct lttng_ht *values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+
+ pthread_mutex_lock(&(umap->dead_app_kv_values.lock));
+
+ assert(umap->dead_app_kv_values.dead_app_kv_values_64bits);
+ dead_app_kv_ht = umap->dead_app_kv_values.dead_app_kv_values_64bits;
+
+ cds_lfht_for_each_entry(dead_app_kv_ht->ht, &key_iter.iter, kv_entry,
+ node.node) {
+ if (key_filter && strcmp(key_filter, kv_entry->key) != 0) {
+ continue;
+ }
+ map_add_or_increment_map_values(values, kv_entry->key,
+ kv_entry->value, kv_entry->has_underflowed,
+ kv_entry->has_overflowed);
+ }
+
+ assert(umap->dead_app_kv_values.dead_app_kv_values_32bits);
+
+ dead_app_kv_ht = umap->dead_app_kv_values.dead_app_kv_values_32bits;
+ cds_lfht_for_each_entry(dead_app_kv_ht->ht, &key_iter.iter, kv_entry,
+ node.node) {
+ if (key_filter && strcmp(key_filter, kv_entry->key) != 0) {
+ continue;
+ }
+ map_add_or_increment_map_values(values, kv_entry->key,
+ kv_entry->value, kv_entry->has_underflowed,
+ kv_entry->has_overflowed);
+ }
+
+ pthread_mutex_unlock(&umap->dead_app_kv_values.lock);
+
+ ret = map_new_content_section(map_content,
+ LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID_AGGREGATED,
+ true, 0, 0, values);
+
+ lttng_ht_destroy(values);
+ if (ret) {
+ ERR("Error appending deadapp kv");
+ goto end;
+ }
+
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+static
+int ust_app_map_list_values_per_pid_with_bitness_and_cpu(
+ const struct ltt_ust_session *usess,
+ struct ust_app *app,
+ struct ltt_ust_map *umap,
+ uint32_t app_bitness,
+ uint32_t cpu,
+ const char *key_filter,
+ struct lttng_ht *values)
+{
+ int ret = 0;
+
+ struct lttng_ht_iter map_iter;
+ struct lttng_ht_node_str *ua_map_node;
+ struct ust_app_map *ua_map;
+ struct ust_app_session *ua_sess;
+ struct ust_registry_session *ust_reg_sess;
+ struct ust_registry_map *ust_reg_map;
+
+ if (app->bits_per_long != app_bitness) {
+ ret = 0;
+ goto end;;
+ }
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (!ua_sess) {
+ /* Session not associated with this app. */
+ ret = 0;
+ goto end;;
+ }
+
+ ust_reg_sess = get_session_registry(ua_sess);
+ if (!ust_reg_sess) {
+ DBG("Application session is being torn down. Skip application.");
+ ret = 0;
+ goto end;;
+ }
+
+ /* Lookup map in the ust app session */
+ lttng_ht_lookup(ua_sess->maps, (void *)umap->name, &map_iter);
+ ua_map_node = lttng_ht_iter_get_node_str(&map_iter);
+
+ assert(ua_map_node != NULL);
+ ua_map = caa_container_of(ua_map_node, struct ust_app_map, node);
+
+ pthread_mutex_lock(&ust_reg_sess->lock);
+ ust_reg_map = ust_registry_map_find(ust_reg_sess, ua_map->key);
+ pthread_mutex_unlock(&ust_reg_sess->lock);
+ assert(ust_reg_map);
+
+ ret = snapshot_key_values(ua_map->map_handle,
+ ust_reg_map->key_string_to_bucket_index_ht,
+ cpu, key_filter, values);
+ if (ret) {
+ ERR("Error snapshoting the content of map");
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int ust_app_map_list_values_per_pid(const struct ltt_ust_session *usess,
+ struct ltt_ust_map *umap,
+ const struct lttng_map_query *query,
+ struct lttng_map_content *map_content)
+{
+ enum lttng_map_query_status map_query_status;
+ const char *key_filter;
+ struct lttng_ht *values;
+ bool sum_cpus = lttng_map_query_get_config_sum_by_cpu(query);
+ bool sum_pids = lttng_map_query_get_config_sum_by_pid(query);
+ enum lttng_map_query_config_cpu config_cpu;
+ int selected_cpu, i, ret = 0;
+ struct lttng_ht_iter app_iter;
+ struct ust_app *app;
+
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+
+ map_query_status = lttng_map_query_get_key_filter(query, &key_filter);
+ if (map_query_status == LTTNG_MAP_QUERY_STATUS_NONE) {
+ key_filter = NULL;
+ } else if (map_query_status != LTTNG_MAP_QUERY_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
+ config_cpu = lttng_map_query_get_config_cpu(query);
+ if (config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
+ unsigned int count;
+ map_query_status = lttng_map_query_get_cpu_count(query, &count);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+ assert(count == 1);
+
+ map_query_status = lttng_map_query_get_cpu_at_index(query, 0,
+ &selected_cpu);
+ assert(map_query_status == LTTNG_MAP_QUERY_STATUS_OK);
+ }
+
+ /* Sum all cpus and pids on the same table. */
+ if (sum_cpus && sum_pids) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ }
+
+ if (!sum_cpus && sum_pids) {
+ /* Iterate over all currently registered apps. */
+ for (i = 0; i < umap->nr_cpu; i++) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ cds_lfht_for_each_entry(ust_app_ht->ht, &app_iter.iter, app, pid_n.node) {
+ ret = ust_app_map_list_values_per_pid_with_bitness_and_cpu(
+ usess, app, umap, 32, i, key_filter, values);
+ if (ret) {
+ abort();
+ }
+ ret = ust_app_map_list_values_per_pid_with_bitness_and_cpu(
+ usess, app, umap, 64, i, key_filter, values);
+ if (ret) {
+ abort();
+ }
+ }
+ ret = map_new_content_section(map_content,
+ LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID,
+ sum_cpus, app->pid, i, values);
+ if (ret) {
+ abort();
+ }
+
+ lttng_ht_destroy(values);
+ }
+ } else {
+ /* Iterate over all currently registered apps. */
+ cds_lfht_for_each_entry(ust_app_ht->ht, &app_iter.iter, app, pid_n.node) {
+
+ if (sum_cpus && !sum_pids) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ }
+
+ for (i = 0; i < umap->nr_cpu; i++) {
+
+ if (config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) {
+ if (selected_cpu != i) {
+ continue;
+ }
+ }
+
+ if (!sum_cpus && !sum_pids) {
+ values = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
+ }
+
+ ret = ust_app_map_list_values_per_pid_with_bitness_and_cpu(
+ usess, app, umap, 32, i, key_filter, values);
+ if (ret) {
+ abort();
+ }
+ ret = ust_app_map_list_values_per_pid_with_bitness_and_cpu(
+ usess, app, umap, 64, i, key_filter, values);
+ if (ret) {
+ abort();
+ }
+
+ if (!sum_cpus && !sum_pids) {
+ ret = map_new_content_section(map_content,
+ LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID,
+ sum_cpus, app->pid, i, values);
+ if (ret) {
+ abort();
+ }