+struct lttng_trigger *_lttng_trigger_create(
+ const struct lttng_event_desc *event_desc,
+ uint64_t id, struct lttng_trigger_group *trigger_group,
+ struct lttng_kernel_trigger *trigger_param, void *filter,
+ enum lttng_kernel_instrumentation itype)
+{
+ struct lttng_trigger *trigger;
+ const char *event_name;
+ struct hlist_head *head;
+ int ret;
+
+ switch (itype) {
+ case LTTNG_KERNEL_TRACEPOINT:
+ event_name = event_desc->name;
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ case LTTNG_KERNEL_UPROBE:
+ case LTTNG_KERNEL_SYSCALL:
+ event_name = trigger_param->name;
+ break;
+ case LTTNG_KERNEL_KRETPROBE:
+ case LTTNG_KERNEL_FUNCTION:
+ case LTTNG_KERNEL_NOOP:
+ default:
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ goto type_error;
+ }
+
+ head = utils_borrow_hash_table_bucket(trigger_group->triggers_ht.table,
+ LTTNG_TRIGGER_HT_SIZE, event_name);
+ lttng_hlist_for_each_entry(trigger, head, hlist) {
+ WARN_ON_ONCE(!trigger->desc);
+ if (!strncmp(trigger->desc->name, event_name,
+ LTTNG_KERNEL_SYM_NAME_LEN - 1)
+ && trigger_group == trigger->group
+ && id == trigger->id) {
+ ret = -EEXIST;
+ goto exist;
+ }
+ }
+
+ trigger = kmem_cache_zalloc(trigger_cache, GFP_KERNEL);
+ if (!trigger) {
+ ret = -ENOMEM;
+ goto cache_error;
+ }
+ trigger->group = trigger_group;
+ trigger->id = id;
+ trigger->filter = filter;
+ trigger->instrumentation = itype;
+ trigger->evtype = LTTNG_TYPE_EVENT;
+ trigger->send_notification = lttng_trigger_send_notification;
+ INIT_LIST_HEAD(&trigger->bytecode_runtime_head);
+ INIT_LIST_HEAD(&trigger->enablers_ref_head);
+
+ switch (itype) {
+ case LTTNG_KERNEL_TRACEPOINT:
+ /* Event will be enabled by enabler sync. */
+ trigger->enabled = 0;
+ trigger->registered = 0;
+ trigger->desc = lttng_event_desc_get(event_name);
+ if (!trigger->desc) {
+ ret = -ENOENT;
+ goto register_error;
+ }
+ /* Populate lttng_trigger structure before event registration. */
+ smp_wmb();
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ trigger->enabled = 0;
+ trigger->registered = 1;
+ /*
+ * Populate lttng_trigger structure before event
+ * registration.
+ */
+ smp_wmb();
+ ret = lttng_kprobes_register_trigger(
+ trigger_param->u.kprobe.symbol_name,
+ trigger_param->u.kprobe.offset,
+ trigger_param->u.kprobe.addr,
+ trigger);
+ if (ret) {
+ ret = -EINVAL;
+ goto register_error;
+ }
+ ret = try_module_get(trigger->desc->owner);
+ WARN_ON_ONCE(!ret);
+ break;
+ case LTTNG_KERNEL_NOOP:
+ case LTTNG_KERNEL_SYSCALL:
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ trigger->enabled = 0;
+ trigger->registered = 0;
+ trigger->desc = event_desc;
+ if (!trigger->desc) {
+ ret = -EINVAL;
+ goto register_error;
+ }
+ break;
+ case LTTNG_KERNEL_UPROBE:
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ trigger->enabled = 0;
+ trigger->registered = 1;
+
+ /*
+ * Populate lttng_trigger structure before trigger
+ * registration.
+ */
+ smp_wmb();
+
+ ret = lttng_uprobes_register_trigger(trigger_param->name,
+ trigger_param->u.uprobe.fd,
+ trigger);
+ if (ret)
+ goto register_error;
+ ret = try_module_get(trigger->desc->owner);
+ WARN_ON_ONCE(!ret);
+ break;
+ case LTTNG_KERNEL_KRETPROBE:
+ case LTTNG_KERNEL_FUNCTION:
+ default:
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ goto register_error;
+ }
+
+ list_add(&trigger->list, &trigger_group->triggers_head);
+ hlist_add_head(&trigger->hlist, head);
+ return trigger;
+
+register_error:
+ kmem_cache_free(trigger_cache, trigger);
+cache_error:
+exist:
+type_error:
+ return ERR_PTR(ret);
+}
+
+struct lttng_event *lttng_event_create(struct lttng_channel *chan,
+ struct lttng_kernel_event *event_param,
+ void *filter,
+ const struct lttng_event_desc *event_desc,
+ enum lttng_kernel_instrumentation itype)
+{
+ struct lttng_event *event;
+
+ mutex_lock(&sessions_mutex);
+ event = _lttng_event_create(chan, event_param, filter, event_desc,
+ itype);
+ mutex_unlock(&sessions_mutex);
+ return event;
+}
+
+struct lttng_trigger *lttng_trigger_create(
+ const struct lttng_event_desc *event_desc,
+ uint64_t id, struct lttng_trigger_group *trigger_group,
+ struct lttng_kernel_trigger *trigger_param, void *filter,
+ enum lttng_kernel_instrumentation itype)
+{
+ struct lttng_trigger *trigger;
+
+ mutex_lock(&sessions_mutex);
+ trigger = _lttng_trigger_create(event_desc, id, trigger_group,
+ trigger_param, filter, itype);
+ mutex_unlock(&sessions_mutex);
+ return trigger;
+}
+
+/* Only used for tracepoints for now. */
+static