+ event_notifier = zmalloc(sizeof(struct lttng_event_notifier));
+ if (!event_notifier) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ event_notifier->group = event_notifier_group;
+ event_notifier->user_token = token;
+ event_notifier->error_counter_index = error_counter_index;
+
+ /* Event notifier will be enabled by enabler sync. */
+ event_notifier->enabled = 0;
+ event_notifier->registered = 0;
+
+ CDS_INIT_LIST_HEAD(&event_notifier->filter_bytecode_runtime_head);
+ CDS_INIT_LIST_HEAD(&event_notifier->capture_bytecode_runtime_head);
+ CDS_INIT_LIST_HEAD(&event_notifier->enablers_ref_head);
+ event_notifier->desc = desc;
+ event_notifier->notification_send = lttng_event_notifier_notification_send;
+
+ cds_list_add(&event_notifier->node,
+ &event_notifier_group->event_notifiers_head);
+ cds_hlist_add_head(&event_notifier->hlist, head);
+
+ return 0;
+
+error:
+ return ret;
+}
+
+static
+void _lttng_event_notifier_destroy(struct lttng_event_notifier *event_notifier)
+{
+ struct lttng_enabler_ref *enabler_ref, *tmp_enabler_ref;
+
+ /* Remove from event_notifier list. */
+ cds_list_del(&event_notifier->node);
+ /* Remove from event_notifier hash table. */
+ cds_hlist_del(&event_notifier->hlist);
+
+ lttng_free_event_notifier_filter_runtime(event_notifier);
+
+ /* Free event_notifier enabler refs */
+ cds_list_for_each_entry_safe(enabler_ref, tmp_enabler_ref,
+ &event_notifier->enablers_ref_head, node)
+ free(enabler_ref);
+ free(event_notifier);
+}
+
+static
+int lttng_desc_match_star_glob_enabler(const struct lttng_event_desc *desc,
+ struct lttng_enabler *enabler)
+{
+ int loglevel = 0;
+ unsigned int has_loglevel = 0;
+
+ assert(enabler->format_type == LTTNG_ENABLER_FORMAT_STAR_GLOB);
+ if (!strutils_star_glob_match(enabler->event_param.name, SIZE_MAX,
+ desc->name, SIZE_MAX))
+ return 0;
+ if (desc->loglevel) {
+ loglevel = *(*desc->loglevel);
+ has_loglevel = 1;
+ }
+ if (!lttng_loglevel_match(loglevel,
+ has_loglevel,
+ enabler->event_param.loglevel_type,
+ enabler->event_param.loglevel))
+ return 0;
+ return 1;
+}
+
+static
+int lttng_desc_match_event_enabler(const struct lttng_event_desc *desc,
+ struct lttng_enabler *enabler)
+{
+ int loglevel = 0;
+ unsigned int has_loglevel = 0;
+
+ assert(enabler->format_type == LTTNG_ENABLER_FORMAT_EVENT);
+ if (strcmp(desc->name, enabler->event_param.name))
+ return 0;
+ if (desc->loglevel) {
+ loglevel = *(*desc->loglevel);
+ has_loglevel = 1;
+ }
+ if (!lttng_loglevel_match(loglevel,
+ has_loglevel,
+ enabler->event_param.loglevel_type,
+ enabler->event_param.loglevel))
+ return 0;
+ return 1;
+}
+
+static
+int lttng_desc_match_enabler(const struct lttng_event_desc *desc,
+ struct lttng_enabler *enabler)
+{
+ switch (enabler->format_type) {
+ case LTTNG_ENABLER_FORMAT_STAR_GLOB:
+ {
+ struct lttng_ust_excluder_node *excluder;
+
+ if (!lttng_desc_match_star_glob_enabler(desc, enabler)) {
+ return 0;
+ }
+
+ /*
+ * If the matching event matches with an excluder,
+ * return 'does not match'
+ */
+ cds_list_for_each_entry(excluder, &enabler->excluder_head, node) {
+ int count;
+
+ for (count = 0; count < excluder->excluder.count; count++) {
+ int len;
+ char *excluder_name;
+
+ excluder_name = (char *) (excluder->excluder.names)
+ + count * LTTNG_UST_SYM_NAME_LEN;
+ len = strnlen(excluder_name, LTTNG_UST_SYM_NAME_LEN);
+ if (len > 0 && strutils_star_glob_match(excluder_name, len, desc->name, SIZE_MAX))
+ return 0;
+ }
+ }
+ return 1;
+ }
+ case LTTNG_ENABLER_FORMAT_EVENT:
+ return lttng_desc_match_event_enabler(desc, enabler);
+ default:
+ return -EINVAL;
+ }