+/*
+ * Enable UST tracepoint event for a map from a UST session.
+ */
+enum lttng_error_code map_event_ust_enable_tracepoint(
+ struct ltt_ust_session *usess,
+ struct ltt_ust_map *umap,
+ uint64_t tracer_token,
+ char *ev_name,
+ struct lttng_map_key *key,
+ enum lttng_event_type ev_type,
+ enum lttng_loglevel_type ev_loglevel_type,
+ int ev_loglevel_value,
+ char *_filter_expression,
+ struct lttng_bytecode *_filter,
+ struct lttng_event_exclusion *exclusion,
+ bool internal_event)
+{
+ enum lttng_error_code ret_code = LTTNG_OK;
+ int ret, to_create = 0;
+ struct ltt_ust_event *uevent;
+ struct lttng_bytecode *filter = NULL;
+ char *filter_expression = NULL;
+
+
+ assert(usess);
+ assert(umap);
+
+ /*
+ * FIXME: FRDESO: this function was copied from ust-app.c
+ */
+ if (_filter_expression) {
+ filter_expression = strdup(_filter_expression);
+ }
+
+ if (_filter) {
+ filter = zmalloc(sizeof(*filter) + _filter->len);
+ if (!filter) {
+ PERROR("Failed to allocate lttng_ust_filter_bytecode: bytecode len = %" PRIu32 " bytes", _filter->len);
+ goto error;
+ }
+
+ assert(sizeof(struct lttng_bytecode) ==
+ sizeof(struct lttng_ust_filter_bytecode));
+ memcpy(filter, _filter, sizeof(*filter) + _filter->len);
+ }
+
+ rcu_read_lock();
+
+ uevent = trace_ust_find_event(umap->events, tracer_token, ev_name, filter,
+ (enum lttng_ust_loglevel_type) ev_loglevel_type,
+ ev_loglevel_value, exclusion, key);
+ if (!uevent) {
+ ret_code = trace_ust_create_event(tracer_token, ev_name, key, ev_type,
+ ev_loglevel_type, ev_loglevel_value,
+ filter_expression, filter, exclusion,
+ internal_event, &uevent);
+ /* We have passed ownership */
+ filter_expression = NULL;
+ filter = NULL;
+ exclusion = NULL;
+ if (ret_code != LTTNG_OK) {
+ goto error;
+ }
+
+ /* Valid to set it after the goto error since uevent is still NULL */
+ to_create = 1;
+ }
+
+ if (uevent->enabled) {
+ /* It's already enabled so everything is OK */
+ assert(!to_create);
+ ret_code = LTTNG_ERR_UST_EVENT_ENABLED;
+ goto end;
+ }
+
+ uevent->enabled = 1;
+ if (to_create) {
+ /* Add ltt ust event to map */
+ add_unique_ust_event(umap->events, uevent, key);
+ }
+
+ if (!usess->active) {
+ goto end;
+ }
+
+ if (to_create) {
+ /* Create event on all UST registered apps for session */
+ ret = ust_app_create_map_event_glb(usess, umap, uevent);
+ } else {
+ /* Enable event on all UST registered apps for session */
+ ret = ust_app_enable_map_event_glb(usess, umap, uevent);
+ }
+
+ if (ret < 0) {
+ if (ret == -LTTNG_UST_ERR_EXIST) {
+ ret_code = LTTNG_ERR_UST_EVENT_EXIST;
+ goto end;
+ } else {
+ ret_code = LTTNG_ERR_UST_ENABLE_FAIL;
+ goto error;
+ }
+ }
+
+ DBG("Event UST %s %s in map %s", uevent->attr.name,
+ to_create ? "created" : "enabled", umap->name);
+
+ ret_code = LTTNG_OK;
+
+end:
+ rcu_read_unlock();
+ free(filter_expression);
+ free(filter);
+ free(exclusion);
+ return ret_code;
+
+error:
+ /*
+ * Only destroy event on creation time (not enabling time) because if the
+ * event is found in the map (to_create == 0), it means that at some
+ * point the enable_event worked and it's thus valid to keep it alive.
+ * Destroying it also implies that we also destroy it's shadow copy to sync
+ * everyone up.
+ */
+ if (to_create) {
+ /* In this code path, the uevent was not added to the hash table */
+ trace_ust_destroy_event(uevent);
+ }
+ rcu_read_unlock();
+ free(filter_expression);
+ free(filter);
+ free(exclusion);
+ return ret_code;
+}
+