+ * Should be called with sessions lock held.
+ */
+int lttng_syscalls_register_event_notifier(struct lttng_event_notifier_enabler *event_notifier_enabler, void *filter)
+{
+ struct lttng_event_notifier_group *group = event_notifier_enabler->group;
+ unsigned int i;
+ int ret = 0;
+
+ wrapper_vmalloc_sync_mappings();
+
+ if (!group->event_notifier_syscall_dispatch) {
+ group->event_notifier_syscall_dispatch = kzalloc(sizeof(struct list_head)
+ * ARRAY_SIZE(sc_table), GFP_KERNEL);
+ if (!group->event_notifier_syscall_dispatch)
+ return -ENOMEM;
+
+ /* Initialize all list_head */
+ for (i = 0; i < ARRAY_SIZE(sc_table); i++)
+ INIT_LIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
+ }
+
+#ifdef CONFIG_COMPAT
+ if (!group->event_notifier_compat_syscall_dispatch) {
+ group->event_notifier_compat_syscall_dispatch = kzalloc(sizeof(struct list_head)
+ * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
+ if (!group->event_notifier_syscall_dispatch)
+ return -ENOMEM;
+
+ /* Initialize all list_head */
+ for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++)
+ INIT_LIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
+ }
+#endif
+
+ if (!group->sys_enter_registered) {
+ ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
+ (void *) syscall_entry_event_notifier_probe, group);
+ if (ret)
+ return ret;
+ group->sys_enter_registered = 1;
+ }
+
+ return ret;
+}
+
+static int create_matching_event_notifiers(struct lttng_event_notifier_enabler *event_notifier_enabler,
+ void *filter, const struct trace_syscall_entry *table,
+ size_t table_len, bool is_compat)
+{
+ struct lttng_event_notifier_group *group = event_notifier_enabler->group;
+ const struct lttng_event_desc *desc;
+ uint64_t user_token = event_notifier_enabler->base.user_token;
+ unsigned int i;
+ int ret = 0;
+
+ /* iterate over all syscall and create event_notifier that match */
+ for (i = 0; i < table_len; i++) {
+ struct lttng_event_notifier *event_notifier;
+ struct lttng_kernel_event_notifier event_notifier_param;
+ struct hlist_head *head;
+ int found = 0;
+
+ desc = table[i].desc;
+ if (!desc) {
+ /* Unknown syscall */
+ continue;
+ }
+
+ 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(group->event_notifiers_ht.table,
+ LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
+ lttng_hlist_for_each_entry(event_notifier, head, hlist) {
+ if (event_notifier->desc == desc
+ && event_notifier->user_token == event_notifier_enabler->base.user_token)
+ found = 1;
+ }
+ if (found)
+ continue;
+
+ memset(&event_notifier_param, 0, sizeof(event_notifier_param));
+ strncat(event_notifier_param.event.name, desc->name,
+ LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
+ event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
+ event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
+
+ event_notifier = _lttng_event_notifier_create(desc, user_token, group,
+ &event_notifier_param, filter,
+ event_notifier_param.event.instrumentation);
+ if (IS_ERR(event_notifier)) {
+ printk(KERN_INFO "Unable to create event_notifier %s\n",
+ desc->name);
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ event_notifier->u.syscall.syscall_id = i;
+ event_notifier->u.syscall.is_compat = is_compat;
+ }
+end:
+ return ret;
+
+}
+
+int lttng_syscals_create_matching_event_notifiers(struct lttng_event_notifier_enabler *event_notifier_enabler, void *filter)
+{
+ int ret;
+
+ ret = create_matching_event_notifiers(event_notifier_enabler, filter, sc_table,
+ ARRAY_SIZE(sc_table), false);
+ if (ret)
+ goto end;
+
+ ret = create_matching_event_notifiers(event_notifier_enabler, filter, compat_sc_table,
+ ARRAY_SIZE(compat_sc_table), true);
+end:
+ return ret;
+}
+
+/*
+ * Unregister the syscall event_notifier probes from the callsites.