+ struct lttng_kernel_event_recorder_private *event_recorder_private;
+ struct lttng_kernel_event_recorder *event_recorder;
+
+ desc = probe_desc->event_desc[i];
+ if (!lttng_desc_match_enabler(desc,
+ lttng_event_recorder_enabler_as_enabler(event_enabler)))
+ continue;
+
+ /*
+ * Check if already created.
+ */
+ head = utils_borrow_hash_table_bucket(
+ session->priv->events_ht.table, LTTNG_EVENT_HT_SIZE,
+ desc->event_name);
+ lttng_hlist_for_each_entry(event_recorder_private, head, hlist) {
+ if (event_recorder_private->parent.desc == desc
+ && event_recorder_private->pub->chan == event_enabler->chan)
+ found = 1;
+ }
+ if (found)
+ continue;
+
+ /*
+ * We need to create an event for this
+ * event probe.
+ */
+ event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
+ if (!event_recorder) {
+ printk(KERN_INFO "LTTng: Unable to create event %s\n",
+ probe_desc->event_desc[i]->event_name);
+ }
+ }
+ }
+}
+
+static
+void lttng_create_tracepoint_event_notifier_if_missing(struct lttng_event_notifier_enabler *event_notifier_enabler)
+{
+ struct lttng_event_notifier_group *event_notifier_group = event_notifier_enabler->group;
+ struct lttng_kernel_probe_desc *probe_desc;
+ const struct lttng_kernel_event_desc *desc;
+ int i;
+ struct list_head *probe_list;
+
+ probe_list = lttng_get_probe_list_head();
+ /*
+ * For each probe event, if we find that a probe event matches
+ * our enabler, create an associated lttng_event_notifier if not
+ * already present.
+ */
+ list_for_each_entry(probe_desc, probe_list, head) {
+ for (i = 0; i < probe_desc->nr_events; i++) {
+ int found = 0;
+ struct hlist_head *head;
+ struct lttng_kernel_event_notifier_private *event_notifier_priv;
+ struct lttng_kernel_event_notifier *event_notifier;
+
+ desc = probe_desc->event_desc[i];
+ if (!lttng_desc_match_enabler(desc,
+ lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
+ continue;
+
+ /*
+ * Check if already created.
+ */
+ head = utils_borrow_hash_table_bucket(
+ event_notifier_group->event_notifiers_ht.table,
+ LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
+ lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
+ if (event_notifier_priv->parent.desc == desc
+ && event_notifier_priv->parent.user_token == event_notifier_enabler->parent.user_token)
+ found = 1;
+ }
+ if (found)
+ continue;
+
+ /*
+ * We need to create a event_notifier for this event probe.
+ */
+ event_notifier = _lttng_event_notifier_create(desc,
+ event_notifier_enabler->parent.user_token,
+ event_notifier_enabler->error_counter_index,
+ event_notifier_group, NULL,
+ LTTNG_KERNEL_ABI_TRACEPOINT);
+ if (IS_ERR(event_notifier)) {
+ printk(KERN_INFO "Unable to create event_notifier %s\n",
+ probe_desc->event_desc[i]->event_name);
+ }
+ }
+ }
+}
+
+static
+void lttng_create_syscall_event_if_missing(struct lttng_event_recorder_enabler *event_enabler)
+{
+ int ret;
+
+ ret = lttng_syscalls_register_event_recorder(event_enabler);
+ WARN_ON_ONCE(ret);
+}
+
+static
+void lttng_create_syscall_event_notifier_if_missing(struct lttng_event_notifier_enabler *event_notifier_enabler)
+{
+ int ret;
+
+ ret = lttng_syscalls_register_event_notifier(event_notifier_enabler);
+ WARN_ON_ONCE(ret);
+ ret = lttng_syscalls_create_matching_event_notifiers(event_notifier_enabler);
+ WARN_ON_ONCE(ret);
+}
+
+/*
+ * Create struct lttng_kernel_event_recorder if it is missing and present in the list of
+ * tracepoint probes.
+ * Should be called with sessions mutex held.
+ */
+static
+void lttng_create_event_if_missing(struct lttng_event_recorder_enabler *event_enabler)
+{
+ switch (event_enabler->parent.event_param.instrumentation) {
+ case LTTNG_KERNEL_ABI_TRACEPOINT:
+ lttng_create_tracepoint_event_if_missing(event_enabler);
+ break;
+
+ case LTTNG_KERNEL_ABI_SYSCALL:
+ lttng_create_syscall_event_if_missing(event_enabler);
+ break;
+
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+
+/*
+ * Create events associated with an event_enabler (if not already present),
+ * and add backward reference from the event to the enabler.
+ * Should be called with sessions mutex held.
+ */
+static
+int lttng_event_enabler_ref_events(struct lttng_event_recorder_enabler *event_enabler)
+{
+ struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
+ struct lttng_kernel_session *session = event_enabler->chan->parent.session;
+ struct lttng_event_enabler_common *base_enabler = lttng_event_recorder_enabler_as_enabler(event_enabler);
+ struct lttng_kernel_event_recorder_private *event_recorder_priv;
+
+ if (base_enabler->event_param.instrumentation == LTTNG_KERNEL_ABI_SYSCALL &&
+ base_enabler->event_param.u.syscall.abi == LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL &&
+ base_enabler->event_param.u.syscall.match == LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME &&
+ !strcmp(base_enabler->event_param.name, "*")) {
+ int enabled = base_enabler->enabled;
+ enum lttng_kernel_abi_syscall_entryexit entryexit = base_enabler->event_param.u.syscall.entryexit;
+
+ if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
+ WRITE_ONCE(chan->priv->parent.syscall_table.syscall_all_entry, enabled);
+
+ if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
+ WRITE_ONCE(chan->priv->parent.syscall_table.syscall_all_exit, enabled);
+ }