diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..7839355
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+.gitattributes export-ignore
+.gitignore export-ignore
+.gitreview export-ignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..61a6986
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,153 @@
+#
+# NOTE! Don't add files that are generated in specific
+# subdirectories here. Add them in the ".gitignore" file
+# in that subdirectory instead.
+#
+# NOTE! Please use 'git ls-files -i --exclude-standard'
+# command after changing this file, to see if there are
+# any tracked files which get ignored after the change.
+#
+# Normal rules (sorted alphabetically)
+#
+.*
+*.a
+*.asn1.[ch]
+*.bin
+*.bz2
+*.c.[012]*.*
+*.dt.yaml
+*.dtb
+*.dtb.S
+*.dwo
+*.elf
+*.gcno
+*.gz
+*.i
+*.ko
+*.lex.c
+*.ll
+*.lst
+*.lz4
+*.lzma
+*.lzo
+*.mod
+*.mod.c
+*.o
+*.o.*
+*.patch
+*.s
+*.so
+*.so.dbg
+*.su
+*.symtypes
+*.tab.[ch]
+*.tar
+*.xz
+Module.symvers
+modules.builtin
+modules.order
+
+#
+# Top-level generic files
+#
+/tags
+/TAGS
+/linux
+/vmlinux
+/vmlinux.32
+/vmlinux-gdb.py
+/vmlinuz
+/System.map
+/Module.markers
+/modules.builtin.modinfo
+/modules.nsdeps
+
+#
+# RPM spec file (make rpm-pkg)
+#
+/*.spec
+
+#
+# Debian directory (make deb-pkg)
+#
+/debian/
+
+#
+# Snap directory (make snap-pkg)
+#
+/snap/
+
+#
+# tar directory (make tar*-pkg)
+#
+/tar-install/
+
+#
+# We don't want to ignore the following even if they are dot-files
+#
+!.clang-format
+!.cocciconfig
+!.get_maintainer.ignore
+!.gitattributes
+!.gitignore
+!.mailmap
+
+#
+# Generated include files
+#
+/include/config/
+/include/generated/
+/include/ksym/
+/arch/*/include/generated/
+
+# stgit generated dirs
+patches-*
+
+# quilt's files
+patches
+series
+
+# cscope files
+cscope.*
+ncscope.*
+
+# gnu global files
+GPATH
+GRTAGS
+GSYMS
+GTAGS
+
+# id-utils files
+ID
+
+*.orig
+*~
+\#*#
+
+#
+# Leavings from module signing
+#
+extra_certificates
+signing_key.pem
+signing_key.priv
+signing_key.x509
+x509.genkey
+
+# Kconfig presets
+/all.config
+/alldef.config
+/allmod.config
+/allno.config
+/allrandom.config
+/allyes.config
+
+# Kdevelop4
+*.kdev4
+
+# Clang's compilation database file
+/compile_commands.json
+
+# lttng-modules specific
+/extra_version
+/include/generated
+!/.gitreview
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..0d2dcde
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,7 @@
+[gerrit]
+host=review.lttng.org
+port=29418
+project=lttng-modules.git
+defaultbranch=master
+defaultremote=review
+defaultrebase=0
diff --git a/ChangeLog b/ChangeLog
index cfd4541..cd9c692 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,110 +1,3 @@
-2022-03-25 (National Waffle Day) LTTng modules 2.13.3
-	* Document expected ISO8601 time formats in ABI header
-	* Fix: lttng ABI: lttng_counter_ioctl() tainted scalar
-	* Fix: sample discarded events count before reserve
-	* Cleanup: comment alignment in ring buffer config.h
-
-2022-03-07 (National Cereal Day) LTTng modules 2.13.2
-	* Fix: incorrect in/out direction for syscall exit
-	* fix: net: socket: rename SKB_DROP_REASON_SOCKET_FILTER (v5.17)
-	* fix: net: skb: introduce kfree_skb_reason() (v5.17)
-	* fix: random: rather than entropy_store abstraction, use global (v5.17)
-	* fix: btrfs: pass fs_info to trace_btrfs_transaction_commit (v5.17)
-	* fix: mm: compaction: fix the migration stats in trace_mm_compaction_migratepages() (v5.17)
-	* fix: block: remove the ->rq_disk field in struct request (v5.17)
-	* fix: block: remove GENHD_FL_SUPPRESS_PARTITION_INFO (v5.17)
-	* Copyright ownership transfer
-
-2022-01-05 (National Bird Day) LTTng modules 2.13.1
-	* fix: mm: move kvmalloc-related functions to slab.h (v5.16)
-	* fix: block: don't call blk_status_to_errno in blk_update_request (v5.16)
-	* fix: KVM: MMU: change tracepoints arguments to kvm_page_fault (v5.16)
-	* fix: KVM: x86: Get exit_reason as part of kvm_x86_ops.get_exit_info (v5.16)
-	* fix: isystem: delete global -isystem compile option (v5.16)
-	* fix: block: move block-related definitions out of fs.h (v5.16)
-	* Fix: syscall tracing: missing trigger actions
-	* Warn on event registration/unregistration failure
-	* fix: implicit-int error in EXPORT_SYMBOL_GPL
-	* fix: Revert "Makefile: Enable -Wimplicit-fallthrough for Clang" (v5.15)
-	* fix: cpu/hotplug: Remove deprecated CPU-hotplug functions. (v5.15)
-
-2021-08-02 (Ice Cream Sandwich Day) LTTng modules 2.13.0
-	* No change
-
-2021-07-16 (World Snake Day) LTTng modules 2.13.0-rc3
-	* fix: sched: Change task_struct::state (v5.14)
-	* fix: btrfs: pass btrfs_inode to btrfs_writepage_endio_finish_ordered() (v5.14)
-	* fix: adjust ranges for RHEL 8.4
-
-2021-05-14 (National Dance Like a Chicken Day) LTTng modules 2.13.0-rc2
-	* fix: adjust ranges for RHEL 8.2 and 8.3
-	* Disable x86 error code bitwise enum in default build
-	* Disable mmap bitwise enum in default build
-	* Disable block rwbs bitwise enum in default build
-	* Disable sched_switch bitwise enum in default build
-	* Disable open[at] bitwise enum in default build
-	* Disable fcntl bitwise enum in default build
-	* Disable clone bitwise enum in default build
-	* Add experimental bitwise enum config option
-	* Add defaults to Kconfig options
-	* Cleanup: remove unused EXTCFLAGS from Makefile
-	* Sync `show_inode_state()` macro with upstream stable kernels
-	* Update .gitreview for stable-2.13
-	* Sync `show_inode_state()` macro with Ubuntu 4.15 kernel
-	* fix: block: remove disk_part_iter (v5.12)
-	* Cleanup: lib ring buffer: rename pagecpy local variable
-	* Cleanup: clarify strcpy/strcpy_from_user local variables
-	* Implement ring buffer Pascal string copy
-	* Move alignment into event write callback
-	* Cleanup: disable page fault after access_ok
-	* Fix: increment buffer offset when failing to copy from user-space
-	* Fix: add missing #include for 3.8 kernel
-	* Fix: builtin script referring to old directories
-	* events.h API const-ness
-	* Rename struct lib_ring_buffer* to struct lttng_kernel_ring_buffer*
-	* Rename struct channel to struct lttng_kernel_ring_buffer_channel
-	* Refactoring: struct lttng_channel
-	* Fix: missing #include for 3.8 kernel
-	* Introduce struct lttng_kernel_tracepoint_class, enum probe_desc field
-	* Set probe descriptor field in event descriptor
-	* Split syscall tracepoint generation in their own files
-	* Include `linux/in{,6}.h` closer to where it's used
-	* Group all syscall enums in one compile unit
-	* Include `linux/mman.h` for mmap flag enum
-	* Add `struct trace_syscall_table`
-	* Define `static_assert()` when not defined by kernel
-	* Move event hash tables to private header
-	* Move forward declarations to private header
-	* Move lttng_syscall_filter forward declaration to private header
-	* Split ID tracker into public/private structures
-	* Move id tracker hash node to private header
-	* Split struct lttng_session into public/private structures
-	* Move struct lttng_metadata_stream to private header
-	* Move event notifier and counter structures to private header
-	* Rename struct lib_ring_buffer_ctx to struct lttng_kernel_ring_buffer_ctx
-	* Refactoring: struct lttng_kernel_channel_buffer_ops
-	* Rename lttng_probe_{,un}register to lttng_kernel_probe_{,un}register
-	* Move metadata cache structure to internal header
-	* Move internal APIs to internal header
-	* Move kprobes, uprobes, kretprobes, syscall structures to internal header
-	* Move kprobe, kretprobe, uprobe APIs to internal header
-	* Remove unused TRACEPOINT_HAS_DATA_ARG
-	* Move enabler APIs to internal header
-	* Move bytecode structures to internal header
-	* Remove include of internal header from tracepoint-event-impl.h
-	* Rename struct lttng_probe_ctx to struct lttng_kernel_probe_ctx
-	* Rename struct lttng_bytecode_runtime to struct lttng_kernel_bytecode_runtime
-	* Rename struct lttng_bytecode_node to struct lttng_kernel_bytecode_node
-	* Move context structures and API to internal header
-	* Move enabler structures to internal header
-	* Makefile: add .o wildcard target
-	* Fix: Makefile: generation of specific .i file not working
-	* Fix: refactor preemptible context
-	* Refactoring: context callbacks
-	* Remove event id parameter from event_reserve callback
-	* Refactoring: ring buffer context
-	* sequence and variant types: use previous field for length/tag if NULL
-
 2021-04-23 (National Take a Chance (on me ?) Day) LTTng modules 2.13.0-rc1
 	* Set the 2.13 release codename and description
 	* Fix: LTTng-modules ABI ioctl wrong direction
diff --git a/debian/changelog b/debian/changelog
index 7718fed..fa8bb24 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+lttng-modules (2.13.3+git20220314.1.3bd6d7b-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Mon, 28 Mar 2022 20:09:06 -0000
+
 lttng-modules (2.13.3-1) unstable; urgency=medium
 
   * [74b0b84] New upstream version 2.13.3
diff --git a/debian/patches/fix-linux-rt-4.9-sched.patch b/debian/patches/fix-linux-rt-4.9-sched.patch
index b85b69c..566b9d6 100644
--- a/debian/patches/fix-linux-rt-4.9-sched.patch
+++ b/debian/patches/fix-linux-rt-4.9-sched.patch
@@ -1,8 +1,10 @@
 Fix build of sched instrumentation on linux-rt >= 4.9.27-rt8
 
---- a/include/instrumentation/events/sched.h
-+++ b/include/instrumentation/events/sched.h
-@@ -596,7 +596,8 @@
+Index: lttng-modules/include/instrumentation/events/sched.h
+===================================================================
+--- lttng-modules.orig/include/instrumentation/events/sched.h
++++ lttng-modules/include/instrumentation/events/sched.h
+@@ -596,7 +596,8 @@ LTTNG_TRACEPOINT_EVENT(sched_stat_runtim
  
  #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,12,0) || \
  	LTTNG_RT_KERNEL_RANGE(4,9,27,18, 4,10,0,0) || \
diff --git a/include/instrumentation/events/random.h b/include/instrumentation/events/random.h
index 8cc88ad..bdde1c0 100644
--- a/include/instrumentation/events/random.h
+++ b/include/instrumentation/events/random.h
@@ -8,6 +8,22 @@
 #include <lttng/tracepoint-event.h>
 #include <linux/writeback.h>
 
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_MAP(add_device_randomness,
+
+	random_add_device_randomness,
+
+	TP_PROTO(int bytes, unsigned long IP),
+
+	TP_ARGS(bytes, IP),
+
+	TP_FIELDS(
+		ctf_integer(int, bytes, bytes)
+		ctf_integer_hex(unsigned long, IP, IP)
+	)
+)
+#endif
+
 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,17,0))
 LTTNG_TRACEPOINT_EVENT_CLASS(random__mix_pool_bytes,
 	TP_PROTO(int bytes, unsigned long IP),
@@ -121,6 +137,131 @@ LTTNG_TRACEPOINT_EVENT_MAP(credit_entropy_bits,
 )
 #endif
 
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_MAP(push_to_pool,
+
+	random_push_to_pool,
+
+	TP_PROTO(const char *pool_name, int pool_bits, int input_bits),
+
+	TP_ARGS(pool_name, pool_bits, input_bits),
+
+	TP_FIELDS(
+		ctf_string(pool_name, pool_name)
+		ctf_integer(int, pool_bits, pool_bits)
+		ctf_integer(int, input_bits, input_bits)
+	)
+)
+#endif
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,17,0))
+LTTNG_TRACEPOINT_EVENT_MAP(debit_entropy,
+
+	random_debit_entropy,
+
+	TP_PROTO(int debit_bits),
+
+	TP_ARGS(debit_bits),
+
+	TP_FIELDS(
+		ctf_integer(int, debit_bits, debit_bits)
+	)
+)
+#elif (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_MAP(debit_entropy,
+
+	random_debit_entropy,
+
+	TP_PROTO(const char *pool_name, int debit_bits),
+
+	TP_ARGS(pool_name, debit_bits),
+
+	TP_FIELDS(
+		ctf_string(pool_name, pool_name)
+		ctf_integer(int, debit_bits, debit_bits)
+	)
+)
+#endif
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_MAP(add_input_randomness,
+
+	random_add_input_randomness,
+
+	TP_PROTO(int input_bits),
+
+	TP_ARGS(input_bits),
+
+	TP_FIELDS(
+		ctf_integer(int, input_bits, input_bits)
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT_MAP(add_disk_randomness,
+
+	random_add_disk_randomness,
+
+	TP_PROTO(dev_t dev, int input_bits),
+
+	TP_ARGS(dev, input_bits),
+
+	TP_FIELDS(
+		ctf_integer(dev_t, dev, dev)
+		ctf_integer(int, input_bits, input_bits)
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT_MAP(xfer_secondary_pool,
+
+	random_xfer_secondary_pool,
+
+	TP_PROTO(const char *pool_name, int xfer_bits, int request_bits,
+		int pool_entropy, int input_entropy),
+
+	TP_ARGS(pool_name, xfer_bits, request_bits, pool_entropy,
+		input_entropy),
+
+	TP_FIELDS(
+		ctf_string(pool_name, pool_name)
+		ctf_integer(int, xfer_bits, xfer_bits)
+		ctf_integer(int, request_bits, request_bits)
+		ctf_integer(int, pool_entropy, pool_entropy)
+		ctf_integer(int, input_entropy, input_entropy)
+	)
+)
+#endif
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_CLASS(random__get_random_bytes,
+
+	TP_PROTO(int nbytes, unsigned long IP),
+
+	TP_ARGS(nbytes, IP),
+
+	TP_FIELDS(
+		ctf_integer(int, nbytes, nbytes)
+		ctf_integer_hex(unsigned long, IP, IP)
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(random__get_random_bytes, get_random_bytes,
+
+	random_get_random_bytes,
+
+	TP_PROTO(int nbytes, unsigned long IP),
+
+	TP_ARGS(nbytes, IP)
+)
+
+LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(random__get_random_bytes, get_random_bytes_arch,
+
+	random_get_random_bytes_arch,
+
+	TP_PROTO(int nbytes, unsigned long IP),
+
+	TP_ARGS(nbytes, IP)
+)
+#else
 LTTNG_TRACEPOINT_EVENT_MAP(get_random_bytes,
 
 	random_get_random_bytes,
@@ -134,6 +275,7 @@ LTTNG_TRACEPOINT_EVENT_MAP(get_random_bytes,
 		ctf_integer_hex(unsigned long, IP, IP)
 	)
 )
+#endif
 
 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,17,0))
 LTTNG_TRACEPOINT_EVENT_CLASS(random__extract_entropy,
@@ -203,6 +345,53 @@ LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(random__extract_entropy, extract_entropy_use
 )
 #endif
 
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(3,13,0))
+LTTNG_TRACEPOINT_EVENT_MAP(random_read,
+
+	random_random_read,
+
+	TP_PROTO(int got_bits, int need_bits, int pool_left, int input_left),
+
+	TP_ARGS(got_bits, need_bits, pool_left, input_left),
+
+	TP_FIELDS(
+		ctf_integer(int, got_bits, got_bits)
+		ctf_integer(int, need_bits, need_bits)
+		ctf_integer(int, pool_left, pool_left)
+		ctf_integer(int, input_left, input_left)
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT_MAP(urandom_read,
+
+	random_urandom_read,
+
+	TP_PROTO(int got_bits, int pool_left, int input_left),
+
+	TP_ARGS(got_bits, pool_left, input_left),
+
+	TP_FIELDS(
+		ctf_integer(int, got_bits, got_bits)
+		ctf_integer(int, pool_left, pool_left)
+		ctf_integer(int, input_left, input_left)
+	)
+)
+#endif
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,9,0))
+LTTNG_TRACEPOINT_EVENT_MAP(prandom_u32,
+
+	random_prandom_u32,
+
+	TP_PROTO(unsigned int ret),
+
+	TP_ARGS(ret),
+
+	TP_FIELDS(
+		ctf_integer(unsigned int, ret, ret)
+	)
+)
+#endif
 
 
 #endif /* LTTNG_TRACE_RANDOM_H */
diff --git a/include/instrumentation/events/timer.h b/include/instrumentation/events/timer.h
index 91a2cd9..b4c6e94 100644
--- a/include/instrumentation/events/timer.h
+++ b/include/instrumentation/events/timer.h
@@ -17,6 +17,38 @@ struct timer_list;
 
 #endif /* _TRACE_TIMER_DEF_ */
 
+LTTNG_TRACEPOINT_ENUM(hrtimer_mode,
+	TP_ENUM_VALUES(
+		ctf_enum_value("HRTIMER_MODE_ABS", HRTIMER_MODE_ABS)
+		ctf_enum_value("HRTIMER_MODE_REL", HRTIMER_MODE_REL)
+		ctf_enum_value("HRTIMER_MODE_PINNED", HRTIMER_MODE_PINNED)
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,16,0))
+		ctf_enum_value("HRTIMER_MODE_SOFT", HRTIMER_MODE_SOFT)
+#endif
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,4,0))
+		ctf_enum_value("HRTIMER_MODE_HARD", HRTIMER_MODE_HARD)
+#endif
+
+		ctf_enum_value("HRTIMER_MODE_ABS_PINNED", HRTIMER_MODE_ABS_PINNED)
+		ctf_enum_value("HRTIMER_MODE_REL_PINNED", HRTIMER_MODE_REL_PINNED)
+
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,16,0))
+		ctf_enum_value("HRTIMER_MODE_ABS_SOFT", HRTIMER_MODE_ABS_SOFT)
+		ctf_enum_value("HRTIMER_MODE_REL_SOFT", HRTIMER_MODE_REL_SOFT)
+
+		ctf_enum_value("HRTIMER_MODE_ABS_PINNED_SOFT", HRTIMER_MODE_ABS_PINNED_SOFT)
+		ctf_enum_value("HRTIMER_MODE_REL_PINNED_SOFT", HRTIMER_MODE_REL_PINNED_SOFT)
+#endif
+#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,4,0))
+		ctf_enum_value("HRTIMER_MODE_ABS_HARD", HRTIMER_MODE_ABS_HARD)
+		ctf_enum_value("HRTIMER_MODE_REL_HARD", HRTIMER_MODE_REL_HARD)
+
+		ctf_enum_value("HRTIMER_MODE_ABS_PINNED_HARD", HRTIMER_MODE_ABS_PINNED_HARD)
+		ctf_enum_value("HRTIMER_MODE_REL_PINNED_HARD", HRTIMER_MODE_REL_PINNED_HARD)
+#endif
+	)
+)
+
 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0))
 #define lttng_ktime_get_tv64(kt)	(kt)
 #else /* #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(4,10,0)) */
@@ -177,7 +209,7 @@ LTTNG_TRACEPOINT_EVENT_MAP(hrtimer_init,
 	TP_FIELDS(
 		ctf_integer_hex(void *, hrtimer, hrtimer)
 		ctf_integer(clockid_t, clockid, clockid)
-		ctf_integer(enum hrtimer_mode, mode, mode)
+		ctf_enum(hrtimer_mode, unsigned int, mode, mode)
 	)
 )
 
@@ -202,7 +234,7 @@ LTTNG_TRACEPOINT_EVENT_MAP(hrtimer_start,
 			lttng_ktime_get_tv64(hrtimer_get_expires(hrtimer)))
 		ctf_integer(s64, softexpires,
 			lttng_ktime_get_tv64(hrtimer_get_softexpires(hrtimer)))
-		ctf_integer(enum hrtimer_mode, mode, mode)
+		ctf_enum(hrtimer_mode, unsigned int, mode, mode)
 	)
 )
 #else
diff --git a/include/instrumentation/syscalls/headers/syscalls_pointers_override.h b/include/instrumentation/syscalls/headers/syscalls_pointers_override.h
index ed8041d..0b7134b 100644
--- a/include/instrumentation/syscalls/headers/syscalls_pointers_override.h
+++ b/include/instrumentation/syscalls/headers/syscalls_pointers_override.h
@@ -505,7 +505,7 @@ static_assert(((ARRAY_SIZE(lttng_pollfd_flag_fields) - 1) + POLL_FLAGS_PADDING_S
 #endif /* LTTNG_TRACEPOINT_TYPE_EXTERN */
 
 LTTNG_TRACEPOINT_TYPE(PARAMS(const struct lttng_kernel_type_struct lttng_pollfd_flag_fields_struct),
-	PARAMS(lttng_kernel_static_type_struct_init( ARRAY_SIZE(lttng_pollfd_flag_fields), lttng_pollfd_flag_fields, 0)))
+	PARAMS(lttng_kernel_static_type_struct_init(ARRAY_SIZE(lttng_pollfd_flag_fields), lttng_pollfd_flag_fields, 0)))
 
 #ifndef LTTNG_TRACEPOINT_TYPE_EXTERN
 static const struct lttng_kernel_event_field *lttng_pollfd_fields[] = {
diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h
index ca2190c..ef1bed2 100644
--- a/include/lttng/events-internal.h
+++ b/include/lttng/events-internal.h
@@ -33,7 +33,7 @@ enum channel_type {
  */
 struct lttng_enabler_ref {
 	struct list_head node;			/* enabler ref list */
-	struct lttng_enabler *ref;		/* backward ref */
+	struct lttng_event_enabler_common *ref;		/* backward ref */
 };
 
 struct lttng_krp;				/* Kretprobe handling */
@@ -77,6 +77,10 @@ struct lttng_kernel_event_common_private {
 	int has_enablers_without_filter_bytecode;
 	/* list of struct lttng_kernel_bytecode_runtime, sorted by seqnum */
 	struct list_head filter_bytecode_runtime_head;
+
+	struct hlist_node hlist_node;			/* node in events hash table */
+	struct list_head node;				/* node in event list */
+
 	enum lttng_kernel_abi_instrumentation instrumentation;
 	/* Selected by instrumentation */
 	union {
@@ -99,8 +103,6 @@ struct lttng_kernel_event_recorder_private {
 	struct lttng_kernel_event_common_private parent;
 
 	struct lttng_kernel_event_recorder *pub;	/* Public event interface */
-	struct list_head node;				/* Event recorder list */
-	struct hlist_node hlist;			/* Hash table of event recorders */
 	struct lttng_kernel_ctx *ctx;
 	unsigned int id;
 	unsigned int metadata_dumped:1;
@@ -113,31 +115,42 @@ struct lttng_kernel_event_notifier_private {
 	struct lttng_event_notifier_group *group;	/* weak ref */
 	size_t num_captures;				/* Needed to allocate the msgpack array. */
 	uint64_t error_counter_index;
-	struct list_head node;				/* Event notifier list */
-	struct hlist_node hlist;			/* Hash table of event notifiers */
 	struct list_head capture_bytecode_runtime_head;
+};
+
+struct lttng_kernel_syscall_table {
+	unsigned int sys_enter_registered:1,
+		sys_exit_registered:1;
+
+	struct hlist_head *syscall_dispatch;		/* for syscall tracing */
+	struct hlist_head *compat_syscall_dispatch;
+	struct hlist_head *syscall_exit_dispatch;	/* for syscall exit tracing */
+	struct hlist_head *compat_syscall_exit_dispatch;
 
+	/*
+	 * Combining all unknown syscall events works as long as they
+	 * are only matched by "all" syscalls enablers, but will require
+	 * a design change when we allow matching by syscall number, for
+	 * instance by allocating sc_tables accomodating NR_syscalls
+	 * entries.
+	 */
+	struct hlist_head unknown_syscall_dispatch;	/* for unknown syscalls */
+	struct hlist_head compat_unknown_syscall_dispatch;
+	struct hlist_head unknown_syscall_exit_dispatch;
+	struct hlist_head compat_unknown_syscall_exit_dispatch;
+
+	struct lttng_syscall_filter *sc_filter;
+	int syscall_all_entry;
+	int syscall_all_exit;
 };
 
 struct lttng_kernel_channel_common_private {
 	struct lttng_kernel_channel_common *pub;
 
 	struct file *file;			/* File associated to channel */
-	unsigned int sys_enter_registered:1,
-		sys_exit_registered:1,
-		tstate:1;			/* Transient enable state */
+	unsigned int tstate:1;			/* Transient enable state */
 
-	struct hlist_head *sc_table;		/* for syscall tracing */
-	struct hlist_head *compat_sc_table;
-	struct hlist_head *sc_exit_table;	/* for syscall exit tracing */
-	struct hlist_head *compat_sc_exit_table;
-	struct hlist_head sc_unknown;		/* for unknown syscalls */
-	struct hlist_head sc_compat_unknown;
-	struct hlist_head sc_exit_unknown;
-	struct hlist_head compat_sc_exit_unknown;
-	struct lttng_syscall_filter *sc_filter;
-	int syscall_all_entry;
-	int syscall_all_exit;
+	struct lttng_kernel_syscall_table syscall_table;
 };
 
 struct lttng_kernel_channel_buffer_private {
@@ -178,10 +191,15 @@ enum lttng_kernel_bytecode_type {
 	LTTNG_KERNEL_BYTECODE_TYPE_CAPTURE,
 };
 
+enum lttng_kernel_event_enabler_type {
+	LTTNG_EVENT_ENABLER_TYPE_RECORDER,
+	LTTNG_EVENT_ENABLER_TYPE_NOTIFIER,
+};
+
 struct lttng_kernel_bytecode_node {
 	enum lttng_kernel_bytecode_type type;
 	struct list_head node;
-	struct lttng_enabler *enabler;
+	struct lttng_event_enabler_common *enabler;
 	struct {
 		uint32_t len;
 		uint32_t reloc_offset;
@@ -207,7 +225,8 @@ struct lttng_kernel_bytecode_runtime {
  * Enabler field, within whatever object is enabling an event. Target of
  * backward reference.
  */
-struct lttng_enabler {
+struct lttng_event_enabler_common {
+	enum lttng_kernel_event_enabler_type enabler_type;
 	enum lttng_enabler_format_type format_type;
 
 	/* head list of struct lttng_kernel_bytecode_node */
@@ -217,18 +236,19 @@ struct lttng_enabler {
 	unsigned int enabled:1;
 
 	uint64_t user_token;		/* User-provided token. */
+
+	struct list_head node;		/* list of enablers */
+	bool published;			/* published in list. */
 };
 
-struct lttng_event_enabler {
-	struct lttng_enabler base;
-	struct list_head node;	/* per-session list of enablers */
+struct lttng_event_recorder_enabler {
+	struct lttng_event_enabler_common parent;
 	struct lttng_kernel_channel_buffer *chan;
 };
 
 struct lttng_event_notifier_enabler {
-	struct lttng_enabler base;
+	struct lttng_event_enabler_common parent;
 	uint64_t error_counter_index;
-	struct list_head node;	/* List of event_notifier enablers */
 	struct lttng_event_notifier_group *group;
 
 	/* head list of struct lttng_kernel_bytecode_node */
@@ -389,11 +409,11 @@ struct lttng_counter {
 	struct lttng_counter_ops *ops;
 };
 
-#define LTTNG_EVENT_NOTIFIER_HT_BITS		12
-#define LTTNG_EVENT_NOTIFIER_HT_SIZE		(1U << LTTNG_EVENT_NOTIFIER_HT_BITS)
+#define LTTNG_EVENT_HT_BITS		12
+#define LTTNG_EVENT_HT_SIZE		(1U << LTTNG_EVENT_HT_BITS)
 
-struct lttng_event_notifier_ht {
-	struct hlist_head table[LTTNG_EVENT_NOTIFIER_HT_SIZE];
+struct lttng_event_ht {
+	struct hlist_head table[LTTNG_EVENT_HT_SIZE];
 };
 
 struct lttng_event_notifier_group {
@@ -402,32 +422,15 @@ struct lttng_event_notifier_group {
 	struct list_head node;		/* event notifier group list */
 	struct list_head enablers_head; /* List of enablers */
 	struct list_head event_notifiers_head; /* List of event notifier */
-	struct lttng_event_notifier_ht event_notifiers_ht; /* Hash table of event notifiers */
+	struct lttng_event_ht events_ht; /* Hash table of event notifiers */
 	struct lttng_kernel_channel_buffer_ops *ops;
 	struct lttng_transport *transport;
 	struct lttng_kernel_ring_buffer_channel *chan;		/* Ring buffer channel for event notifier group. */
 	struct lttng_kernel_ring_buffer *buf;	/* Ring buffer for event notifier group. */
 	wait_queue_head_t read_wait;
 	struct irq_work wakeup_pending;	/* Pending wakeup irq work. */
-	struct lttng_kernel_event_notifier *sc_unknown;	/* for unknown syscalls */
-	struct lttng_kernel_event_notifier *sc_compat_unknown;
-
-	struct lttng_syscall_filter *sc_filter;
-
-	struct hlist_head *event_notifier_syscall_dispatch;
-	struct hlist_head *event_notifier_compat_syscall_dispatch;
-	struct hlist_head *event_notifier_exit_syscall_dispatch;
-	struct hlist_head *event_notifier_exit_compat_syscall_dispatch;
-
-	struct hlist_head event_notifier_unknown_syscall_dispatch;
-	struct hlist_head event_notifier_compat_unknown_syscall_dispatch;
-	struct hlist_head event_notifier_exit_unknown_syscall_dispatch;
-	struct hlist_head event_notifier_exit_compat_unknown_syscall_dispatch;
-
-	int syscall_all_entry;
-	int syscall_all_exit;
 
-	unsigned int sys_enter_registered:1, sys_exit_registered:1;
+	struct lttng_kernel_syscall_table syscall_table;
 
 	struct lttng_counter *error_counter;
 	size_t error_counter_len;
@@ -447,13 +450,6 @@ struct lttng_counter_transport {
 	struct lttng_counter_ops ops;
 };
 
-#define LTTNG_EVENT_HT_BITS		12
-#define LTTNG_EVENT_HT_SIZE		(1U << LTTNG_EVENT_HT_BITS)
-
-struct lttng_event_ht {
-	struct hlist_head table[LTTNG_EVENT_HT_SIZE];
-};
-
 struct lttng_kernel_session_private {
 	struct lttng_kernel_session *pub;	/* Public session interface */
 
@@ -583,17 +579,59 @@ int lttng_kernel_interpret_event_filter(const struct lttng_kernel_event_common *
 		void *event_filter_ctx);
 
 static inline
-struct lttng_enabler *lttng_event_enabler_as_enabler(
-		struct lttng_event_enabler *event_enabler)
+struct lttng_event_enabler_common *lttng_event_recorder_enabler_as_enabler(
+		struct lttng_event_recorder_enabler *event_recorder_enabler)
 {
-	return &event_enabler->base;
+	return &event_recorder_enabler->parent;
 }
 
 static inline
-struct lttng_enabler *lttng_event_notifier_enabler_as_enabler(
+struct lttng_event_enabler_common *lttng_event_notifier_enabler_as_enabler(
 		struct lttng_event_notifier_enabler *event_notifier_enabler)
 {
-	return &event_notifier_enabler->base;
+	return &event_notifier_enabler->parent;
+}
+
+static inline
+struct lttng_event_ht *lttng_get_event_ht_from_enabler(struct lttng_event_enabler_common *event_enabler)
+{
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		return &event_recorder_enabler->chan->parent.session->priv->events_ht;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		return &event_notifier_enabler->group->events_ht;
+	}
+	default:
+		return NULL;
+	}
+}
+
+static inline
+struct list_head *lttng_get_event_list_head_from_enabler(struct lttng_event_enabler_common *event_enabler)
+{
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		return &event_recorder_enabler->chan->parent.session->priv->events;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		return &event_notifier_enabler->group->event_notifiers_head;
+	}
+	default:
+		return NULL;
+	}
 }
 
 int lttng_context_init(void);
@@ -775,34 +813,39 @@ int lttng_cpuhp_perf_counter_dead(unsigned int cpu,
 }
 #endif
 
-struct lttng_event_enabler *lttng_event_enabler_create(
+struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create(
 		enum lttng_enabler_format_type format_type,
 		struct lttng_kernel_abi_event *event_param,
 		struct lttng_kernel_channel_buffer *chan);
+void lttng_event_enabler_session_add(struct lttng_kernel_session *session,
+		struct lttng_event_recorder_enabler *event_enabler);
 
-int lttng_event_enabler_enable(struct lttng_event_enabler *event_enabler);
-int lttng_event_enabler_disable(struct lttng_event_enabler *event_enabler);
 struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create(
-		struct lttng_event_notifier_group *event_notifier_group,
 		enum lttng_enabler_format_type format_type,
-		struct lttng_kernel_abi_event_notifier *event_notifier_param);
-
-int lttng_event_notifier_enabler_enable(
-		struct lttng_event_notifier_enabler *event_notifier_enabler);
-int lttng_event_notifier_enabler_disable(
+		struct lttng_kernel_abi_event_notifier *event_notifier_param,
+		struct lttng_event_notifier_group *event_notifier_group);
+void lttng_event_notifier_enabler_group_add(struct lttng_event_notifier_group *event_notifier_group,
 		struct lttng_event_notifier_enabler *event_notifier_enabler);
-
-int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler *event_enabler,
-		struct lttng_kernel_abi_filter_bytecode __user *bytecode);
-int lttng_event_notifier_enabler_attach_filter_bytecode(
-		struct lttng_event_notifier_enabler *event_notifier_enabler,
-		struct lttng_kernel_abi_filter_bytecode __user *bytecode);
 int lttng_event_notifier_enabler_attach_capture_bytecode(
 		struct lttng_event_notifier_enabler *event_notifier_enabler,
 		struct lttng_kernel_abi_capture_bytecode __user *bytecode);
 
-int lttng_desc_match_enabler(const struct lttng_kernel_event_desc *desc,
-		struct lttng_enabler *enabler);
+int lttng_event_enabler_enable(struct lttng_event_enabler_common *event_enabler);
+int lttng_event_enabler_disable(struct lttng_event_enabler_common *event_enabler);
+int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler_common *event_enabler,
+		struct lttng_kernel_abi_filter_bytecode __user *bytecode);
+void lttng_event_enabler_destroy(struct lttng_event_enabler_common *event_enabler);
+
+bool lttng_desc_match_enabler(const struct lttng_kernel_event_desc *desc,
+		struct lttng_event_enabler_common *enabler);
+bool lttng_event_enabler_match_event(struct lttng_event_enabler_common *event_enabler,
+		struct lttng_kernel_event_common *event);
+bool lttng_event_enabler_desc_match_event(struct lttng_event_enabler_common *event_enabler,
+		const struct lttng_kernel_event_desc *desc,
+		struct lttng_kernel_event_common *event);
+bool lttng_event_enabler_event_name_match_event(struct lttng_event_enabler_common *event_enabler,
+		const char *event_name,
+		struct lttng_kernel_event_common *event);
 
 void lttng_enabler_link_bytecode(const struct lttng_kernel_event_desc *event_desc,
 		struct lttng_kernel_ctx *ctx,
@@ -810,87 +853,57 @@ void lttng_enabler_link_bytecode(const struct lttng_kernel_event_desc *event_des
 		struct list_head *enabler_bytecode_runtime_head);
 
 #if defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
-int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler);
-int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan);
-int lttng_syscalls_destroy_event(struct lttng_kernel_channel_buffer *chan);
-int lttng_syscall_filter_enable_event(
-		struct lttng_kernel_channel_buffer *chan,
-		struct lttng_kernel_event_recorder *event);
-int lttng_syscall_filter_disable_event(
-		struct lttng_kernel_channel_buffer *chan,
-		struct lttng_kernel_event_recorder *event);
-
-long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
-		struct lttng_kernel_abi_syscall_mask __user *usyscall_mask);
+int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enabler_common *event_enabler);
+int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event);
+int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event);
 
-int lttng_syscalls_register_event_notifier(
-		struct lttng_event_notifier_enabler *event_notifier_enabler);
-int lttng_syscalls_create_matching_event_notifiers(
-		struct lttng_event_notifier_enabler *event_notifier_enabler);
-int lttng_syscalls_unregister_event_notifier_group(struct lttng_event_notifier_group *group);
-int lttng_syscall_filter_enable_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
-int lttng_syscall_filter_disable_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
-#else
-static inline int lttng_syscalls_register_event(
-		struct lttng_event_enabler *event_enabler)
-{
-	return -ENOSYS;
-}
+int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table);
+int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table);
 
-static inline int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
-{
-	return 0;
-}
-
-static inline int lttng_syscalls_destroy(struct lttng_kernel_channel_buffer *chan)
-{
-	return 0;
-}
+long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
+		struct lttng_kernel_abi_syscall_mask __user *usyscall_mask);
 
-static inline int lttng_syscall_filter_enable_event(struct lttng_kernel_channel_buffer *chan,
-		struct lttng_kernel_event_recorder *event);
+void lttng_syscall_table_set_wildcard_all(struct lttng_event_enabler_common *event_enabler);
+#else
+static inline int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enabler_common *event_enabler)
 {
 	return -ENOSYS;
 }
 
-static inline int lttng_syscall_filter_disable_event(struct lttng_kernel_channel_buffer *chan,
-		struct lttng_kernel_event_recorder *event);
+static inline int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
 {
 	return -ENOSYS;
 }
 
-static inline long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
-		struct lttng_kernel_syscall_mask __user *usyscall_mask)
+static inline int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
 {
 	return -ENOSYS;
 }
 
-static inline int lttng_syscalls_register_event_notifier(
-		struct lttng_event_notifier_group *group)
+static inline int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-	return -ENOSYS;
+	return 0;
 }
 
-static inline int lttng_syscalls_unregister_event_notifier_group(
-		struct lttng_event_notifier_group *group)
+static inline int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
 	return 0;
 }
 
-static inline int lttng_syscall_filter_enable_event_notifier(
-		struct lttng_event_notifier_group *group,
-		const char *name)
+static inline long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
+		struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
 {
 	return -ENOSYS;
 }
 
-static inline int lttng_syscall_filter_disable_event_notifier(
-		struct lttng_event_notifier_group *group,
-		const char *name)
+static inline int lttng_syscalls_create_matching_event_notifiers(struct lttng_event_notifier_enabler *event_notifier_enabler)
 {
 	return -ENOSYS;
 }
 
+static inline void lttng_syscall_table_set_wildcard_all(struct lttng_event_enabler_common *event_enabler)
+{
+}
 #endif
 
 #ifdef CONFIG_KPROBES
@@ -898,52 +911,27 @@ int lttng_kprobes_register_event(const char *name,
 		const char *symbol_name,
 		uint64_t offset,
 		uint64_t addr,
-		struct lttng_kernel_event_recorder *event);
-void lttng_kprobes_unregister_event(struct lttng_kernel_event_recorder *event);
-void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_recorder *event);
-int lttng_kprobes_register_event_notifier(const char *symbol_name,
-		uint64_t offset,
-		uint64_t addr,
-		struct lttng_kernel_event_notifier *event_notifier);
-void lttng_kprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
-void lttng_kprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier);
+		struct lttng_kernel_event_common *event);
+void lttng_kprobes_unregister_event(struct lttng_kernel_event_common *event);
+void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_common *event);
 #else
 static inline
 int lttng_kprobes_register_event(const char *name,
 		const char *symbol_name,
 		uint64_t offset,
 		uint64_t addr,
-		struct lttng_kernel_event_recorder *event)
+		struct lttng_kernel_event_common *event)
 {
 	return -ENOSYS;
 }
 
 static inline
-void lttng_kprobes_unregister_event(struct lttng_kernel_event_recorder *event)
+void lttng_kprobes_unregister_event(struct lttng_kernel_event_common *event)
 {
 }
 
 static inline
-void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_recorder *event)
-{
-}
-
-static inline
-int lttng_kprobes_register_event_notifier(const char *symbol_name,
-		uint64_t offset,
-		uint64_t addr,
-		struct lttng_kernel_event_notifier *event_notifier)
-{
-	return -ENOSYS;
-}
-
-static inline
-void lttng_kprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
-{
-}
-
-static inline
-void lttng_kprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier)
+void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_common *event)
 {
 }
 #endif
@@ -953,19 +941,15 @@ int lttng_event_add_callsite(struct lttng_kernel_event_common *event,
 
 #ifdef CONFIG_UPROBES
 int lttng_uprobes_register_event(const char *name,
-	int fd, struct lttng_kernel_event_recorder *event);
+	int fd, struct lttng_kernel_event_common *event);
 int lttng_uprobes_event_add_callsite(struct lttng_kernel_event_common *event,
 	struct lttng_kernel_abi_event_callsite __user *callsite);
-void lttng_uprobes_unregister_event(struct lttng_kernel_event_recorder *event);
-void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_recorder *event);
-int lttng_uprobes_register_event_notifier(const char *name,
-	int fd, struct lttng_kernel_event_notifier *event_notifier);
-void lttng_uprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier);
-void lttng_uprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier);
+void lttng_uprobes_unregister_event(struct lttng_kernel_event_common *event);
+void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_common *event);
 #else
 static inline
 int lttng_uprobes_register_event(const char *name,
-	int fd, struct lttng_kernel_event_recorder *event)
+	int fd, struct lttng_kernel_event_common *event)
 {
 	return -ENOSYS;
 }
@@ -978,29 +962,12 @@ int lttng_uprobes_event_add_callsite(struct lttng_kernel_event_common *event,
 }
 
 static inline
-void lttng_uprobes_unregister_event(struct lttng_kernel_event_recorder *event)
+void lttng_uprobes_unregister_event(struct lttng_kernel_event_common *event)
 {
 }
 
 static inline
-void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_recorder *event)
-{
-}
-
-static inline
-int lttng_uprobes_register_event_notifier(const char *name,
-	int fd, struct lttng_kernel_event_notifier *event_notifier)
-{
-	return -ENOSYS;
-}
-
-static inline
-void lttng_uprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
-{
-}
-
-static inline
-void lttng_uprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier)
+void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_common *event)
 {
 }
 #endif
@@ -1010,10 +977,10 @@ int lttng_kretprobes_register(const char *name,
 		const char *symbol_name,
 		uint64_t offset,
 		uint64_t addr,
-		struct lttng_kernel_event_recorder *event_entry,
-		struct lttng_kernel_event_recorder *event_exit);
-void lttng_kretprobes_unregister(struct lttng_kernel_event_recorder *event);
-void lttng_kretprobes_destroy_private(struct lttng_kernel_event_recorder *event);
+		struct lttng_kernel_event_common *event_entry,
+		struct lttng_kernel_event_common *event_exit);
+void lttng_kretprobes_unregister(struct lttng_kernel_event_common *event);
+void lttng_kretprobes_destroy_private(struct lttng_kernel_event_common *event);
 int lttng_kretprobes_event_enable_state(struct lttng_kernel_event_common *event,
 	int enable);
 #else
@@ -1022,19 +989,19 @@ int lttng_kretprobes_register(const char *name,
 		const char *symbol_name,
 		uint64_t offset,
 		uint64_t addr,
-		struct lttng_kernel_event_recorder *event_entry,
-		struct lttng_kernel_event_recorder *event_exit)
+		struct lttng_kernel_event_common *event_entry,
+		struct lttng_kernel_event_common *event_exit)
 {
 	return -ENOSYS;
 }
 
 static inline
-void lttng_kretprobes_unregister(struct lttng_kernel_event_recorder *event)
+void lttng_kretprobes_unregister(struct lttng_kernel_event_common *event)
 {
 }
 
 static inline
-void lttng_kretprobes_destroy_private(struct lttng_kernel_event_recorder *event)
+void lttng_kretprobes_destroy_private(struct lttng_kernel_event_common *event)
 {
 }
 
@@ -1082,7 +1049,7 @@ int lttng_event_notifier_group_create_error_counter(
 void lttng_event_notifier_group_destroy(
 		struct lttng_event_notifier_group *event_notifier_group);
 
-struct lttng_kernel_channel_buffer *lttng_channel_create(struct lttng_kernel_session *session,
+struct lttng_kernel_channel_buffer *lttng_channel_buffer_create(struct lttng_kernel_session *session,
 				       const char *transport_name,
 				       void *buf_addr,
 				       size_t subbuf_size, size_t num_subbuf,
@@ -1096,35 +1063,13 @@ struct lttng_kernel_channel_buffer *lttng_global_channel_create(struct lttng_ker
 				       unsigned int read_timer_interval);
 
 void lttng_metadata_channel_destroy(struct lttng_kernel_channel_buffer *chan);
-struct lttng_kernel_event_recorder *lttng_kernel_event_recorder_create(struct lttng_kernel_channel_buffer *chan,
-				struct lttng_kernel_abi_event *event_param,
-				const struct lttng_kernel_event_desc *event_desc,
-				enum lttng_kernel_abi_instrumentation itype);
-struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct lttng_kernel_channel_buffer *chan,
-				struct lttng_kernel_abi_event *event_param,
-				const struct lttng_kernel_event_desc *event_desc,
-				enum lttng_kernel_abi_instrumentation itype);
-struct lttng_kernel_event_recorder *lttng_event_compat_old_create(struct lttng_kernel_channel_buffer *chan,
-		struct lttng_kernel_abi_old_event *old_event_param,
-		const struct lttng_kernel_event_desc *internal_desc);
-
-struct lttng_kernel_event_notifier *lttng_event_notifier_create(
-				const struct lttng_kernel_event_desc *event_notifier_desc,
-				uint64_t id,
-				uint64_t error_counter_idx,
-				struct lttng_event_notifier_group *event_notifier_group,
-				struct lttng_kernel_abi_event_notifier *event_notifier_param,
-				enum lttng_kernel_abi_instrumentation itype);
-struct lttng_kernel_event_notifier *_lttng_event_notifier_create(
-				const struct lttng_kernel_event_desc *event_notifier_desc,
-				uint64_t id,
-				uint64_t error_counter_idx,
-				struct lttng_event_notifier_group *event_notifier_group,
-				struct lttng_kernel_abi_event_notifier *event_notifier_param,
-				enum lttng_kernel_abi_instrumentation itype);
-
-int lttng_channel_enable(struct lttng_kernel_channel_buffer *channel);
-int lttng_channel_disable(struct lttng_kernel_channel_buffer *channel);
+struct lttng_kernel_event_common *_lttng_kernel_event_create(struct lttng_event_enabler_common *event_enabler,
+				const struct lttng_kernel_event_desc *event_desc);
+struct lttng_kernel_event_common *lttng_kernel_event_create(struct lttng_event_enabler_common *event_enabler,
+				const struct lttng_kernel_event_desc *event_desc);
+
+int lttng_channel_enable(struct lttng_kernel_channel_common *channel);
+int lttng_channel_disable(struct lttng_kernel_channel_common *channel);
 int lttng_event_enable(struct lttng_kernel_event_common *event);
 int lttng_event_disable(struct lttng_kernel_event_common *event);
 
diff --git a/include/lttng/events.h b/include/lttng/events.h
index fa3e7e9..d25f428 100644
--- a/include/lttng/events.h
+++ b/include/lttng/events.h
@@ -94,7 +94,7 @@ struct lttng_kernel_type_array {
 	struct lttng_kernel_type_common parent;
 	const struct lttng_kernel_type_common *elem_type;
 	unsigned int length;			/* Num. elems. */
-	unsigned int alignment;
+	unsigned int alignment;		/* Alignment in bytes before elements. */
 	enum lttng_kernel_string_encoding encoding;
 };
 
@@ -102,7 +102,7 @@ struct lttng_kernel_type_sequence {
 	struct lttng_kernel_type_common parent;
 	const char *length_name;	/* Length field name. If NULL, use previous field. */
 	const struct lttng_kernel_type_common *elem_type;
-	unsigned int alignment;		/* Alignment before elements. */
+	unsigned int alignment;		/* Alignment in bytes before elements. */
 	enum lttng_kernel_string_encoding encoding;
 };
 
@@ -110,7 +110,7 @@ struct lttng_kernel_type_struct {
 	struct lttng_kernel_type_common parent;
 	unsigned int nr_fields;
 	const struct lttng_kernel_event_field * const *fields;	/* Array of pointers to fields. */
-	unsigned int alignment;
+	unsigned int alignment;		/* Alignment in bits */
 };
 
 struct lttng_kernel_type_variant {
@@ -118,7 +118,7 @@ struct lttng_kernel_type_variant {
 	const char *tag_name;		/* Tag field name. If NULL, use previous field. */
 	const struct lttng_kernel_event_field * const *choices; /* Array of pointers to fields. */
 	unsigned int nr_choices;
-	unsigned int alignment;
+	unsigned int alignment;		/* Alignment in bytes */
 };
 
 struct lttng_kernel_enum_desc {
diff --git a/include/lttng/tracer.h b/include/lttng/tracer.h
index 2643f2e..927ad9f 100644
--- a/include/lttng/tracer.h
+++ b/include/lttng/tracer.h
@@ -28,8 +28,8 @@
 
 #define LTTNG_MODULES_MAJOR_VERSION 2
 #define LTTNG_MODULES_MINOR_VERSION 13
-#define LTTNG_MODULES_PATCHLEVEL_VERSION 3
-#define LTTNG_MODULES_EXTRAVERSION ""
+#define LTTNG_MODULES_PATCHLEVEL_VERSION 0
+#define LTTNG_MODULES_EXTRAVERSION "-rc1"
 
 #define LTTNG_VERSION_NAME		"Nordicité"
 #define LTTNG_VERSION_DESCRIPTION	"The product of a collaboration between Champ Libre and Boréale, this farmhouse IPA is brewed with Kveik yeast and Québec-grown barley, oats and juniper branches. The result is a remarkable fruity hazy golden IPA that offers a balanced touch of resinous and woodsy bitterness."
diff --git a/src/lttng-abi.c b/src/lttng-abi.c
index 864df6f..fa7eca6 100644
--- a/src/lttng-abi.c
+++ b/src/lttng-abi.c
@@ -550,7 +550,7 @@ int lttng_abi_create_channel(struct file *session_file,
 	 * We tolerate no failure path after channel creation. It will stay
 	 * invariant for the rest of the session.
 	 */
-	chan = lttng_channel_create(session, transport_name, NULL,
+	chan = lttng_channel_buffer_create(session, transport_name, NULL,
 				  chan_param->subbuf_size,
 				  chan_param->num_subbuf,
 				  chan_param->switch_timer_interval,
@@ -1893,19 +1893,21 @@ int lttng_abi_create_event(struct file *channel_file,
 		lttng_fallthrough;
 	case LTTNG_KERNEL_ABI_SYSCALL:
 	{
-		struct lttng_event_enabler *event_enabler;
+		struct lttng_event_recorder_enabler *event_enabler;
 
 		if (strutils_is_star_glob_pattern(event_param->name)) {
 			/*
 			 * If the event name is a star globbing pattern,
 			 * we create the special star globbing enabler.
 			 */
-			event_enabler = lttng_event_enabler_create(LTTNG_ENABLER_FORMAT_STAR_GLOB,
+			event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_STAR_GLOB,
 				event_param, channel);
 		} else {
-			event_enabler = lttng_event_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
+			event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
 				event_param, channel);
 		}
+		if (event_enabler)
+			lttng_event_enabler_session_add(channel->parent.session, event_enabler);
 		priv = event_enabler;
 		break;
 	}
@@ -1916,20 +1918,27 @@ int lttng_abi_create_event(struct file *channel_file,
 		lttng_fallthrough;
 	case LTTNG_KERNEL_ABI_UPROBE:
 	{
-		struct lttng_kernel_event_recorder *event;
+		struct lttng_kernel_event_common *event;
+		struct lttng_event_recorder_enabler *event_enabler;
 
+		event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
+				event_param, channel);
+		if (!event_enabler) {
+			ret = -ENOMEM;
+			goto event_error;
+		}
 		/*
 		 * We tolerate no failure path after event creation. It
 		 * will stay invariant for the rest of the session.
 		 */
-		event = lttng_kernel_event_recorder_create(channel, event_param,
-				NULL, event_param->instrumentation);
-		WARN_ON_ONCE(!event);
+		event = lttng_kernel_event_create(&event_enabler->parent, NULL);
+		WARN_ON_ONCE(IS_ERR(event));
+		lttng_event_enabler_destroy(&event_enabler->parent);
 		if (IS_ERR(event)) {
 			ret = PTR_ERR(event);
 			goto event_error;
 		}
-		priv = event;
+		priv = container_of(event, struct lttng_kernel_event_recorder, parent);
 		break;
 	}
 
@@ -1984,12 +1993,11 @@ long lttng_event_notifier_enabler_ioctl(struct file *file, unsigned int cmd, uns
 
 	switch (cmd) {
 	case LTTNG_KERNEL_ABI_ENABLE:
-		return lttng_event_notifier_enabler_enable(event_notifier_enabler);
+		return lttng_event_enabler_enable(&event_notifier_enabler->parent);
 	case LTTNG_KERNEL_ABI_DISABLE:
-		return lttng_event_notifier_enabler_disable(event_notifier_enabler);
+		return lttng_event_enabler_disable(&event_notifier_enabler->parent);
 	case LTTNG_KERNEL_ABI_FILTER:
-		return lttng_event_notifier_enabler_attach_filter_bytecode(
-				event_notifier_enabler,
+		return lttng_event_enabler_attach_filter_bytecode(&event_notifier_enabler->parent,
 			(struct lttng_kernel_abi_filter_bytecode __user *) arg);
 	case LTTNG_KERNEL_ABI_CAPTURE:
 		return lttng_event_notifier_enabler_attach_capture_bytecode(
@@ -2130,15 +2138,17 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file,
 			 * we create the special star globbing enabler.
 			 */
 			enabler = lttng_event_notifier_enabler_create(
-					event_notifier_group,
 					LTTNG_ENABLER_FORMAT_STAR_GLOB,
-					event_notifier_param);
+					event_notifier_param,
+					event_notifier_group);
 		} else {
 			enabler = lttng_event_notifier_enabler_create(
-					event_notifier_group,
 					LTTNG_ENABLER_FORMAT_NAME,
-					event_notifier_param);
+					event_notifier_param,
+					event_notifier_group);
 		}
+		if (enabler)
+			lttng_event_notifier_enabler_group_add(event_notifier_group, enabler);
 		priv = enabler;
 		break;
 	}
@@ -2149,24 +2159,23 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file,
 		lttng_fallthrough;
 	case LTTNG_KERNEL_ABI_UPROBE:
 	{
-		struct lttng_kernel_event_notifier *event_notifier;
+		struct lttng_kernel_event_common *event;
+		struct lttng_event_notifier_enabler *event_notifier_enabler;
 
-		/*
-		 * We tolerate no failure path after event notifier creation.
-		 * It will stay invariant for the rest of the session.
-		 */
-		event_notifier = lttng_event_notifier_create(NULL,
-				event_notifier_param->event.token,
-				event_notifier_param->error_counter_index,
-				event_notifier_group,
-				event_notifier_param,
-				event_notifier_param->event.instrumentation);
-		WARN_ON_ONCE(!event_notifier);
-		if (IS_ERR(event_notifier)) {
-			ret = PTR_ERR(event_notifier);
+		event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
+				event_notifier_param, event_notifier_group);
+		if (!event_notifier_enabler) {
+			ret = -ENOMEM;
+			goto event_notifier_error;
+		}
+		event = lttng_kernel_event_create(&event_notifier_enabler->parent, NULL);
+		WARN_ON_ONCE(IS_ERR(event));
+		lttng_event_enabler_destroy(&event_notifier_enabler->parent);
+		if (IS_ERR(event)) {
+			ret = PTR_ERR(event);
 			goto event_notifier_error;
 		}
-		priv = event_notifier;
+		priv = container_of(event, struct lttng_kernel_event_notifier, parent);
 		break;
 	}
 
@@ -2525,12 +2534,12 @@ old_ctx_end:
 	}
 	case LTTNG_KERNEL_ABI_OLD_ENABLE:
 	case LTTNG_KERNEL_ABI_ENABLE:
-		return lttng_channel_enable(channel);
+		return lttng_channel_enable(&channel->parent);
 	case LTTNG_KERNEL_ABI_OLD_DISABLE:
 	case LTTNG_KERNEL_ABI_DISABLE:
-		return lttng_channel_disable(channel);
+		return lttng_channel_disable(&channel->parent);
 	case LTTNG_KERNEL_ABI_SYSCALL_MASK:
-		return lttng_channel_syscall_mask(channel,
+		return lttng_syscall_table_get_active_mask(&channel->priv->parent.syscall_table,
 			(struct lttng_kernel_abi_syscall_mask __user *) arg);
 	default:
 		return -ENOIOCTLCMD;
@@ -2697,7 +2706,7 @@ long lttng_event_recorder_event_ioctl(struct file *file, unsigned int cmd, unsig
 static
 long lttng_event_recorder_enabler_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct lttng_event_enabler *event_enabler = file->private_data;
+	struct lttng_event_recorder_enabler *event_enabler = file->private_data;
 
 	switch (cmd) {
 	case LTTNG_KERNEL_ABI_OLD_CONTEXT:
@@ -2712,13 +2721,12 @@ long lttng_event_recorder_enabler_ioctl(struct file *file, unsigned int cmd, uns
 	}
 	case LTTNG_KERNEL_ABI_OLD_ENABLE:
 	case LTTNG_KERNEL_ABI_ENABLE:
-		return lttng_event_enabler_enable(event_enabler);
+		return lttng_event_enabler_enable(&event_enabler->parent);
 	case LTTNG_KERNEL_ABI_OLD_DISABLE:
 	case LTTNG_KERNEL_ABI_DISABLE:
-		return lttng_event_enabler_disable(event_enabler);
+		return lttng_event_enabler_disable(&event_enabler->parent);
 	case LTTNG_KERNEL_ABI_FILTER:
-		return lttng_event_enabler_attach_filter_bytecode(
-			event_enabler,
+		return lttng_event_enabler_attach_filter_bytecode(&event_enabler->parent,
 			(struct lttng_kernel_abi_filter_bytecode __user *) arg);
 	case LTTNG_KERNEL_ABI_ADD_CALLSITE:
 		return -EINVAL;
@@ -2740,7 +2748,7 @@ int lttng_event_recorder_event_release(struct inode *inode, struct file *file)
 static
 int lttng_event_recorder_enabler_release(struct inode *inode, struct file *file)
 {
-	struct lttng_event_enabler *event_enabler = file->private_data;
+	struct lttng_event_recorder_enabler *event_enabler = file->private_data;
 
 	if (event_enabler)
 		fput(event_enabler->chan->priv->parent.file);
diff --git a/src/lttng-bytecode.c b/src/lttng-bytecode.c
index b143777..2ad0b39 100644
--- a/src/lttng-bytecode.c
+++ b/src/lttng-bytecode.c
@@ -578,14 +578,14 @@ void lttng_enabler_link_bytecode(const struct lttng_kernel_event_desc *event_des
 /*
  * We own the filter_bytecode if we return success.
  */
-int lttng_filter_enabler_attach_bytecode(struct lttng_enabler *enabler,
+int lttng_filter_enabler_attach_bytecode(struct lttng_event_enabler_common *enabler,
 		struct lttng_kernel_bytecode_node *filter_bytecode)
 {
 	list_add(&filter_bytecode->node, &enabler->filter_bytecode_head);
 	return 0;
 }
 
-void lttng_free_enabler_filter_bytecode(struct lttng_enabler *enabler)
+void lttng_free_enabler_filter_bytecode(struct lttng_event_enabler_common *enabler)
 {
 	struct lttng_kernel_bytecode_node *filter_bytecode, *tmp;
 
diff --git a/src/lttng-events.c b/src/lttng-events.c
index e9b5687..dab3a0e 100644
--- a/src/lttng-events.c
+++ b/src/lttng-events.c
@@ -72,18 +72,14 @@ static struct kmem_cache *event_notifier_private_cache;
 
 static void lttng_session_lazy_sync_event_enablers(struct lttng_kernel_session *session);
 static void lttng_session_sync_event_enablers(struct lttng_kernel_session *session);
-static void lttng_event_enabler_destroy(struct lttng_event_enabler *event_enabler);
-static void lttng_event_notifier_enabler_destroy(struct lttng_event_notifier_enabler *event_notifier_enabler);
 static void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group *event_notifier_group);
+static void lttng_event_enabler_sync(struct lttng_event_enabler_common *event_enabler);
 
 static void _lttng_event_destroy(struct lttng_kernel_event_common *event);
 static void _lttng_channel_destroy(struct lttng_kernel_channel_buffer *chan);
-static void _lttng_event_unregister(struct lttng_kernel_event_recorder *event);
-static void _lttng_event_notifier_unregister(struct lttng_kernel_event_notifier *event_notifier);
+static void _lttng_event_unregister(struct lttng_kernel_event_common *event);
 static
-int _lttng_event_metadata_statedump(struct lttng_kernel_session *session,
-				  struct lttng_kernel_channel_buffer *chan,
-				  struct lttng_kernel_event_recorder *event);
+int _lttng_event_recorder_metadata_statedump(struct lttng_kernel_event_common *event);
 static
 int _lttng_session_metadata_statedump(struct lttng_kernel_session *session);
 static
@@ -329,8 +325,8 @@ struct lttng_event_notifier_group *lttng_event_notifier_group_create(void)
 
 	INIT_LIST_HEAD(&event_notifier_group->enablers_head);
 	INIT_LIST_HEAD(&event_notifier_group->event_notifiers_head);
-	for (i = 0; i < LTTNG_EVENT_NOTIFIER_HT_SIZE; i++)
-		INIT_HLIST_HEAD(&event_notifier_group->event_notifiers_ht.table[i]);
+	for (i = 0; i < LTTNG_EVENT_HT_SIZE; i++)
+		INIT_HLIST_HEAD(&event_notifier_group->events_ht.table[i]);
 
 	list_add(&event_notifier_group->node, &event_notifier_groups);
 
@@ -361,26 +357,25 @@ void lttng_session_destroy(struct lttng_kernel_session *session)
 	struct lttng_kernel_channel_buffer_private *chan_priv, *tmpchan_priv;
 	struct lttng_kernel_event_recorder_private *event_recorder_priv, *tmpevent_recorder_priv;
 	struct lttng_metadata_stream *metadata_stream;
-	struct lttng_event_enabler *event_enabler, *tmp_event_enabler;
+	struct lttng_event_enabler_common *event_enabler, *tmp_event_enabler;
 	int ret;
 
 	mutex_lock(&sessions_mutex);
 	WRITE_ONCE(session->active, 0);
 	list_for_each_entry(chan_priv, &session->priv->chan, node) {
-		ret = lttng_syscalls_unregister_channel(chan_priv->pub);
+		ret = lttng_syscalls_unregister_syscall_table(&chan_priv->parent.syscall_table);
 		WARN_ON(ret);
 	}
-	list_for_each_entry(event_recorder_priv, &session->priv->events, node)
-		_lttng_event_unregister(event_recorder_priv->pub);
+	list_for_each_entry(event_recorder_priv, &session->priv->events, parent.node)
+		_lttng_event_unregister(&event_recorder_priv->pub->parent);
 	synchronize_trace();	/* Wait for in-flight events to complete */
 	list_for_each_entry(chan_priv, &session->priv->chan, node) {
-		ret = lttng_syscalls_destroy_event(chan_priv->pub);
+		ret = lttng_syscalls_destroy_syscall_table(&chan_priv->parent.syscall_table);
 		WARN_ON(ret);
 	}
-	list_for_each_entry_safe(event_enabler, tmp_event_enabler,
-			&session->priv->enablers_head, node)
+	list_for_each_entry_safe(event_enabler, tmp_event_enabler, &session->priv->enablers_head, node)
 		lttng_event_enabler_destroy(event_enabler);
-	list_for_each_entry_safe(event_recorder_priv, tmpevent_recorder_priv, &session->priv->events, node)
+	list_for_each_entry_safe(event_recorder_priv, tmpevent_recorder_priv, &session->priv->events, parent.node)
 		_lttng_event_destroy(&event_recorder_priv->pub->parent);
 	list_for_each_entry_safe(chan_priv, tmpchan_priv, &session->priv->chan, node) {
 		BUG_ON(chan_priv->channel_type == METADATA_CHANNEL);
@@ -406,7 +401,7 @@ void lttng_session_destroy(struct lttng_kernel_session *session)
 void lttng_event_notifier_group_destroy(
 		struct lttng_event_notifier_group *event_notifier_group)
 {
-	struct lttng_event_notifier_enabler *event_notifier_enabler, *tmp_event_notifier_enabler;
+	struct lttng_event_enabler_common *event_enabler, *tmp_event_enabler;
 	struct lttng_kernel_event_notifier_private *event_notifier_priv, *tmpevent_notifier_priv;
 	int ret;
 
@@ -415,26 +410,27 @@ void lttng_event_notifier_group_destroy(
 
 	mutex_lock(&sessions_mutex);
 
-	ret = lttng_syscalls_unregister_event_notifier_group(event_notifier_group);
+	ret = lttng_syscalls_unregister_syscall_table(&event_notifier_group->syscall_table);
 	WARN_ON(ret);
 
 	list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv,
-			&event_notifier_group->event_notifiers_head, node)
-		_lttng_event_notifier_unregister(event_notifier_priv->pub);
+			&event_notifier_group->event_notifiers_head, parent.node)
+		_lttng_event_unregister(&event_notifier_priv->pub->parent);
 
 	/* Wait for in-flight event notifier to complete */
 	synchronize_trace();
 
 	irq_work_sync(&event_notifier_group->wakeup_pending);
 
-	kfree(event_notifier_group->sc_filter);
+	ret = lttng_syscalls_destroy_syscall_table(&event_notifier_group->syscall_table);
+	WARN_ON(ret);
 
-	list_for_each_entry_safe(event_notifier_enabler, tmp_event_notifier_enabler,
+	list_for_each_entry_safe(event_enabler, tmp_event_enabler,
 			&event_notifier_group->enablers_head, node)
-		lttng_event_notifier_enabler_destroy(event_notifier_enabler);
+		lttng_event_enabler_destroy(event_enabler);
 
 	list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv,
-			&event_notifier_group->event_notifiers_head, node)
+			&event_notifier_group->event_notifiers_head, parent.node)
 		_lttng_event_destroy(&event_notifier_priv->pub->parent);
 
 	if (event_notifier_group->error_counter) {
@@ -570,7 +566,7 @@ int lttng_session_metadata_regenerate(struct lttng_kernel_session *session)
 		chan_priv->metadata_dumped = 0;
 	}
 
-	list_for_each_entry(event_recorder_priv, &session->priv->events, node) {
+	list_for_each_entry(event_recorder_priv, &session->priv->events, parent.node) {
 		event_recorder_priv->metadata_dumped = 0;
 	}
 
@@ -581,47 +577,60 @@ end:
 	return ret;
 }
 
-int lttng_channel_enable(struct lttng_kernel_channel_buffer *channel)
+static
+bool is_channel_buffer_metadata(struct lttng_kernel_channel_common *channel)
+{
+	struct lttng_kernel_channel_buffer *chan_buf;
+
+	if (channel->type != LTTNG_KERNEL_CHANNEL_TYPE_BUFFER)
+		return false;
+	chan_buf = container_of(channel, struct lttng_kernel_channel_buffer, parent);
+	if (chan_buf->priv->channel_type == METADATA_CHANNEL)
+		return true;
+	return false;
+}
+
+int lttng_channel_enable(struct lttng_kernel_channel_common *channel)
 {
 	int ret = 0;
 
 	mutex_lock(&sessions_mutex);
-	if (channel->priv->channel_type == METADATA_CHANNEL) {
+	if (is_channel_buffer_metadata(channel)) {
 		ret = -EPERM;
 		goto end;
 	}
-	if (channel->parent.enabled) {
+	if (channel->enabled) {
 		ret = -EEXIST;
 		goto end;
 	}
 	/* Set transient enabler state to "enabled" */
-	channel->priv->parent.tstate = 1;
-	lttng_session_sync_event_enablers(channel->parent.session);
+	channel->priv->tstate = 1;
+	lttng_session_sync_event_enablers(channel->session);
 	/* Set atomically the state to "enabled" */
-	WRITE_ONCE(channel->parent.enabled, 1);
+	WRITE_ONCE(channel->enabled, 1);
 end:
 	mutex_unlock(&sessions_mutex);
 	return ret;
 }
 
-int lttng_channel_disable(struct lttng_kernel_channel_buffer *channel)
+int lttng_channel_disable(struct lttng_kernel_channel_common *channel)
 {
 	int ret = 0;
 
 	mutex_lock(&sessions_mutex);
-	if (channel->priv->channel_type == METADATA_CHANNEL) {
+	if (is_channel_buffer_metadata(channel)) {
 		ret = -EPERM;
 		goto end;
 	}
-	if (!channel->parent.enabled) {
+	if (!channel->enabled) {
 		ret = -EEXIST;
 		goto end;
 	}
 	/* Set atomically the state to "disabled" */
-	WRITE_ONCE(channel->parent.enabled, 0);
+	WRITE_ONCE(channel->enabled, 0);
 	/* Set transient enabler state to "enabled" */
-	channel->priv->parent.tstate = 0;
-	lttng_session_sync_event_enablers(channel->parent.session);
+	channel->priv->tstate = 0;
+	lttng_session_sync_event_enablers(channel->session);
 end:
 	mutex_unlock(&sessions_mutex);
 	return ret;
@@ -755,7 +764,7 @@ end:
 	return ret;
 }
 
-struct lttng_kernel_channel_buffer *lttng_channel_create(struct lttng_kernel_session *session,
+struct lttng_kernel_channel_buffer *lttng_channel_buffer_create(struct lttng_kernel_session *session,
 				       const char *transport_name,
 				       void *buf_addr,
 				       size_t subbuf_size, size_t num_subbuf,
@@ -857,24 +866,217 @@ void _lttng_metadata_channel_hangup(struct lttng_metadata_stream *stream)
 	wake_up_interruptible(&stream->read_wait);
 }
 
+static
+bool lttng_kernel_event_id_available(struct lttng_event_enabler_common *event_enabler)
+{
+	struct lttng_kernel_abi_event *event_param = &event_enabler->event_param;
+        enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation;
+
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_kernel_channel_buffer *chan = event_recorder_enabler->chan;
+
+		switch (itype) {
+		case LTTNG_KERNEL_ABI_TRACEPOINT:
+			lttng_fallthrough;
+		case LTTNG_KERNEL_ABI_KPROBE:
+			lttng_fallthrough;
+		case LTTNG_KERNEL_ABI_SYSCALL:
+			lttng_fallthrough;
+		case LTTNG_KERNEL_ABI_UPROBE:
+			if (chan->priv->free_event_id == -1U)
+				return false;
+			return true;
+		case LTTNG_KERNEL_ABI_KRETPROBE:
+			/* kretprobes require 2 event IDs. */
+			if (chan->priv->free_event_id >= -2U)
+				return false;
+			return true;
+		default:
+			WARN_ON_ONCE(1);
+			return false;
+		}
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+		return true;
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+}
+
+static
+struct lttng_kernel_event_common *lttng_kernel_event_alloc(struct lttng_event_enabler_common *event_enabler)
+{
+	struct lttng_kernel_abi_event *event_param = &event_enabler->event_param;
+        enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation;
+
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_kernel_event_recorder *event_recorder;
+		struct lttng_kernel_event_recorder_private *event_recorder_priv;
+		struct lttng_kernel_channel_buffer *chan = event_recorder_enabler->chan;
+
+		event_recorder = kmem_cache_zalloc(event_recorder_cache, GFP_KERNEL);
+		if (!event_recorder)
+			return NULL;
+		event_recorder_priv = kmem_cache_zalloc(event_recorder_private_cache, GFP_KERNEL);
+		if (!event_recorder_priv) {
+			kmem_cache_free(event_recorder_private_cache, event_recorder);
+			return NULL;
+		}
+		event_recorder_priv->pub = event_recorder;
+		event_recorder_priv->parent.pub = &event_recorder->parent;
+		event_recorder->priv = event_recorder_priv;
+		event_recorder->parent.priv = &event_recorder_priv->parent;
+
+		event_recorder->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER;
+		event_recorder->parent.run_filter = lttng_kernel_interpret_event_filter;
+		event_recorder->priv->parent.instrumentation = itype;
+		INIT_LIST_HEAD(&event_recorder->priv->parent.filter_bytecode_runtime_head);
+		INIT_LIST_HEAD(&event_recorder->priv->parent.enablers_ref_head);
+
+		event_recorder->chan = chan;
+		event_recorder->priv->id = chan->priv->free_event_id++;
+		return &event_recorder->parent;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_kernel_event_notifier *event_notifier;
+		struct lttng_kernel_event_notifier_private *event_notifier_priv;
+
+		event_notifier = kmem_cache_zalloc(event_notifier_cache, GFP_KERNEL);
+		if (!event_notifier)
+			return NULL;
+		event_notifier_priv = kmem_cache_zalloc(event_notifier_private_cache, GFP_KERNEL);
+		if (!event_notifier_priv) {
+			kmem_cache_free(event_notifier_private_cache, event_notifier);
+			return NULL;
+		}
+		event_notifier_priv->pub = event_notifier;
+		event_notifier_priv->parent.pub = &event_notifier->parent;
+		event_notifier->priv = event_notifier_priv;
+		event_notifier->parent.priv = &event_notifier_priv->parent;
+
+		event_notifier->parent.type = LTTNG_KERNEL_EVENT_TYPE_NOTIFIER;
+		event_notifier->parent.run_filter = lttng_kernel_interpret_event_filter;
+		event_notifier->priv->parent.instrumentation = itype;
+		event_notifier->priv->parent.user_token = event_enabler->user_token;
+		INIT_LIST_HEAD(&event_notifier->priv->parent.filter_bytecode_runtime_head);
+		INIT_LIST_HEAD(&event_notifier->priv->parent.enablers_ref_head);
+
+		event_notifier->priv->group = event_notifier_enabler->group;
+		event_notifier->priv->error_counter_index = event_notifier_enabler->error_counter_index;
+		event_notifier->priv->num_captures = 0;
+		event_notifier->notification_send = lttng_event_notifier_notification_send;
+		INIT_LIST_HEAD(&event_notifier->priv->capture_bytecode_runtime_head);
+		return &event_notifier->parent;
+	}
+	default:
+		return NULL;
+	}
+}
+
+static
+void lttng_kernel_event_free(struct lttng_kernel_event_common *event)
+{
+	switch (event->type) {
+	case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+	{
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+
+		kmem_cache_free(event_recorder_private_cache, event_recorder->priv);
+		kmem_cache_free(event_recorder_cache, event_recorder);
+		break;
+	}
+	case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+	{
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+
+		kmem_cache_free(event_notifier_private_cache, event_notifier->priv);
+		kmem_cache_free(event_notifier_cache, event_notifier);
+		break;
+	}
+	default:
+		WARN_ON_ONCE(1);
+	}
+}
+
+static
+int lttng_kernel_event_notifier_clear_error_counter(struct lttng_kernel_event_common *event)
+{
+	switch (event->type) {
+	case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+		return 0;
+	case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+	{
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+		struct lttng_counter *error_counter;
+		struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
+		size_t dimension_index[1];
+		int ret;
+
+		/*
+		 * Clear the error counter bucket. The sessiond keeps track of which
+		 * bucket is currently in use. We trust it. The session lock
+		 * synchronizes against concurrent creation of the error
+		 * counter.
+		 */
+		error_counter = event_notifier_group->error_counter;
+		if (!error_counter)
+			return 0;
+		/*
+		 * Check that the index is within the boundary of the counter.
+		 */
+		if (event_notifier->priv->error_counter_index >= event_notifier_group->error_counter_len) {
+			printk(KERN_INFO "LTTng: event_notifier: Error counter index out-of-bound: counter-len=%zu, index=%llu\n",
+				event_notifier_group->error_counter_len, event_notifier->priv->error_counter_index);
+			return -EINVAL;
+		}
+
+		dimension_index[0] = event_notifier->priv->error_counter_index;
+		ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index);
+		if (ret) {
+			printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n",
+				event_notifier->priv->error_counter_index);
+			return -EINVAL;
+		}
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+}
 
 /*
  * Supports event creation while tracing session is active.
  * Needs to be called with sessions mutex held.
  */
-struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct lttng_kernel_channel_buffer *chan,
-				struct lttng_kernel_abi_event *event_param,
-				const struct lttng_kernel_event_desc *event_desc,
-				enum lttng_kernel_abi_instrumentation itype)
+struct lttng_kernel_event_common *_lttng_kernel_event_create(struct lttng_event_enabler_common *event_enabler,
+				const struct lttng_kernel_event_desc *event_desc)
 {
-	struct lttng_kernel_session *session = chan->parent.session;
-	struct lttng_kernel_event_recorder *event_recorder;
-	struct lttng_kernel_event_recorder_private *event_recorder_priv;
+	struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(event_enabler);
+	struct list_head *event_list_head = lttng_get_event_list_head_from_enabler(event_enabler);
+	struct lttng_kernel_abi_event *event_param = &event_enabler->event_param;
+	enum lttng_kernel_abi_instrumentation itype = event_param->instrumentation;
+	struct lttng_kernel_event_common_private *event_priv;
+	struct lttng_kernel_event_common *event;
 	const char *event_name;
 	struct hlist_head *head;
 	int ret;
 
-	if (chan->priv->free_event_id == -1U) {
+	if (!lttng_kernel_event_id_available(event_enabler)) {
 		ret = -EMFILE;
 		goto full;
 	}
@@ -904,48 +1106,27 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 		goto type_error;
 	}
 
-	head = utils_borrow_hash_table_bucket(session->priv->events_ht.table,
-		LTTNG_EVENT_HT_SIZE, event_name);
-	lttng_hlist_for_each_entry(event_recorder_priv, head, hlist) {
-		WARN_ON_ONCE(!event_recorder_priv->parent.desc);
-		if (!strncmp(event_recorder_priv->parent.desc->event_name, event_name,
-					LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1)
-				&& chan == event_recorder_priv->pub->chan) {
+	head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, event_name);
+	lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
+		if (lttng_event_enabler_event_name_match_event(event_enabler, event_name, event_priv->pub)) {
 			ret = -EEXIST;
 			goto exist;
 		}
 	}
 
-	event_recorder = kmem_cache_zalloc(event_recorder_cache, GFP_KERNEL);
-	if (!event_recorder) {
-		ret = -ENOMEM;
-		goto cache_error;
-	}
-	event_recorder_priv = kmem_cache_zalloc(event_recorder_private_cache, GFP_KERNEL);
-	if (!event_recorder_priv) {
+	event = lttng_kernel_event_alloc(event_enabler);
+	if (!event) {
 		ret = -ENOMEM;
-		goto cache_private_error;
+		goto alloc_error;
 	}
-	event_recorder_priv->pub = event_recorder;
-	event_recorder_priv->parent.pub = &event_recorder->parent;
-	event_recorder->priv = event_recorder_priv;
-	event_recorder->parent.priv = &event_recorder_priv->parent;
-	event_recorder->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER;
-
-	event_recorder->parent.run_filter = lttng_kernel_interpret_event_filter;
-	event_recorder->chan = chan;
-	event_recorder->priv->id = chan->priv->free_event_id++;
-	event_recorder->priv->parent.instrumentation = itype;
-	INIT_LIST_HEAD(&event_recorder->priv->parent.filter_bytecode_runtime_head);
-	INIT_LIST_HEAD(&event_recorder->priv->parent.enablers_ref_head);
 
 	switch (itype) {
 	case LTTNG_KERNEL_ABI_TRACEPOINT:
 		/* Event will be enabled by enabler sync. */
-		event_recorder->parent.enabled = 0;
-		event_recorder->priv->parent.registered = 0;
-		event_recorder->priv->parent.desc = lttng_event_desc_get(event_name);
-		if (!event_recorder->priv->parent.desc) {
+		event->enabled = 0;
+		event->priv->registered = 0;
+		event->priv->desc = lttng_event_desc_get(event_name);
+		if (!event->priv->desc) {
 			ret = -ENOENT;
 			goto register_error;
 		}
@@ -958,8 +1139,8 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 		 * Needs to be explicitly enabled after creation, since
 		 * we may want to apply filters.
 		 */
-		event_recorder->parent.enabled = 0;
-		event_recorder->priv->parent.registered = 1;
+		event->enabled = 0;
+		event->priv->registered = 1;
 		/*
 		 * Populate lttng_event structure before event
 		 * registration.
@@ -969,53 +1150,36 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 				event_param->u.kprobe.symbol_name,
 				event_param->u.kprobe.offset,
 				event_param->u.kprobe.addr,
-				event_recorder);
+				event);
 		if (ret) {
 			ret = -EINVAL;
 			goto register_error;
 		}
-		ret = try_module_get(event_recorder->priv->parent.desc->owner);
+		ret = try_module_get(event->priv->desc->owner);
 		WARN_ON_ONCE(!ret);
 		break;
 
 	case LTTNG_KERNEL_ABI_KRETPROBE:
 	{
-		struct lttng_kernel_event_recorder *event_recorder_return;
-		struct lttng_kernel_event_recorder_private *event_recorder_return_priv;
+		struct lttng_kernel_event_common *event_return;
 
 		/* kretprobe defines 2 events */
 		/*
 		 * Needs to be explicitly enabled after creation, since
 		 * we may want to apply filters.
 		 */
-		event_recorder->parent.enabled = 0;
-		event_recorder->priv->parent.registered = 1;
+		event->enabled = 0;
+		event->priv->registered = 1;
 
-		event_recorder_return = kmem_cache_zalloc(event_recorder_cache, GFP_KERNEL);
-		if (!event_recorder_return) {
+		event_return = lttng_kernel_event_alloc(event_enabler);
+		if (!event) {
 			ret = -ENOMEM;
-			goto register_error;
-		}
-		event_recorder_return_priv = kmem_cache_zalloc(event_recorder_private_cache, GFP_KERNEL);
-		if (!event_recorder_return_priv) {
-			kmem_cache_free(event_recorder_cache, event_recorder_return);
-			ret = -ENOMEM;
-			goto register_error;
+			goto alloc_error;
 		}
-		event_recorder_return_priv->pub = event_recorder_return;
-		event_recorder_return_priv->parent.pub = &event_recorder_return->parent;
-		event_recorder_return->priv = event_recorder_return_priv;
-		event_recorder_return->parent.priv = &event_recorder_return_priv->parent;
-		event_recorder_return->parent.type = LTTNG_KERNEL_EVENT_TYPE_RECORDER;
-
-		event_recorder_return->parent.run_filter = lttng_kernel_interpret_event_filter;
-		event_recorder_return->chan = chan;
-		event_recorder_return->priv->id = chan->priv->free_event_id++;
-		event_recorder_return->priv->parent.instrumentation = itype;
-		event_recorder_return->parent.enabled = 0;
-		event_recorder_return->priv->parent.registered = 1;
-		INIT_LIST_HEAD(&event_recorder_return->priv->parent.filter_bytecode_runtime_head);
-		INIT_LIST_HEAD(&event_recorder_return->priv->parent.enablers_ref_head);
+
+		event_return->enabled = 0;
+		event_return->priv->registered = 1;
+
 		/*
 		 * Populate lttng_event structure before kretprobe registration.
 		 */
@@ -1024,29 +1188,26 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 				event_param->u.kretprobe.symbol_name,
 				event_param->u.kretprobe.offset,
 				event_param->u.kretprobe.addr,
-				event_recorder, event_recorder_return);
+				event, event_return);
 		if (ret) {
-			kmem_cache_free(event_recorder_private_cache, event_recorder_return_priv);
-			kmem_cache_free(event_recorder_cache, event_recorder_return);
+			lttng_kernel_event_free(event_return);
 			ret = -EINVAL;
 			goto register_error;
 		}
 		/* Take 2 refs on the module: one per event. */
-		ret = try_module_get(event_recorder->priv->parent.desc->owner);
+		ret = try_module_get(event->priv->desc->owner);
 		WARN_ON_ONCE(!ret);
-		ret = try_module_get(event_recorder_return->priv->parent.desc->owner);
+		ret = try_module_get(event_return->priv->desc->owner);
 		WARN_ON_ONCE(!ret);
-		ret = _lttng_event_metadata_statedump(chan->parent.session, chan,
-						    event_recorder_return);
+		ret = _lttng_event_recorder_metadata_statedump(event_return);
 		WARN_ON_ONCE(ret > 0);
 		if (ret) {
-			kmem_cache_free(event_recorder_private_cache, event_recorder_return_priv);
-			kmem_cache_free(event_recorder_cache, event_recorder_return);
-			module_put(event_recorder_return->priv->parent.desc->owner);
-			module_put(event_recorder->priv->parent.desc->owner);
+			lttng_kernel_event_free(event_return);
+			module_put(event_return->priv->desc->owner);
+			module_put(event->priv->desc->owner);
 			goto statedump_error;
 		}
-		list_add(&event_recorder_return->priv->node, &chan->parent.session->priv->events);
+		list_add(&event_return->priv->node, event_list_head);
 		break;
 	}
 
@@ -1055,18 +1216,18 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 		 * Needs to be explicitly enabled after creation, since
 		 * we may want to apply filters.
 		 */
-		event_recorder->parent.enabled = 0;
-		event_recorder->priv->parent.registered = 0;
-		event_recorder->priv->parent.desc = event_desc;
+		event->enabled = 0;
+		event->priv->registered = 0;
+		event->priv->desc = event_desc;
 		switch (event_param->u.syscall.entryexit) {
 		case LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT:
 			ret = -EINVAL;
 			goto register_error;
 		case LTTNG_KERNEL_ABI_SYSCALL_ENTRY:
-			event_recorder->priv->parent.u.syscall.entryexit = LTTNG_SYSCALL_ENTRY;
+			event->priv->u.syscall.entryexit = LTTNG_SYSCALL_ENTRY;
 			break;
 		case LTTNG_KERNEL_ABI_SYSCALL_EXIT:
-			event_recorder->priv->parent.u.syscall.entryexit = LTTNG_SYSCALL_EXIT;
+			event->priv->u.syscall.entryexit = LTTNG_SYSCALL_EXIT;
 			break;
 		}
 		switch (event_param->u.syscall.abi) {
@@ -1074,13 +1235,13 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 			ret = -EINVAL;
 			goto register_error;
 		case LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE:
-			event_recorder->priv->parent.u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE;
+			event->priv->u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE;
 			break;
 		case LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT:
-			event_recorder->priv->parent.u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT;
+			event->priv->u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT;
 			break;
 		}
-		if (!event_recorder->priv->parent.desc) {
+		if (!event->priv->desc) {
 			ret = -EINVAL;
 			goto register_error;
 		}
@@ -1091,8 +1252,8 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 		 * Needs to be explicitly enabled after creation, since
 		 * we may want to apply filters.
 		 */
-		event_recorder->parent.enabled = 0;
-		event_recorder->priv->parent.registered = 1;
+		event->enabled = 0;
+		event->priv->registered = 1;
 
 		/*
 		 * Populate lttng_event structure before event
@@ -1102,411 +1263,179 @@ struct lttng_kernel_event_recorder *_lttng_kernel_event_recorder_create(struct l
 
 		ret = lttng_uprobes_register_event(event_param->name,
 				event_param->u.uprobe.fd,
-				event_recorder);
+				event);
 		if (ret)
 			goto register_error;
-		ret = try_module_get(event_recorder->priv->parent.desc->owner);
+		ret = try_module_get(event->priv->desc->owner);
 		WARN_ON_ONCE(!ret);
 		break;
 
-	case LTTNG_KERNEL_ABI_FUNCTION:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_NOOP:
-		lttng_fallthrough;
 	default:
 		WARN_ON_ONCE(1);
 		ret = -EINVAL;
 		goto register_error;
 	}
-	ret = _lttng_event_metadata_statedump(chan->parent.session, chan, event_recorder);
+
+	ret = _lttng_event_recorder_metadata_statedump(event);
 	WARN_ON_ONCE(ret > 0);
 	if (ret) {
 		goto statedump_error;
 	}
-	hlist_add_head(&event_recorder->priv->hlist, head);
-	list_add(&event_recorder->priv->node, &chan->parent.session->priv->events);
-	return event_recorder;
+
+	ret = lttng_kernel_event_notifier_clear_error_counter(event);
+	if (ret)
+		goto register_error;
+
+	hlist_add_head(&event->priv->hlist_node, head);
+	list_add(&event->priv->node, event_list_head);
+
+	return event;
 
 statedump_error:
 	/* If a statedump error occurs, events will not be readable. */
 register_error:
-	kmem_cache_free(event_recorder_private_cache, event_recorder_priv);
-cache_private_error:
-	kmem_cache_free(event_recorder_cache, event_recorder);
-cache_error:
+	lttng_kernel_event_free(event);
+alloc_error:
 exist:
 type_error:
 full:
 	return ERR_PTR(ret);
 }
 
-struct lttng_kernel_event_notifier *_lttng_event_notifier_create(
-		const struct lttng_kernel_event_desc *event_desc,
-		uint64_t token, uint64_t error_counter_index,
-		struct lttng_event_notifier_group *event_notifier_group,
-		struct lttng_kernel_abi_event_notifier *event_notifier_param,
-		enum lttng_kernel_abi_instrumentation itype)
+struct lttng_kernel_event_common *lttng_kernel_event_create(struct lttng_event_enabler_common *event_enabler,
+				const struct lttng_kernel_event_desc *event_desc)
 {
-	struct lttng_kernel_event_notifier *event_notifier;
-	struct lttng_kernel_event_notifier_private *event_notifier_priv;
-	struct lttng_counter *error_counter;
-	const char *event_name;
-	struct hlist_head *head;
-	int ret;
+	struct lttng_kernel_event_common *event;
 
-	switch (itype) {
+	mutex_lock(&sessions_mutex);
+	event = _lttng_kernel_event_create(event_enabler, event_desc);
+	mutex_unlock(&sessions_mutex);
+	return event;
+}
+
+int lttng_kernel_counter_read(struct lttng_counter *counter,
+		const size_t *dim_indexes, int32_t cpu,
+		int64_t *val, bool *overflow, bool *underflow)
+{
+	return counter->ops->counter_read(counter->counter, dim_indexes,
+			cpu, val, overflow, underflow);
+}
+
+int lttng_kernel_counter_aggregate(struct lttng_counter *counter,
+		const size_t *dim_indexes, int64_t *val,
+		bool *overflow, bool *underflow)
+{
+	return counter->ops->counter_aggregate(counter->counter, dim_indexes,
+			val, overflow, underflow);
+}
+
+int lttng_kernel_counter_clear(struct lttng_counter *counter,
+		const size_t *dim_indexes)
+{
+	return counter->ops->counter_clear(counter->counter, dim_indexes);
+}
+
+/* Only used for tracepoints and system calls for now. */
+static
+void register_event(struct lttng_kernel_event_common *event)
+{
+	const struct lttng_kernel_event_desc *desc;
+	int ret = -EINVAL;
+
+	WARN_ON_ONCE(event->priv->registered);
+
+	desc = event->priv->desc;
+	switch (event->priv->instrumentation) {
 	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		event_name = event_desc->event_name;
+		ret = lttng_wrapper_tracepoint_probe_register(desc->event_kname,
+						  desc->tp_class->probe_callback,
+						  event);
+		break;
+
+	case LTTNG_KERNEL_ABI_SYSCALL:
+		ret = lttng_syscall_filter_enable_event(event);
 		break;
 
 	case LTTNG_KERNEL_ABI_KPROBE:
 		lttng_fallthrough;
 	case LTTNG_KERNEL_ABI_UPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		event_name = event_notifier_param->event.name;
+		ret = 0;
 		break;
 
 	case LTTNG_KERNEL_ABI_KRETPROBE:
-		lttng_fallthrough;
+		switch (event->type) {
+		case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+			ret = 0;
+			break;
+		case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+			WARN_ON_ONCE(1);
+			break;
+		}
+		break;
+
 	case LTTNG_KERNEL_ABI_FUNCTION:
 		lttng_fallthrough;
 	case LTTNG_KERNEL_ABI_NOOP:
 		lttng_fallthrough;
 	default:
 		WARN_ON_ONCE(1);
-		ret = -EINVAL;
-		goto type_error;
 	}
+	WARN_ON_ONCE(ret);
+	if (!ret)
+		event->priv->registered = 1;
+}
 
-	head = utils_borrow_hash_table_bucket(event_notifier_group->event_notifiers_ht.table,
-		LTTNG_EVENT_NOTIFIER_HT_SIZE, event_name);
-	lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
-		WARN_ON_ONCE(!event_notifier_priv->parent.desc);
-		if (!strncmp(event_notifier_priv->parent.desc->event_name, event_name,
-					LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1)
-				&& event_notifier_group == event_notifier_priv->group
-				&& token == event_notifier_priv->parent.user_token) {
-			ret = -EEXIST;
-			goto exist;
-		}
-	}
+static
+void unregister_event(struct lttng_kernel_event_common *event)
+{
+	struct lttng_kernel_event_common_private *event_priv = event->priv;
+	const struct lttng_kernel_event_desc *desc;
+	int ret = -EINVAL;
 
-	event_notifier = kmem_cache_zalloc(event_notifier_cache, GFP_KERNEL);
-	if (!event_notifier) {
-		ret = -ENOMEM;
-		goto cache_error;
-	}
-	event_notifier_priv = kmem_cache_zalloc(event_notifier_private_cache, GFP_KERNEL);
-	if (!event_notifier_priv) {
-		ret = -ENOMEM;
-		goto cache_private_error;
-	}
-	event_notifier_priv->pub = event_notifier;
-	event_notifier_priv->parent.pub = &event_notifier->parent;
-	event_notifier->priv = event_notifier_priv;
-	event_notifier->parent.priv = &event_notifier_priv->parent;
-	event_notifier->parent.type = LTTNG_KERNEL_EVENT_TYPE_NOTIFIER;
-
-	event_notifier->priv->group = event_notifier_group;
-	event_notifier->priv->parent.user_token = token;
-	event_notifier->priv->error_counter_index = error_counter_index;
-	event_notifier->priv->num_captures = 0;
-	event_notifier->priv->parent.instrumentation = itype;
-	event_notifier->notification_send = lttng_event_notifier_notification_send;
-	INIT_LIST_HEAD(&event_notifier->priv->parent.filter_bytecode_runtime_head);
-	INIT_LIST_HEAD(&event_notifier->priv->parent.enablers_ref_head);
-	INIT_LIST_HEAD(&event_notifier->priv->capture_bytecode_runtime_head);
-	event_notifier->parent.run_filter = lttng_kernel_interpret_event_filter;
+	WARN_ON_ONCE(!event->priv->registered);
 
-	switch (itype) {
+	desc = event_priv->desc;
+	switch (event_priv->instrumentation) {
 	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		/* Event will be enabled by enabler sync. */
-		event_notifier->parent.enabled = 0;
-		event_notifier->priv->parent.registered = 0;
-		event_notifier->priv->parent.desc = lttng_event_desc_get(event_name);
-		if (!event_notifier->priv->parent.desc) {
-			ret = -ENOENT;
-			goto register_error;
-		}
-		/* Populate lttng_event_notifier structure before event registration. */
-		smp_wmb();
+		ret = lttng_wrapper_tracepoint_probe_unregister(event_priv->desc->event_kname,
+						  event_priv->desc->tp_class->probe_callback,
+						  event);
 		break;
 
 	case LTTNG_KERNEL_ABI_KPROBE:
-		/*
-		 * Needs to be explicitly enabled after creation, since
-		 * we may want to apply filters.
-		 */
-		event_notifier->parent.enabled = 0;
-		event_notifier->priv->parent.registered = 1;
-		/*
-		 * Populate lttng_event_notifier structure before event
-		 * registration.
-		 */
-		smp_wmb();
-		ret = lttng_kprobes_register_event_notifier(
-				event_notifier_param->event.u.kprobe.symbol_name,
-				event_notifier_param->event.u.kprobe.offset,
-				event_notifier_param->event.u.kprobe.addr,
-				event_notifier);
-		if (ret) {
-			ret = -EINVAL;
-			goto register_error;
-		}
-		ret = try_module_get(event_notifier->priv->parent.desc->owner);
-		WARN_ON_ONCE(!ret);
+		lttng_kprobes_unregister_event(event);
+		ret = 0;
 		break;
 
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		/*
-		 * Needs to be explicitly enabled after creation, since
-		 * we may want to apply filters.
-		 */
-		event_notifier->parent.enabled = 0;
-		event_notifier->priv->parent.registered = 0;
-		event_notifier->priv->parent.desc = event_desc;
-		switch (event_notifier_param->event.u.syscall.entryexit) {
-		case LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT:
-			ret = -EINVAL;
-			goto register_error;
-		case LTTNG_KERNEL_ABI_SYSCALL_ENTRY:
-			event_notifier->priv->parent.u.syscall.entryexit = LTTNG_SYSCALL_ENTRY;
+	case LTTNG_KERNEL_ABI_KRETPROBE:
+		switch (event->type) {
+		case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+			lttng_kretprobes_unregister(event);
+			ret = 0;
 			break;
-		case LTTNG_KERNEL_ABI_SYSCALL_EXIT:
-			event_notifier->priv->parent.u.syscall.entryexit = LTTNG_SYSCALL_EXIT;
+		case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+			WARN_ON_ONCE(1);
 			break;
 		}
-		switch (event_notifier_param->event.u.syscall.abi) {
-		case LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL:
-			ret = -EINVAL;
-			goto register_error;
-		case LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE:
-			event_notifier->priv->parent.u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE;
+		break;
+
+	case LTTNG_KERNEL_ABI_SYSCALL:
+		ret = lttng_syscall_filter_disable_event(event);
+		break;
+
+	case LTTNG_KERNEL_ABI_NOOP:
+		switch (event->type) {
+		case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+			ret = 0;
 			break;
-		case LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT:
-			event_notifier->priv->parent.u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT;
+		case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+			WARN_ON_ONCE(1);
 			break;
 		}
-
-		if (!event_notifier->priv->parent.desc) {
-			ret = -EINVAL;
-			goto register_error;
-		}
-		break;
-
-	case LTTNG_KERNEL_ABI_UPROBE:
-		/*
-		 * Needs to be explicitly enabled after creation, since
-		 * we may want to apply filters.
-		 */
-		event_notifier->parent.enabled = 0;
-		event_notifier->priv->parent.registered = 1;
-
-		/*
-		 * Populate lttng_event_notifier structure before
-		 * event_notifier registration.
-		 */
-		smp_wmb();
-
-		ret = lttng_uprobes_register_event_notifier(
-				event_notifier_param->event.name,
-				event_notifier_param->event.u.uprobe.fd,
-				event_notifier);
-		if (ret)
-			goto register_error;
-		ret = try_module_get(event_notifier->priv->parent.desc->owner);
-		WARN_ON_ONCE(!ret);
-		break;
-
-	case LTTNG_KERNEL_ABI_KRETPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_FUNCTION:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_NOOP:
-		lttng_fallthrough;
-	default:
-		WARN_ON_ONCE(1);
-		ret = -EINVAL;
-		goto register_error;
-	}
-
-	list_add(&event_notifier->priv->node, &event_notifier_group->event_notifiers_head);
-	hlist_add_head(&event_notifier->priv->hlist, head);
-
-	/*
-	 * Clear the error counter bucket. The sessiond keeps track of which
-	 * bucket is currently in use. We trust it. The session lock
-	 * synchronizes against concurrent creation of the error
-	 * counter.
-	 */
-	error_counter = event_notifier_group->error_counter;
-	if (error_counter) {
-		size_t dimension_index[1];
-
-		/*
-		 * Check that the index is within the boundary of the counter.
-		 */
-		if (event_notifier->priv->error_counter_index >= event_notifier_group->error_counter_len) {
-			printk(KERN_INFO "LTTng: event_notifier: Error counter index out-of-bound: counter-len=%zu, index=%llu\n",
-				event_notifier_group->error_counter_len, event_notifier->priv->error_counter_index);
-			ret = -EINVAL;
-			goto register_error;
-		}
-
-		dimension_index[0] = event_notifier->priv->error_counter_index;
-		ret = error_counter->ops->counter_clear(error_counter->counter, dimension_index);
-		if (ret) {
-			printk(KERN_INFO "LTTng: event_notifier: Unable to clear error counter bucket %llu\n",
-				event_notifier->priv->error_counter_index);
-			goto register_error;
-		}
-	}
-
-	return event_notifier;
-
-register_error:
-	kmem_cache_free(event_notifier_private_cache, event_notifier_priv);
-cache_private_error:
-	kmem_cache_free(event_notifier_cache, event_notifier);
-cache_error:
-exist:
-type_error:
-	return ERR_PTR(ret);
-}
-
-int lttng_kernel_counter_read(struct lttng_counter *counter,
-		const size_t *dim_indexes, int32_t cpu,
-		int64_t *val, bool *overflow, bool *underflow)
-{
-	return counter->ops->counter_read(counter->counter, dim_indexes,
-			cpu, val, overflow, underflow);
-}
-
-int lttng_kernel_counter_aggregate(struct lttng_counter *counter,
-		const size_t *dim_indexes, int64_t *val,
-		bool *overflow, bool *underflow)
-{
-	return counter->ops->counter_aggregate(counter->counter, dim_indexes,
-			val, overflow, underflow);
-}
-
-int lttng_kernel_counter_clear(struct lttng_counter *counter,
-		const size_t *dim_indexes)
-{
-	return counter->ops->counter_clear(counter->counter, dim_indexes);
-}
-
-struct lttng_kernel_event_recorder *lttng_kernel_event_recorder_create(struct lttng_kernel_channel_buffer *chan,
-				struct lttng_kernel_abi_event *event_param,
-				const struct lttng_kernel_event_desc *event_desc,
-				enum lttng_kernel_abi_instrumentation itype)
-{
-	struct lttng_kernel_event_recorder *event;
-
-	mutex_lock(&sessions_mutex);
-	event = _lttng_kernel_event_recorder_create(chan, event_param, event_desc, itype);
-	mutex_unlock(&sessions_mutex);
-	return event;
-}
-
-struct lttng_kernel_event_notifier *lttng_event_notifier_create(
-		const struct lttng_kernel_event_desc *event_desc,
-		uint64_t id, uint64_t error_counter_index,
-		struct lttng_event_notifier_group *event_notifier_group,
-		struct lttng_kernel_abi_event_notifier *event_notifier_param,
-		enum lttng_kernel_abi_instrumentation itype)
-{
-	struct lttng_kernel_event_notifier *event_notifier;
-
-	mutex_lock(&sessions_mutex);
-	event_notifier = _lttng_event_notifier_create(event_desc, id,
-		error_counter_index, event_notifier_group,
-		event_notifier_param, itype);
-	mutex_unlock(&sessions_mutex);
-	return event_notifier;
-}
-
-/* Only used for tracepoints for now. */
-static
-void register_event(struct lttng_kernel_event_recorder *event_recorder)
-{
-	const struct lttng_kernel_event_desc *desc;
-	int ret = -EINVAL;
-
-	WARN_ON_ONCE(event_recorder->priv->parent.registered);
-
-	desc = event_recorder->priv->parent.desc;
-	switch (event_recorder->priv->parent.instrumentation) {
-	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		ret = lttng_wrapper_tracepoint_probe_register(desc->event_kname,
-						  desc->tp_class->probe_callback,
-						  event_recorder);
-		break;
-
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		ret = lttng_syscall_filter_enable_event(event_recorder->chan, event_recorder);
-		break;
-
-	case LTTNG_KERNEL_ABI_KPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_UPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_KRETPROBE:
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_FUNCTION:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_NOOP:
-		lttng_fallthrough;
-	default:
-		WARN_ON_ONCE(1);
-	}
-	if (!ret)
-		event_recorder->priv->parent.registered = 1;
-}
-
-/*
- * Only used internally at session destruction.
- */
-static
-void unregister_event(struct lttng_kernel_event_recorder *event_recorder)
-{
-	struct lttng_kernel_event_common_private *event_priv = &event_recorder->priv->parent;
-	const struct lttng_kernel_event_desc *desc;
-	int ret = -EINVAL;
-
-	WARN_ON_ONCE(!event_priv->registered);
-
-	desc = event_priv->desc;
-	switch (event_priv->instrumentation) {
-	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		ret = lttng_wrapper_tracepoint_probe_unregister(event_priv->desc->event_kname,
-						  event_priv->desc->tp_class->probe_callback,
-						  event_recorder);
-		break;
-
-	case LTTNG_KERNEL_ABI_KPROBE:
-		lttng_kprobes_unregister_event(event_recorder);
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_KRETPROBE:
-		lttng_kretprobes_unregister(event_recorder);
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		ret = lttng_syscall_filter_disable_event(event_recorder->chan, event_recorder);
-		break;
-
-	case LTTNG_KERNEL_ABI_NOOP:
-		ret = 0;
-		break;
+		break;
 
 	case LTTNG_KERNEL_ABI_UPROBE:
-		lttng_uprobes_unregister_event(event_recorder);
+		lttng_uprobes_unregister_event(event);
 		ret = 0;
 		break;
 
@@ -1521,101 +1450,10 @@ void unregister_event(struct lttng_kernel_event_recorder *event_recorder)
 }
 
 static
-void _lttng_event_unregister(struct lttng_kernel_event_recorder *event_recorder)
-{
-	if (event_recorder->priv->parent.registered)
-		unregister_event(event_recorder);
-}
-
-/* Only used for tracepoints for now. */
-static
-void register_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
-{
-	const struct lttng_kernel_event_desc *desc;
-	int ret = -EINVAL;
-
-	WARN_ON_ONCE(event_notifier->priv->parent.registered);
-
-	desc = event_notifier->priv->parent.desc;
-	switch (event_notifier->priv->parent.instrumentation) {
-	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		ret = lttng_wrapper_tracepoint_probe_register(desc->event_kname,
-						  desc->tp_class->probe_callback,
-						  event_notifier);
-		break;
-
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		ret = lttng_syscall_filter_enable_event_notifier(event_notifier);
-		break;
-
-	case LTTNG_KERNEL_ABI_KPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_UPROBE:
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_KRETPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_FUNCTION:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_NOOP:
-		lttng_fallthrough;
-	default:
-		WARN_ON_ONCE(1);
-	}
-	if (!ret)
-		event_notifier->priv->parent.registered = 1;
-}
-
-static
-int unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
-{
-	const struct lttng_kernel_event_desc *desc;
-	int ret = -EINVAL;
-
-	WARN_ON_ONCE(!event_notifier->priv->parent.registered);
-
-	desc = event_notifier->priv->parent.desc;
-	switch (event_notifier->priv->parent.instrumentation) {
-	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		ret = lttng_wrapper_tracepoint_probe_unregister(event_notifier->priv->parent.desc->event_kname,
-						  event_notifier->priv->parent.desc->tp_class->probe_callback,
-						  event_notifier);
-		break;
-
-	case LTTNG_KERNEL_ABI_KPROBE:
-		lttng_kprobes_unregister_event_notifier(event_notifier);
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_UPROBE:
-		lttng_uprobes_unregister_event_notifier(event_notifier);
-		ret = 0;
-		break;
-
-	case LTTNG_KERNEL_ABI_SYSCALL:
-		ret = lttng_syscall_filter_disable_event_notifier(event_notifier);
-		break;
-
-	case LTTNG_KERNEL_ABI_KRETPROBE:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_FUNCTION:
-		lttng_fallthrough;
-	case LTTNG_KERNEL_ABI_NOOP:
-		lttng_fallthrough;
-	default:
-		WARN_ON_ONCE(1);
-	}
-	if (!ret)
-		event_notifier->priv->parent.registered = 0;
-	return ret;
-}
-
-static
-void _lttng_event_notifier_unregister(struct lttng_kernel_event_notifier *event_notifier)
+void _lttng_event_unregister(struct lttng_kernel_event_common *event)
 {
-	if (event_notifier->priv->parent.registered)
-		unregister_event_notifier(event_notifier);
+	if (event->priv->registered)
+		unregister_event(event);
 }
 
 /*
@@ -1646,12 +1484,12 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 
 		case LTTNG_KERNEL_ABI_KPROBE:
 			module_put(event_priv->desc->owner);
-			lttng_kprobes_destroy_event_private(event_recorder);
+			lttng_kprobes_destroy_event_private(&event_recorder->parent);
 			break;
 
 		case LTTNG_KERNEL_ABI_KRETPROBE:
 			module_put(event_priv->desc->owner);
-			lttng_kretprobes_destroy_private(event_recorder);
+			lttng_kretprobes_destroy_private(&event_recorder->parent);
 			break;
 
 		case LTTNG_KERNEL_ABI_SYSCALL:
@@ -1659,7 +1497,7 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 
 		case LTTNG_KERNEL_ABI_UPROBE:
 			module_put(event_priv->desc->owner);
-			lttng_uprobes_destroy_event_private(event_recorder);
+			lttng_uprobes_destroy_event_private(&event_recorder->parent);
 			break;
 
 		case LTTNG_KERNEL_ABI_FUNCTION:
@@ -1669,7 +1507,7 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 		default:
 			WARN_ON_ONCE(1);
 		}
-		list_del(&event_recorder->priv->node);
+		list_del(&event_recorder->priv->parent.node);
 		kmem_cache_free(event_recorder_private_cache, event_recorder->priv);
 		kmem_cache_free(event_recorder_cache, event_recorder);
 		break;
@@ -1686,7 +1524,7 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 
 		case LTTNG_KERNEL_ABI_KPROBE:
 			module_put(event_notifier->priv->parent.desc->owner);
-			lttng_kprobes_destroy_event_notifier_private(event_notifier);
+			lttng_kprobes_destroy_event_private(&event_notifier->parent);
 			break;
 
 		case LTTNG_KERNEL_ABI_SYSCALL:
@@ -1694,7 +1532,7 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 
 		case LTTNG_KERNEL_ABI_UPROBE:
 			module_put(event_notifier->priv->parent.desc->owner);
-			lttng_uprobes_destroy_event_notifier_private(event_notifier);
+			lttng_uprobes_destroy_event_private(&event_notifier->parent);
 			break;
 
 		case LTTNG_KERNEL_ABI_KRETPROBE:
@@ -1706,7 +1544,7 @@ void _lttng_event_destroy(struct lttng_kernel_event_common *event)
 		default:
 			WARN_ON_ONCE(1);
 		}
-		list_del(&event_notifier->priv->node);
+		list_del(&event_notifier->priv->parent.node);
 		kmem_cache_free(event_notifier_private_cache, event_notifier->priv);
 		kmem_cache_free(event_notifier_cache, event_notifier);
 		break;
@@ -1991,8 +1829,9 @@ int lttng_match_enabler_name(const char *desc_name,
 	return 1;
 }
 
-int lttng_desc_match_enabler(const struct lttng_kernel_event_desc *desc,
-		struct lttng_enabler *enabler)
+static
+int lttng_desc_match_enabler_check(const struct lttng_kernel_event_desc *desc,
+		struct lttng_event_enabler_common *enabler)
 {
 	const char *desc_name, *enabler_name;
 	bool compat = false, entry = false;
@@ -2080,43 +1919,144 @@ int lttng_desc_match_enabler(const struct lttng_kernel_event_desc *desc,
 	}
 }
 
-static
-int lttng_event_enabler_match_event(struct lttng_event_enabler *event_enabler,
-		struct lttng_kernel_event_recorder *event_recorder)
+bool lttng_desc_match_enabler(const struct lttng_kernel_event_desc *desc,
+		struct lttng_event_enabler_common *enabler)
 {
-	struct lttng_enabler *base_enabler = lttng_event_enabler_as_enabler(
-		event_enabler);
+	int ret;
 
-	if (base_enabler->event_param.instrumentation != event_recorder->priv->parent.instrumentation)
-		return 0;
-	if (lttng_desc_match_enabler(event_recorder->priv->parent.desc, base_enabler)
-			&& event_recorder->chan == event_enabler->chan)
-		return 1;
-	else
-		return 0;
+	ret = lttng_desc_match_enabler_check(desc, enabler);
+	if (ret < 0) {
+		WARN_ON_ONCE(1);
+		return false;
+	}
+	return ret;
 }
 
-static
-int lttng_event_notifier_enabler_match_event_notifier(struct lttng_event_notifier_enabler *event_notifier_enabler,
-		struct lttng_kernel_event_notifier *event_notifier)
+bool lttng_event_enabler_match_event(struct lttng_event_enabler_common *event_enabler,
+		struct lttng_kernel_event_common *event)
 {
-	struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
-		event_notifier_enabler);
+	if (event_enabler->event_param.instrumentation != event->priv->instrumentation)
+		return false;
 
-	if (base_enabler->event_param.instrumentation != event_notifier->priv->parent.instrumentation)
-		return 0;
-	if (lttng_desc_match_enabler(event_notifier->priv->parent.desc, base_enabler)
-			&& event_notifier->priv->group == event_notifier_enabler->group
-			&& event_notifier->priv->parent.user_token == event_notifier_enabler->base.user_token)
-		return 1;
-	else
-		return 0;
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+
+		if (lttng_desc_match_enabler(event->priv->desc, event_enabler)
+				&& event_recorder->chan == event_recorder_enabler->chan)
+			return true;
+		else
+			return false;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+
+		if (lttng_desc_match_enabler(event->priv->desc, event_enabler)
+				&& event_notifier->priv->group == event_notifier_enabler->group
+				&& event->priv->user_token == event_enabler->user_token)
+			return true;
+		else
+			return false;
+	}
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+}
+
+bool lttng_event_enabler_desc_match_event(struct lttng_event_enabler_common *event_enabler,
+		const struct lttng_kernel_event_desc *desc,
+		struct lttng_kernel_event_common *event)
+{
+	if (event_enabler->event_param.instrumentation != event->priv->instrumentation)
+		return false;
+
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+
+		if (event->priv->desc == desc && event_recorder->chan == event_recorder_enabler->chan)
+			return true;
+		else
+			return false;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+
+		if (event->priv->desc == desc
+				&& event_notifier->priv->group == event_notifier_enabler->group
+				&& event->priv->user_token == event_enabler->user_token)
+			return true;
+		else
+			return false;
+	}
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+}
+
+bool lttng_event_enabler_event_name_match_event(struct lttng_event_enabler_common *event_enabler,
+		const char *event_name,
+		struct lttng_kernel_event_common *event)
+{
+	if (event_enabler->event_param.instrumentation != event->priv->instrumentation)
+		return false;
+
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+
+		if (!strncmp(event->priv->desc->event_name, event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1)
+				&& event_recorder->chan == event_recorder_enabler->chan)
+			return true;
+		else
+			return false;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+
+		if (!strncmp(event->priv->desc->event_name, event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1)
+				&& event_notifier->priv->group == event_notifier_enabler->group
+				&& event->priv->user_token == event_enabler->user_token)
+			return true;
+		else
+			return false;
+	}
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
 }
 
 static
 struct lttng_enabler_ref *lttng_enabler_ref(
 		struct list_head *enablers_ref_list,
-		struct lttng_enabler *enabler)
+		struct lttng_event_enabler_common *enabler)
 {
 	struct lttng_enabler_ref *enabler_ref;
 
@@ -2128,238 +2068,73 @@ struct lttng_enabler_ref *lttng_enabler_ref(
 }
 
 static
-void lttng_create_tracepoint_event_if_missing(struct lttng_event_enabler *event_enabler)
+void lttng_event_enabler_create_tracepoint_events_if_missing(struct lttng_event_enabler_common *event_enabler)
 {
-	struct lttng_kernel_session *session = event_enabler->chan->parent.session;
+	struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(event_enabler);
 	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 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_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_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->chan,
-					NULL, desc, LTTNG_KERNEL_ABI_TRACEPOINT);
-			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
+	 * our enabler, create an associated lttng_event 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;
+			bool found = false;
 			struct hlist_head *head;
-			struct lttng_kernel_event_notifier_private *event_notifier_priv;
-			struct lttng_kernel_event_notifier *event_notifier;
+			struct lttng_kernel_event_common *event;
+			struct lttng_kernel_event_common_private *event_priv;
 
 			desc = probe_desc->event_desc[i];
-			if (!lttng_desc_match_enabler(desc,
-					lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
+			if (!lttng_desc_match_enabler(desc, event_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->base.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->base.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);
+			head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
+			lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
+				if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) {
+					found = true;
+					break;
+				}
 			}
-		}
-	}
-}
-
-static
-void lttng_create_syscall_event_if_missing(struct lttng_event_enabler *event_enabler)
-{
-	int ret;
-
-	ret = lttng_syscalls_register_event(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_enabler *event_enabler)
-{
-	switch (event_enabler->base.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_enabler *event_enabler)
-{
-	struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
-	struct lttng_kernel_session *session = event_enabler->chan->parent.session;
-	struct lttng_enabler *base_enabler = lttng_event_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_all_entry, enabled);
-
-		if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
-			WRITE_ONCE(chan->priv->parent.syscall_all_exit, enabled);
-	}
-
-	/* First ensure that probe events are created for this enabler. */
-	lttng_create_event_if_missing(event_enabler);
-
-	/* For each event matching event_enabler in session event list. */
-	list_for_each_entry(event_recorder_priv, &session->priv->events, node) {
-		struct lttng_kernel_event_recorder *event_recorder = event_recorder_priv->pub;
-		struct lttng_enabler_ref *enabler_ref;
+			if (found)
+				continue;
 
-		if (!lttng_event_enabler_match_event(event_enabler, event_recorder))
-			continue;
-		enabler_ref = lttng_enabler_ref(&event_recorder_priv->parent.enablers_ref_head,
-			lttng_event_enabler_as_enabler(event_enabler));
-		if (!enabler_ref) {
 			/*
-			 * If no backward ref, create it.
-			 * Add backward ref from event to event_enabler.
+			 * We need to create an event for this event probe.
 			 */
-			enabler_ref = kzalloc(sizeof(*enabler_ref), GFP_KERNEL);
-			if (!enabler_ref)
-				return -ENOMEM;
-			enabler_ref->ref = lttng_event_enabler_as_enabler(event_enabler);
-			list_add(&enabler_ref->node,
-				&event_recorder_priv->parent.enablers_ref_head);
+			event = _lttng_kernel_event_create(event_enabler, desc);
+			if (IS_ERR(event)) {
+				printk(KERN_INFO "LTTng: Unable to create event %s\n",
+					probe_desc->event_desc[i]->event_name);
+			}
 		}
-
-		/*
-		 * Link filter bytecodes if not linked yet.
-		 */
-		lttng_enabler_link_bytecode(event_recorder_priv->parent.desc,
-			lttng_static_ctx,
-			&event_recorder_priv->parent.filter_bytecode_runtime_head,
-			&lttng_event_enabler_as_enabler(event_enabler)->filter_bytecode_head);
 	}
-	return 0;
 }
 
 /*
- * Create struct lttng_kernel_event_notifier if it is missing and present in the list of
- * tracepoint probes.
+ * Create event if it is missing and present in the list of tracepoint probes.
  * Should be called with sessions mutex held.
  */
 static
-void lttng_create_event_notifier_if_missing(struct lttng_event_notifier_enabler *event_notifier_enabler)
+void lttng_event_enabler_create_events_if_missing(struct lttng_event_enabler_common *event_enabler)
 {
-	switch (event_notifier_enabler->base.event_param.instrumentation) {
+	int ret;
+
+	switch (event_enabler->event_param.instrumentation) {
 	case LTTNG_KERNEL_ABI_TRACEPOINT:
-		lttng_create_tracepoint_event_notifier_if_missing(event_notifier_enabler);
+		lttng_event_enabler_create_tracepoint_events_if_missing(event_enabler);
 		break;
 
 	case LTTNG_KERNEL_ABI_SYSCALL:
-		lttng_create_syscall_event_notifier_if_missing(event_notifier_enabler);
+		ret = lttng_event_enabler_create_syscall_events_if_missing(event_enabler);
+		WARN_ON_ONCE(ret);
 		break;
 
 	default:
@@ -2368,46 +2143,66 @@ void lttng_create_event_notifier_if_missing(struct lttng_event_notifier_enabler
 	}
 }
 
-/*
- * Create event_notifiers associated with a event_notifier enabler (if not already present).
- */
 static
-int lttng_event_notifier_enabler_ref_event_notifiers(
-		struct lttng_event_notifier_enabler *event_notifier_enabler)
+void lttng_event_enabler_init_event_filter(struct lttng_event_enabler_common *event_enabler,
+		struct lttng_kernel_event_common *event)
 {
-	struct lttng_event_notifier_group *event_notifier_group = event_notifier_enabler->group;
-	struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
-	struct lttng_kernel_event_notifier_private *event_notifier_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, "*")) {
+	/* Link filter bytecodes if not linked yet. */
+	lttng_enabler_link_bytecode(event->priv->desc, lttng_static_ctx,
+		&event->priv->filter_bytecode_runtime_head, &event_enabler->filter_bytecode_head);
+}
 
-		int enabled = base_enabler->enabled;
-		enum lttng_kernel_abi_syscall_entryexit entryexit = base_enabler->event_param.u.syscall.entryexit;
+static
+void lttng_event_enabler_init_event_capture(struct lttng_event_enabler_common *event_enabler,
+		struct lttng_kernel_event_common *event)
+{
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+		break;
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
 
-		if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
-			WRITE_ONCE(event_notifier_group->syscall_all_entry, enabled);
+		/* Link capture bytecodes if not linked yet. */
+		lttng_enabler_link_bytecode(event->priv->desc,
+			lttng_static_ctx, &event_notifier->priv->capture_bytecode_runtime_head,
+			&event_notifier_enabler->capture_bytecode_head);
+		event_notifier->priv->num_captures = event_notifier_enabler->num_captures;
+		break;
+	}
+	default:
+		WARN_ON_ONCE(1);
+	}
+}
 
-		if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
-			WRITE_ONCE(event_notifier_group->syscall_all_exit, enabled);
+/*
+ * 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_enabler_common *event_enabler)
+{
+	struct list_head *event_list_head = lttng_get_event_list_head_from_enabler(event_enabler);
+	struct lttng_kernel_event_common_private *event_priv;
 
-	}
+	lttng_syscall_table_set_wildcard_all(event_enabler);
 
-	/* First ensure that probe event_notifiers are created for this enabler. */
-	lttng_create_event_notifier_if_missing(event_notifier_enabler);
+	/* First ensure that probe events are created for this enabler. */
+	lttng_event_enabler_create_events_if_missing(event_enabler);
 
-	/* Link the created event_notifier with its associated enabler. */
-	list_for_each_entry(event_notifier_priv, &event_notifier_group->event_notifiers_head, node) {
-		struct lttng_kernel_event_notifier *event_notifier = event_notifier_priv->pub;
+	/* Link the created event with its associated enabler. */
+	list_for_each_entry(event_priv, event_list_head, node) {
+		struct lttng_kernel_event_common *event = event_priv->pub;
 		struct lttng_enabler_ref *enabler_ref;
 
-		if (!lttng_event_notifier_enabler_match_event_notifier(event_notifier_enabler, event_notifier))
+		if (!lttng_event_enabler_match_event(event_enabler, event))
 			continue;
 
-		enabler_ref = lttng_enabler_ref(&event_notifier_priv->parent.enablers_ref_head,
-			lttng_event_notifier_enabler_as_enabler(event_notifier_enabler));
+		enabler_ref = lttng_enabler_ref(&event_priv->enablers_ref_head, event_enabler);
 		if (!enabler_ref) {
 			/*
 			 * If no backward ref, create it.
@@ -2417,25 +2212,12 @@ int lttng_event_notifier_enabler_ref_event_notifiers(
 			if (!enabler_ref)
 				return -ENOMEM;
 
-			enabler_ref->ref = lttng_event_notifier_enabler_as_enabler(
-				event_notifier_enabler);
-			list_add(&enabler_ref->node,
-				&event_notifier_priv->parent.enablers_ref_head);
+			enabler_ref->ref = event_enabler;
+			list_add(&enabler_ref->node, &event_priv->enablers_ref_head);
 		}
 
-		/*
-		 * Link filter bytecodes if not linked yet.
-		 */
-		lttng_enabler_link_bytecode(event_notifier_priv->parent.desc,
-			lttng_static_ctx, &event_notifier_priv->parent.filter_bytecode_runtime_head,
-			&lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)->filter_bytecode_head);
-
-		/* Link capture bytecodes if not linked yet. */
-		lttng_enabler_link_bytecode(event_notifier_priv->parent.desc,
-			lttng_static_ctx, &event_notifier_priv->capture_bytecode_runtime_head,
-			&event_notifier_enabler->capture_bytecode_head);
-
-		event_notifier_priv->num_captures = event_notifier_enabler->num_captures;
+		lttng_event_enabler_init_event_filter(event_enabler, event);
+		lttng_event_enabler_init_event_capture(event_enabler, event);
 	}
 	return 0;
 }
@@ -2457,11 +2239,10 @@ int lttng_fix_pending_events(void)
 static bool lttng_event_notifier_group_has_active_event_notifiers(
 		struct lttng_event_notifier_group *event_notifier_group)
 {
-	struct lttng_event_notifier_enabler *event_notifier_enabler;
+	struct lttng_event_enabler_common *event_enabler;
 
-	list_for_each_entry(event_notifier_enabler, &event_notifier_group->enablers_head,
-			node) {
-		if (event_notifier_enabler->base.enabled)
+	list_for_each_entry(event_enabler, &event_notifier_group->enablers_head, node) {
+		if (event_enabler->enabled)
 			return true;
 	}
 	return false;
@@ -2487,50 +2268,57 @@ int lttng_fix_pending_event_notifiers(void)
 	return 0;
 }
 
-struct lttng_event_enabler *lttng_event_enabler_create(
+struct lttng_event_recorder_enabler *lttng_event_recorder_enabler_create(
 		enum lttng_enabler_format_type format_type,
 		struct lttng_kernel_abi_event *event_param,
 		struct lttng_kernel_channel_buffer *chan)
 {
-	struct lttng_event_enabler *event_enabler;
+	struct lttng_event_recorder_enabler *event_enabler;
 
 	event_enabler = kzalloc(sizeof(*event_enabler), GFP_KERNEL);
 	if (!event_enabler)
 		return NULL;
-	event_enabler->base.format_type = format_type;
-	INIT_LIST_HEAD(&event_enabler->base.filter_bytecode_head);
-	memcpy(&event_enabler->base.event_param, event_param,
-		sizeof(event_enabler->base.event_param));
+	event_enabler->parent.enabler_type = LTTNG_EVENT_ENABLER_TYPE_RECORDER;
+	event_enabler->parent.format_type = format_type;
+	INIT_LIST_HEAD(&event_enabler->parent.filter_bytecode_head);
+	memcpy(&event_enabler->parent.event_param, event_param,
+		sizeof(event_enabler->parent.event_param));
 	event_enabler->chan = chan;
 	/* ctx left NULL */
-	event_enabler->base.enabled = 0;
+	event_enabler->parent.enabled = 0;
+	return event_enabler;
+}
+
+void lttng_event_enabler_session_add(struct lttng_kernel_session *session,
+		struct lttng_event_recorder_enabler *event_enabler)
+{
 	mutex_lock(&sessions_mutex);
-	list_add(&event_enabler->node, &event_enabler->chan->parent.session->priv->enablers_head);
-	lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent.session);
+	list_add(&event_enabler->parent.node, &session->priv->enablers_head);
+	event_enabler->parent.published = true;
+	lttng_session_lazy_sync_event_enablers(session);
 	mutex_unlock(&sessions_mutex);
-	return event_enabler;
 }
 
-int lttng_event_enabler_enable(struct lttng_event_enabler *event_enabler)
+int lttng_event_enabler_enable(struct lttng_event_enabler_common *event_enabler)
 {
 	mutex_lock(&sessions_mutex);
-	lttng_event_enabler_as_enabler(event_enabler)->enabled = 1;
-	lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent.session);
+	event_enabler->enabled = 1;
+	lttng_event_enabler_sync(event_enabler);
 	mutex_unlock(&sessions_mutex);
 	return 0;
 }
 
-int lttng_event_enabler_disable(struct lttng_event_enabler *event_enabler)
+int lttng_event_enabler_disable(struct lttng_event_enabler_common *event_enabler)
 {
 	mutex_lock(&sessions_mutex);
-	lttng_event_enabler_as_enabler(event_enabler)->enabled = 0;
-	lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent.session);
+	event_enabler->enabled = 0;
+	lttng_event_enabler_sync(event_enabler);
 	mutex_unlock(&sessions_mutex);
 	return 0;
 }
 
 static
-int lttng_enabler_attach_filter_bytecode(struct lttng_enabler *enabler,
+int lttng_enabler_attach_filter_bytecode(struct lttng_event_enabler_common *enabler,
 		struct lttng_kernel_abi_filter_bytecode __user *bytecode)
 {
 	struct lttng_kernel_bytecode_node *bytecode_node;
@@ -2562,16 +2350,14 @@ error_free:
 	return ret;
 }
 
-int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler *event_enabler,
+int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler_common *event_enabler,
 		struct lttng_kernel_abi_filter_bytecode __user *bytecode)
 {
 	int ret;
-	ret = lttng_enabler_attach_filter_bytecode(
-		lttng_event_enabler_as_enabler(event_enabler), bytecode);
+	ret = lttng_enabler_attach_filter_bytecode(event_enabler, bytecode);
 	if (ret)
 		goto error;
-
-	lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent.session);
+	lttng_event_enabler_sync(event_enabler);
 	return 0;
 
 error:
@@ -2591,7 +2377,7 @@ int lttng_event_add_callsite(struct lttng_kernel_event_common *event,
 }
 
 static
-void lttng_enabler_destroy(struct lttng_enabler *enabler)
+void lttng_enabler_destroy(struct lttng_event_enabler_common *enabler)
 {
 	struct lttng_kernel_bytecode_node *filter_node, *tmp_filter_node;
 
@@ -2602,19 +2388,38 @@ void lttng_enabler_destroy(struct lttng_enabler *enabler)
 	}
 }
 
-static
-void lttng_event_enabler_destroy(struct lttng_event_enabler *event_enabler)
+void lttng_event_enabler_destroy(struct lttng_event_enabler_common *event_enabler)
 {
-	lttng_enabler_destroy(lttng_event_enabler_as_enabler(event_enabler));
+	lttng_enabler_destroy(event_enabler);
+	if (event_enabler->published)
+		list_del(&event_enabler->node);
+
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+
+		kfree(event_recorder_enabler);
+		break;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
 
-	list_del(&event_enabler->node);
-	kfree(event_enabler);
+		kfree(event_notifier_enabler);
+		break;
+	}
+	default:
+		WARN_ON_ONCE(1);
+	}
 }
 
 struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create(
-		struct lttng_event_notifier_group *event_notifier_group,
 		enum lttng_enabler_format_type format_type,
-		struct lttng_kernel_abi_event_notifier *event_notifier_param)
+		struct lttng_kernel_abi_event_notifier *event_notifier_param,
+		struct lttng_event_notifier_group *event_notifier_group)
 {
 	struct lttng_event_notifier_enabler *event_notifier_enabler;
 
@@ -2622,27 +2427,31 @@ struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create(
 	if (!event_notifier_enabler)
 		return NULL;
 
-	event_notifier_enabler->base.format_type = format_type;
-	INIT_LIST_HEAD(&event_notifier_enabler->base.filter_bytecode_head);
+	event_notifier_enabler->parent.enabler_type = LTTNG_EVENT_ENABLER_TYPE_NOTIFIER;
+	event_notifier_enabler->parent.format_type = format_type;
+	INIT_LIST_HEAD(&event_notifier_enabler->parent.filter_bytecode_head);
 	INIT_LIST_HEAD(&event_notifier_enabler->capture_bytecode_head);
 
 	event_notifier_enabler->error_counter_index = event_notifier_param->error_counter_index;
 	event_notifier_enabler->num_captures = 0;
 
-	memcpy(&event_notifier_enabler->base.event_param, &event_notifier_param->event,
-		sizeof(event_notifier_enabler->base.event_param));
+	memcpy(&event_notifier_enabler->parent.event_param, &event_notifier_param->event,
+		sizeof(event_notifier_enabler->parent.event_param));
 
-	event_notifier_enabler->base.enabled = 0;
-	event_notifier_enabler->base.user_token = event_notifier_param->event.token;
+	event_notifier_enabler->parent.enabled = 0;
+	event_notifier_enabler->parent.user_token = event_notifier_param->event.token;
 	event_notifier_enabler->group = event_notifier_group;
+	return event_notifier_enabler;
+}
 
+void lttng_event_notifier_enabler_group_add(struct lttng_event_notifier_group *event_notifier_group,
+		struct lttng_event_notifier_enabler *event_notifier_enabler)
+{
 	mutex_lock(&sessions_mutex);
-	list_add(&event_notifier_enabler->node, &event_notifier_enabler->group->enablers_head);
+	list_add(&event_notifier_enabler->parent.node, &event_notifier_enabler->group->enablers_head);
+	event_notifier_enabler->parent.published = true;
 	lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
-
 	mutex_unlock(&sessions_mutex);
-
-	return event_notifier_enabler;
 }
 
 int lttng_event_notifier_enabler_enable(
@@ -2665,31 +2474,12 @@ int lttng_event_notifier_enabler_disable(
 	return 0;
 }
 
-int lttng_event_notifier_enabler_attach_filter_bytecode(
-		struct lttng_event_notifier_enabler *event_notifier_enabler,
-		struct lttng_kernel_abi_filter_bytecode __user *bytecode)
-{
-	int ret;
-
-	ret = lttng_enabler_attach_filter_bytecode(
-		lttng_event_notifier_enabler_as_enabler(event_notifier_enabler),
-		bytecode);
-	if (ret)
-		goto error;
-
-	lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
-	return 0;
-
-error:
-	return ret;
-}
-
 int lttng_event_notifier_enabler_attach_capture_bytecode(
 		struct lttng_event_notifier_enabler *event_notifier_enabler,
 		struct lttng_kernel_abi_capture_bytecode __user *bytecode)
 {
 	struct lttng_kernel_bytecode_node *bytecode_node;
-	struct lttng_enabler *enabler =
+	struct lttng_event_enabler_common *enabler =
 			lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
 	uint32_t bytecode_len;
 	int ret;
@@ -2727,105 +2517,168 @@ end:
 }
 
 static
-void lttng_event_notifier_enabler_destroy(
-		struct lttng_event_notifier_enabler *event_notifier_enabler)
+void lttng_event_sync_filter_state(struct lttng_kernel_event_common *event)
 {
-	if (!event_notifier_enabler) {
-		return;
+	int has_enablers_without_filter_bytecode = 0, nr_filters = 0;
+	struct lttng_kernel_bytecode_runtime *runtime;
+	struct lttng_enabler_ref *enabler_ref;
+
+	/* Check if has enablers without bytecode enabled */
+	list_for_each_entry(enabler_ref, &event->priv->enablers_ref_head, node) {
+		if (enabler_ref->ref->enabled
+				&& list_empty(&enabler_ref->ref->filter_bytecode_head)) {
+			has_enablers_without_filter_bytecode = 1;
+			break;
+		}
+	}
+	event->priv->has_enablers_without_filter_bytecode = has_enablers_without_filter_bytecode;
+
+	/* Enable filters */
+	list_for_each_entry(runtime, &event->priv->filter_bytecode_runtime_head, node) {
+		lttng_bytecode_sync_state(runtime);
+		nr_filters++;
+	}
+	WRITE_ONCE(event->eval_filter, !(has_enablers_without_filter_bytecode || !nr_filters));
+}
+
+static
+void lttng_event_sync_capture_state(struct lttng_kernel_event_common *event)
+{
+	switch (event->type) {
+	case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+		break;
+	case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+	{
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+		struct lttng_kernel_bytecode_runtime *runtime;
+		int nr_captures = 0;
+
+		/* Enable captures */
+		list_for_each_entry(runtime, &event_notifier->priv->capture_bytecode_runtime_head, node) {
+			lttng_bytecode_sync_state(runtime);
+			nr_captures++;
+		}
+		WRITE_ONCE(event_notifier->eval_capture, !!nr_captures);
+		break;
+	}
+	default:
+		WARN_ON_ONCE(1);
+	}
+}
+
+static
+bool lttng_get_event_enabled_state(struct lttng_kernel_event_common *event)
+{
+	struct lttng_enabler_ref *enabler_ref;
+	bool enabled = false;
+
+	switch (event->priv->instrumentation) {
+	case LTTNG_KERNEL_ABI_TRACEPOINT:
+		lttng_fallthrough;
+	case LTTNG_KERNEL_ABI_SYSCALL:
+		/* Enable events */
+		list_for_each_entry(enabler_ref, &event->priv->enablers_ref_head, node) {
+			if (enabler_ref->ref->enabled) {
+				enabled = true;
+				break;
+			}
+		}
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
+	switch (event->type) {
+	case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+	{
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+
+		/*
+		 * Enabled state is based on union of enablers, with
+		 * intersection of session and channel transient enable
+		 * states.
+		 */
+		return enabled && event_recorder->chan->parent.session->priv->tstate && event_recorder->chan->priv->parent.tstate;
+	}
+	case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+		return enabled;
+	default:
+		WARN_ON_ONCE(1);
+		return false;
 	}
+}
 
-	list_del(&event_notifier_enabler->node);
+static
+bool lttng_event_is_lazy_sync(struct lttng_kernel_event_common *event)
+{
+	switch (event->priv->instrumentation) {
+	case LTTNG_KERNEL_ABI_TRACEPOINT:
+		lttng_fallthrough;
+	case LTTNG_KERNEL_ABI_SYSCALL:
+		return true;
 
-	lttng_enabler_destroy(lttng_event_notifier_enabler_as_enabler(event_notifier_enabler));
-	kfree(event_notifier_enabler);
+	default:
+		/* Not handled with lazy sync. */
+		return false;
+	}
 }
 
 /*
- * lttng_session_sync_event_enablers should be called just before starting a
- * session.
  * Should be called with sessions mutex held.
  */
 static
-void lttng_session_sync_event_enablers(struct lttng_kernel_session *session)
+void lttng_sync_event_list(struct list_head *event_enabler_list,
+		struct list_head *event_list)
 {
-	struct lttng_event_enabler *event_enabler;
-	struct lttng_kernel_event_recorder_private *event_recorder_priv;
+	struct lttng_kernel_event_common_private *event_priv;
+	struct lttng_event_enabler_common *event_enabler;
 
-	list_for_each_entry(event_enabler, &session->priv->enablers_head, node)
+	list_for_each_entry(event_enabler, event_enabler_list, node)
 		lttng_event_enabler_ref_events(event_enabler);
+
 	/*
 	 * For each event, if at least one of its enablers is enabled,
 	 * and its channel and session transient states are enabled, we
 	 * enable the event, else we disable it.
 	 */
-	list_for_each_entry(event_recorder_priv, &session->priv->events, node) {
-		struct lttng_kernel_event_recorder *event_recorder = event_recorder_priv->pub;
-		struct lttng_enabler_ref *enabler_ref;
-		struct lttng_kernel_bytecode_runtime *runtime;
-		int enabled = 0, has_enablers_without_filter_bytecode = 0;
-		int nr_filters = 0;
-
-		switch (event_recorder_priv->parent.instrumentation) {
-		case LTTNG_KERNEL_ABI_TRACEPOINT:
-			lttng_fallthrough;
-		case LTTNG_KERNEL_ABI_SYSCALL:
-			/* Enable events */
-			list_for_each_entry(enabler_ref,
-					&event_recorder_priv->parent.enablers_ref_head, node) {
-				if (enabler_ref->ref->enabled) {
-					enabled = 1;
-					break;
-				}
-			}
-			break;
+	list_for_each_entry(event_priv, event_list, node) {
+		struct lttng_kernel_event_common *event = event_priv->pub;
+		bool enabled;
 
-		default:
-			/* Not handled with lazy sync. */
+		if (!lttng_event_is_lazy_sync(event))
 			continue;
-		}
-		/*
-		 * Enabled state is based on union of enablers, with
-		 * intesection of session and channel transient enable
-		 * states.
-		 */
-		enabled = enabled && session->priv->tstate && event_recorder->chan->priv->parent.tstate;
 
-		WRITE_ONCE(event_recorder->parent.enabled, enabled);
+		enabled = lttng_get_event_enabled_state(event);
+		WRITE_ONCE(event->enabled, enabled);
 		/*
-		 * Sync tracepoint registration with event enabled
-		 * state.
+		 * Sync tracepoint registration with event enabled state.
 		 */
 		if (enabled) {
-			if (!event_recorder_priv->parent.registered)
-				register_event(event_recorder);
+			if (!event_priv->registered)
+				register_event(event);
 		} else {
-			if (event_recorder_priv->parent.registered)
-				_lttng_event_unregister(event_recorder);
-		}
-
-		/* Check if has enablers without bytecode enabled */
-		list_for_each_entry(enabler_ref,
-				&event_recorder_priv->parent.enablers_ref_head, node) {
-			if (enabler_ref->ref->enabled
-					&& list_empty(&enabler_ref->ref->filter_bytecode_head)) {
-				has_enablers_without_filter_bytecode = 1;
-				break;
-			}
+			if (event_priv->registered)
+				unregister_event(event);
 		}
-		event_recorder_priv->parent.has_enablers_without_filter_bytecode =
-			has_enablers_without_filter_bytecode;
 
-		/* Enable filters */
-		list_for_each_entry(runtime,
-				&event_recorder_priv->parent.filter_bytecode_runtime_head, node) {
-			lttng_bytecode_sync_state(runtime);
-			nr_filters++;
-		}
-		WRITE_ONCE(event_recorder_priv->parent.pub->eval_filter,
-			!(has_enablers_without_filter_bytecode || !nr_filters));
+		lttng_event_sync_filter_state(event);
+		lttng_event_sync_capture_state(event);
 	}
 }
 
+/*
+ * lttng_session_sync_event_enablers should be called just before starting a
+ * session.
+ */
+static
+void lttng_session_sync_event_enablers(struct lttng_kernel_session *session)
+{
+	lttng_sync_event_list(&session->priv->enablers_head, &session->priv->events);
+}
+
 /*
  * Apply enablers to session events, adding events to session if need
  * be. It is required after each modification applied to an active
@@ -2845,83 +2698,29 @@ void lttng_session_lazy_sync_event_enablers(struct lttng_kernel_session *session
 static
 void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group *event_notifier_group)
 {
-	struct lttng_event_notifier_enabler *event_notifier_enabler;
-	struct lttng_kernel_event_notifier_private *event_notifier_priv;
-
-	list_for_each_entry(event_notifier_enabler, &event_notifier_group->enablers_head, node)
-		lttng_event_notifier_enabler_ref_event_notifiers(event_notifier_enabler);
-
-	/*
-	 * For each event_notifier, if at least one of its enablers is enabled,
-	 * we enable the event_notifier, else we disable it.
-	 */
-	list_for_each_entry(event_notifier_priv, &event_notifier_group->event_notifiers_head, node) {
-		struct lttng_kernel_event_notifier *event_notifier = event_notifier_priv->pub;
-		struct lttng_enabler_ref *enabler_ref;
-		struct lttng_kernel_bytecode_runtime *runtime;
-		int enabled = 0, has_enablers_without_filter_bytecode = 0;
-		int nr_filters = 0, nr_captures = 0;
-
-		switch (event_notifier_priv->parent.instrumentation) {
-		case LTTNG_KERNEL_ABI_TRACEPOINT:
-			lttng_fallthrough;
-		case LTTNG_KERNEL_ABI_SYSCALL:
-			/* Enable event_notifiers */
-			list_for_each_entry(enabler_ref,
-					&event_notifier_priv->parent.enablers_ref_head, node) {
-				if (enabler_ref->ref->enabled) {
-					enabled = 1;
-					break;
-				}
-			}
-			break;
-
-		default:
-			/* Not handled with sync. */
-			continue;
-		}
-
-		WRITE_ONCE(event_notifier->parent.enabled, enabled);
-		/*
-		 * Sync tracepoint registration with event_notifier enabled
-		 * state.
-		 */
-		if (enabled) {
-			if (!event_notifier_priv->parent.registered)
-				register_event_notifier(event_notifier);
-		} else {
-			if (event_notifier_priv->parent.registered)
-				unregister_event_notifier(event_notifier);
-		}
-
-		/* Check if has enablers without bytecode enabled */
-		list_for_each_entry(enabler_ref,
-				&event_notifier_priv->parent.enablers_ref_head, node) {
-			if (enabler_ref->ref->enabled
-					&& list_empty(&enabler_ref->ref->filter_bytecode_head)) {
-				has_enablers_without_filter_bytecode = 1;
-				break;
-			}
-		}
-		event_notifier_priv->parent.has_enablers_without_filter_bytecode =
-			has_enablers_without_filter_bytecode;
-
-		/* Enable filters */
-		list_for_each_entry(runtime,
-				&event_notifier_priv->parent.filter_bytecode_runtime_head, node) {
-			lttng_bytecode_sync_state(runtime);
-			nr_filters++;
-		}
-		WRITE_ONCE(event_notifier_priv->parent.pub->eval_filter,
-			!(has_enablers_without_filter_bytecode || !nr_filters));
+	lttng_sync_event_list(&event_notifier_group->enablers_head, &event_notifier_group->event_notifiers_head);
+}
 
-		/* Enable captures */
-		list_for_each_entry(runtime,
-				&event_notifier_priv->capture_bytecode_runtime_head, node) {
-			lttng_bytecode_sync_state(runtime);
-			nr_captures++;
-		}
-		WRITE_ONCE(event_notifier->eval_capture, !!nr_captures);
+static
+void lttng_event_enabler_sync(struct lttng_event_enabler_common *event_enabler)
+{
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		lttng_session_lazy_sync_event_enablers(event_recorder_enabler->chan->parent.session);
+		break;
+	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
+		break;
+	}
+	default:
+		WARN_ON_ONCE(1);
 	}
 }
 
@@ -3694,12 +3493,19 @@ int _lttng_fields_metadata_statedump(struct lttng_kernel_session *session,
  * transaction.
  */
 static
-int _lttng_event_metadata_statedump(struct lttng_kernel_session *session,
-				  struct lttng_kernel_channel_buffer *chan,
-				  struct lttng_kernel_event_recorder *event_recorder)
+int _lttng_event_recorder_metadata_statedump(struct lttng_kernel_event_common *event)
 {
+	struct lttng_kernel_event_recorder *event_recorder;
+	struct lttng_kernel_channel_buffer *chan;
+	struct lttng_kernel_session *session;
 	int ret = 0;
 
+	if (event->type != LTTNG_KERNEL_EVENT_TYPE_RECORDER)
+		return 0;
+	event_recorder = container_of(event, struct lttng_kernel_event_recorder, parent);
+	chan = event_recorder->chan;
+	session = chan->parent.session;
+
 	if (event_recorder->priv->metadata_dumped || !LTTNG_READ_ONCE(session->active))
 		return 0;
 	if (chan->priv->channel_type == METADATA_CHANNEL)
@@ -4153,9 +3959,8 @@ skip_session:
 			goto end;
 	}
 
-	list_for_each_entry(event_recorder_priv, &session->priv->events, node) {
-		ret = _lttng_event_metadata_statedump(session, event_recorder_priv->pub->chan,
-				event_recorder_priv->pub);
+	list_for_each_entry(event_recorder_priv, &session->priv->events, parent.node) {
+		ret = _lttng_event_recorder_metadata_statedump(&event_recorder_priv->pub->parent);
 		if (ret)
 			goto end;
 	}
diff --git a/src/lttng-syscalls.c b/src/lttng-syscalls.c
index d74851b..e8b7257 100644
--- a/src/lttng-syscalls.c
+++ b/src/lttng-syscalls.c
@@ -66,11 +66,6 @@ enum sc_type {
 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
 
-void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
-		long id);
-void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
-		long ret);
-
 /*
  * Forward declarations for old kernels.
  */
@@ -266,33 +261,33 @@ void syscall_entry_event_call_func(struct hlist_head *action_list,
 
 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
 {
-	struct lttng_kernel_channel_buffer *chan = __data;
+	struct lttng_kernel_syscall_table *syscall_table = __data;
 	struct hlist_head *action_list, *unknown_action_list;
 	const struct trace_syscall_entry *table, *entry;
 	size_t table_len;
 
 	if (unlikely(in_compat_syscall())) {
-		struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
+		struct lttng_syscall_filter *filter = syscall_table->sc_filter;
 
 		if (id < 0 || id >= NR_compat_syscalls
-			|| (!READ_ONCE(chan->priv->parent.syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
+			|| (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
 			/* System call filtered out. */
 			return;
 		}
 		table = compat_sc_table.table;
 		table_len = compat_sc_table.len;
-		unknown_action_list = &chan->priv->parent.sc_compat_unknown;
+		unknown_action_list = &syscall_table->compat_unknown_syscall_dispatch;
 	} else {
-		struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
+		struct lttng_syscall_filter *filter = syscall_table->sc_filter;
 
 		if (id < 0 || id >= NR_syscalls
-			|| (!READ_ONCE(chan->priv->parent.syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
+			|| (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
 			/* System call filtered out. */
 			return;
 		}
 		table = sc_table.table;
 		table_len = sc_table.len;
-		unknown_action_list = &chan->priv->parent.sc_unknown;
+		unknown_action_list = &syscall_table->unknown_syscall_dispatch;
 	}
 	if (unlikely(id < 0 || id >= table_len)) {
 		syscall_entry_event_unknown(unknown_action_list, regs, id);
@@ -306,9 +301,9 @@ void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
 	}
 
 	if (unlikely(in_compat_syscall())) {
-		action_list = &chan->priv->parent.compat_sc_table[id];
+		action_list = &syscall_table->compat_syscall_dispatch[id];
 	} else {
-		action_list = &chan->priv->parent.sc_table[id];
+		action_list = &syscall_table->syscall_dispatch[id];
 	}
 	if (unlikely(hlist_empty(action_list)))
 		return;
@@ -316,65 +311,6 @@ void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
 	syscall_entry_event_call_func(action_list, entry->event_func, entry->nrargs, regs);
 }
 
-void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
-		long id)
-{
-	struct lttng_event_notifier_group *group = __data;
-	const struct trace_syscall_entry *table, *entry;
-	struct hlist_head *dispatch_list, *unknown_dispatch_list;
-	size_t table_len;
-
-	if (unlikely(in_compat_syscall())) {
-		struct lttng_syscall_filter *filter = group->sc_filter;
-
-		if (id < 0 || id >= NR_compat_syscalls
-			|| (!READ_ONCE(group->syscall_all_entry) &&
-				!test_bit(id, filter->sc_compat_entry))) {
-			/* System call filtered out. */
-			return;
-		}
-		table = compat_sc_table.table;
-		table_len = compat_sc_table.len;
-		unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
-	} else {
-		struct lttng_syscall_filter *filter = group->sc_filter;
-
-		if (id < 0 || id >= NR_syscalls
-			|| (!READ_ONCE(group->syscall_all_entry) &&
-				!test_bit(id, filter->sc_entry))) {
-			/* System call filtered out. */
-			return;
-		}
-		table = sc_table.table;
-		table_len = sc_table.len;
-		unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
-	}
-	/* Check if the syscall id is out of bound. */
-	if (unlikely(id < 0 || id >= table_len)) {
-		syscall_entry_event_unknown(unknown_dispatch_list,
-				regs, id);
-		return;
-	}
-
-	entry = &table[id];
-	if (!entry->event_func) {
-		syscall_entry_event_unknown(unknown_dispatch_list,
-				regs, id);
-		return;
-	}
-
-	if (unlikely(in_compat_syscall())) {
-		dispatch_list = &group->event_notifier_compat_syscall_dispatch[id];
-	} else {
-		dispatch_list = &group->event_notifier_syscall_dispatch[id];
-	}
-	if (unlikely(hlist_empty(dispatch_list)))
-		return;
-
-	syscall_entry_event_call_func(dispatch_list,
-			entry->event_func, entry->nrargs, regs);
-}
-
 static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
 	struct pt_regs *regs, long id, long ret)
 {
@@ -502,7 +438,7 @@ void syscall_exit_event_call_func(struct hlist_head *action_list,
 
 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
 {
-	struct lttng_kernel_channel_buffer *chan = __data;
+	struct lttng_kernel_syscall_table *syscall_table = __data;
 	struct hlist_head *action_list, *unknown_action_list;
 	const struct trace_syscall_entry *table, *entry;
 	size_t table_len;
@@ -511,27 +447,27 @@ void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
 	id = syscall_get_nr(current, regs);
 
 	if (unlikely(in_compat_syscall())) {
-		struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
+		struct lttng_syscall_filter *filter = syscall_table->sc_filter;
 
 		if (id < 0 || id >= NR_compat_syscalls
-			|| (!READ_ONCE(chan->priv->parent.syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
+			|| (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
 			/* System call filtered out. */
 			return;
 		}
 		table = compat_sc_exit_table.table;
 		table_len = compat_sc_exit_table.len;
-		unknown_action_list = &chan->priv->parent.compat_sc_exit_unknown;
+		unknown_action_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
 	} else {
-		struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
+		struct lttng_syscall_filter *filter = syscall_table->sc_filter;
 
 		if (id < 0 || id >= NR_syscalls
-			|| (!READ_ONCE(chan->priv->parent.syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
+			|| (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
 			/* System call filtered out. */
 			return;
 		}
 		table = sc_exit_table.table;
 		table_len = sc_exit_table.len;
-		unknown_action_list = &chan->priv->parent.sc_exit_unknown;
+		unknown_action_list = &syscall_table->unknown_syscall_exit_dispatch;
 	}
 	if (unlikely(id < 0 || id >= table_len)) {
 		syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
@@ -545,9 +481,9 @@ void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
 	}
 
 	if (unlikely(in_compat_syscall())) {
-		action_list = &chan->priv->parent.compat_sc_exit_table[id];
+		action_list = &syscall_table->compat_syscall_exit_dispatch[id];
 	} else {
-		action_list = &chan->priv->parent.sc_exit_table[id];
+		action_list = &syscall_table->syscall_exit_dispatch[id];
 	}
 	if (unlikely(hlist_empty(action_list)))
 		return;
@@ -556,109 +492,61 @@ void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
 			       regs, ret);
 }
 
-void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
-		long ret)
+static
+struct lttng_kernel_syscall_table *get_syscall_table_from_enabler(struct lttng_event_enabler_common *event_enabler)
 {
-	struct lttng_event_notifier_group *group = __data;
-	const struct trace_syscall_entry *table, *entry;
-	struct hlist_head *dispatch_list, *unknown_dispatch_list;
-	size_t table_len;
-	long id;
-
-	id = syscall_get_nr(current, regs);
-
-	if (unlikely(in_compat_syscall())) {
-		struct lttng_syscall_filter *filter = group->sc_filter;
-
-		if (id < 0 || id >= NR_compat_syscalls
-			|| (!READ_ONCE(group->syscall_all_exit) &&
-				!test_bit(id, filter->sc_compat_exit))) {
-			/* System call filtered out. */
-			return;
-		}
-		table = compat_sc_exit_table.table;
-		table_len = compat_sc_exit_table.len;
-		unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
-	} else {
-		struct lttng_syscall_filter *filter = group->sc_filter;
-
-		if (id < 0 || id >= NR_syscalls
-			|| (!READ_ONCE(group->syscall_all_exit) &&
-					!test_bit(id, filter->sc_exit))) {
-			/* System call filtered out. */
-			return;
-		}
-		table = sc_exit_table.table;
-		table_len = sc_exit_table.len;
-		unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
+	switch (event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *event_recorder_enabler =
+			container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
+		return &event_recorder_enabler->chan->priv->parent.syscall_table;
 	}
-	/* Check if the syscall id is out of bound. */
-	if (unlikely(id < 0 || id >= table_len)) {
-		syscall_exit_event_unknown(unknown_dispatch_list,
-				regs, id, ret);
-		return;
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *event_notifier_enabler =
+			container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
+		return &event_notifier_enabler->group->syscall_table;
 	}
-
-	entry = &table[id];
-	if (!entry->event_func) {
-		syscall_entry_event_unknown(unknown_dispatch_list,
-				regs, id);
-		return;
+	default:
+		return NULL;
 	}
+}
 
-	if (unlikely(in_compat_syscall())) {
-		dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[id];
-	} else {
-		dispatch_list = &group->event_notifier_exit_syscall_dispatch[id];
+static
+struct lttng_kernel_syscall_table *get_syscall_table_from_event(struct lttng_kernel_event_common *event)
+{
+	switch (event->type) {
+	case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
+	{
+		struct lttng_kernel_event_recorder *event_recorder =
+			container_of(event, struct lttng_kernel_event_recorder, parent);
+		return &event_recorder->chan->priv->parent.syscall_table;
+	}
+	case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
+	{
+		struct lttng_kernel_event_notifier *event_notifier =
+			container_of(event, struct lttng_kernel_event_notifier, parent);
+		return &event_notifier->priv->group->syscall_table;
+	}
+	default:
+		return NULL;
 	}
-	if (unlikely(hlist_empty(dispatch_list)))
-		return;
-
-	syscall_exit_event_call_func(dispatch_list,
-			entry->event_func, entry->nrargs, regs, ret);
 }
-/*
- * noinline to diminish caller stack size.
- * Should be called with sessions lock held.
- */
+
 static
-int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
-	struct hlist_head *chan_table, struct lttng_event_enabler *event_enabler,
-	enum sc_type type)
+void lttng_syscall_event_enabler_create_event(struct lttng_event_enabler_common *syscall_event_enabler,
+		const struct lttng_kernel_event_desc *desc, enum sc_type type, unsigned int syscall_nr)
 {
-	struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
-	struct lttng_kernel_session *session = chan->parent.session;
-	unsigned int i;
+	struct lttng_kernel_event_common *event;
 
-	/* Allocate events for each syscall matching enabler, insert into table */
-	for (i = 0; i < table_len; i++) {
-		const struct lttng_kernel_event_desc *desc = table[i].desc;
+	switch (syscall_event_enabler->enabler_type) {
+	case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
+	{
+		struct lttng_event_recorder_enabler *syscall_event_recorder_enabler =
+			container_of(syscall_event_enabler, struct lttng_event_recorder_enabler, parent);
+		struct lttng_event_recorder_enabler *event_recorder_enabler;
 		struct lttng_kernel_abi_event ev;
-		struct lttng_kernel_event_recorder_private *event_recorder_priv;
-		struct lttng_kernel_event_recorder *event_recorder;
-		struct hlist_head *head;
-		bool found = false;
-
-		if (!desc) {
-			/* Unknown syscall */
-			continue;
-		}
-		if (lttng_desc_match_enabler(desc,
-				lttng_event_enabler_as_enabler(event_enabler)) <= 0)
-			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_priv, head, hlist) {
-			if (event_recorder_priv->parent.desc == desc
-				&& event_recorder_priv->pub->chan == event_enabler->chan)
-				found = true;
-		}
-		if (found)
-			continue;
 
 		/* We need to create an event for this syscall/enabler. */
 		memset(&ev, 0, sizeof(ev));
@@ -683,652 +571,313 @@ int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *tabl
 		strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
 		ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
 		ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-		event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc, ev.instrumentation);
-		WARN_ON_ONCE(!event_recorder);
-		if (IS_ERR(event_recorder)) {
-			/*
-			 * If something goes wrong in event registration
-			 * after the first one, we have no choice but to
-			 * leave the previous events in there, until
-			 * deleted by session teardown.
-			 */
-			return PTR_ERR(event_recorder);
-		}
-		hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan_table[i]);
-	}
-	return 0;
-}
-
-/*
- * Should be called with sessions lock held.
- */
-int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler)
-{
-	struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
-	struct lttng_kernel_abi_event ev;
-	int ret;
-
-	wrapper_vmalloc_sync_mappings();
-
-	if (!chan->priv->parent.sc_table) {
-		/* create syscall table mapping syscall to events */
-		chan->priv->parent.sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
-					* sc_table.len, GFP_KERNEL);
-		if (!chan->priv->parent.sc_table)
-			return -ENOMEM;
-	}
-	if (!chan->priv->parent.sc_exit_table) {
-		/* create syscall table mapping syscall to events */
-		chan->priv->parent.sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
-					* sc_exit_table.len, GFP_KERNEL);
-		if (!chan->priv->parent.sc_exit_table)
-			return -ENOMEM;
-	}
-
-
-#ifdef CONFIG_COMPAT
-	if (!chan->priv->parent.compat_sc_table) {
-		/* create syscall table mapping compat syscall to events */
-		chan->priv->parent.compat_sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
-					* compat_sc_table.len, GFP_KERNEL);
-		if (!chan->priv->parent.compat_sc_table)
-			return -ENOMEM;
-	}
-
-	if (!chan->priv->parent.compat_sc_exit_table) {
-		/* create syscall table mapping compat syscall to events */
-		chan->priv->parent.compat_sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
-					* compat_sc_exit_table.len, GFP_KERNEL);
-		if (!chan->priv->parent.compat_sc_exit_table)
-			return -ENOMEM;
-	}
-#endif
-	if (hlist_empty(&chan->priv->parent.sc_unknown)) {
-		const struct lttng_kernel_event_desc *desc =
-			&__event_desc___syscall_entry_unknown;
-		struct lttng_kernel_event_recorder *event_recorder;
-
-		memset(&ev, 0, sizeof(ev));
-		strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
-		ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-		ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-		ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-		ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
-		event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
-					    ev.instrumentation);
-		WARN_ON_ONCE(!event_recorder);
-		if (IS_ERR(event_recorder)) {
-			return PTR_ERR(event_recorder);
-		}
-		hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_unknown);
-	}
-
-	if (hlist_empty(&chan->priv->parent.sc_compat_unknown)) {
-		const struct lttng_kernel_event_desc *desc =
-			&__event_desc___compat_syscall_entry_unknown;
-		struct lttng_kernel_event_recorder *event_recorder;
-
-		memset(&ev, 0, sizeof(ev));
-		strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
-		ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-		ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-		ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-		ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
-		event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
-					    ev.instrumentation);
-		WARN_ON_ONCE(!event_recorder);
-		if (IS_ERR(event_recorder)) {
-			return PTR_ERR(event_recorder);
+		event_recorder_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev,
+				syscall_event_recorder_enabler->chan);
+		WARN_ON_ONCE(!event_recorder_enabler);
+		if (!event_recorder_enabler)
+			return;
+		event = _lttng_kernel_event_create(&event_recorder_enabler->parent, desc);
+		WARN_ON_ONCE(IS_ERR(event));
+		lttng_event_enabler_destroy(&event_recorder_enabler->parent);
+		if (IS_ERR(event)) {
+			printk(KERN_INFO "Unable to create event recorder %s\n", desc->event_name);
+			return;
 		}
-		hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_compat_unknown);
+		event->priv->u.syscall.syscall_id = syscall_nr;
+		break;
 	}
+	case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
+	{
+		struct lttng_event_notifier_enabler *syscall_event_notifier_enabler =
+			container_of(syscall_event_enabler, struct lttng_event_notifier_enabler, parent);
+		struct lttng_event_notifier_enabler *event_notifier_enabler;
+		struct lttng_kernel_abi_event_notifier event_notifier_param;
+		uint64_t user_token = syscall_event_enabler->user_token;
+		uint64_t error_counter_index = syscall_event_notifier_enabler->error_counter_index;
 
-	if (hlist_empty(&chan->priv->parent.compat_sc_exit_unknown)) {
-		const struct lttng_kernel_event_desc *desc =
-			&__event_desc___compat_syscall_exit_unknown;
-		struct lttng_kernel_event_recorder *event_recorder;
-
-		memset(&ev, 0, sizeof(ev));
-		strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
-		ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-		ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-		ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-		ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
-		event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
-					    ev.instrumentation);
-		WARN_ON_ONCE(!event_recorder);
-		if (IS_ERR(event_recorder)) {
-			return PTR_ERR(event_recorder);
+		memset(&event_notifier_param, 0, sizeof(event_notifier_param));
+		switch (type) {
+		case SC_TYPE_ENTRY:
+			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
+			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
+			break;
+		case SC_TYPE_EXIT:
+			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
+			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
+			break;
+		case SC_TYPE_COMPAT_ENTRY:
+			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
+			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
+			break;
+		case SC_TYPE_COMPAT_EXIT:
+			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
+			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
+			break;
 		}
-		hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.compat_sc_exit_unknown);
-	}
-
-	if (hlist_empty(&chan->priv->parent.sc_exit_unknown)) {
-		const struct lttng_kernel_event_desc *desc =
-			&__event_desc___syscall_exit_unknown;
-		struct lttng_kernel_event_recorder *event_recorder;
-
-		memset(&ev, 0, sizeof(ev));
-		strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
-		ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-		ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-		ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-		ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
-		event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
-					    ev.instrumentation);
-		WARN_ON_ONCE(!event_recorder);
-		if (IS_ERR(event_recorder)) {
-			return PTR_ERR(event_recorder);
+		strncat(event_notifier_param.event.name, desc->event_name,
+			LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
+		event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
+		event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
+		event_notifier_param.event.token = user_token;
+		event_notifier_param.error_counter_index = error_counter_index;
+
+		event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
+				&event_notifier_param, syscall_event_notifier_enabler->group);
+		WARN_ON_ONCE(!event_notifier_enabler);
+		event = _lttng_kernel_event_create(&event_notifier_enabler->parent, desc);
+		WARN_ON_ONCE(IS_ERR(event));
+		lttng_event_enabler_destroy(&event_notifier_enabler->parent);
+		if (IS_ERR(event)) {
+			printk(KERN_INFO "Unable to create event notifier %s\n", desc->event_name);
+			return;
 		}
-		hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_exit_unknown);
-	}
-
-	ret = lttng_create_syscall_event_if_missing(sc_table.table, sc_table.len,
-			chan->priv->parent.sc_table, event_enabler, SC_TYPE_ENTRY);
-	if (ret)
-		return ret;
-	ret = lttng_create_syscall_event_if_missing(sc_exit_table.table, sc_exit_table.len,
-			chan->priv->parent.sc_exit_table, event_enabler, SC_TYPE_EXIT);
-	if (ret)
-		return ret;
-
-#ifdef CONFIG_COMPAT
-	ret = lttng_create_syscall_event_if_missing(compat_sc_table.table, compat_sc_table.len,
-			chan->priv->parent.compat_sc_table, event_enabler, SC_TYPE_COMPAT_ENTRY);
-	if (ret)
-		return ret;
-	ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table.table, compat_sc_exit_table.len,
-			chan->priv->parent.compat_sc_exit_table, event_enabler, SC_TYPE_COMPAT_EXIT);
-	if (ret)
-		return ret;
-#endif
-
-	if (!chan->priv->parent.sc_filter) {
-		chan->priv->parent.sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
-				GFP_KERNEL);
-		if (!chan->priv->parent.sc_filter)
-			return -ENOMEM;
-	}
-
-	if (!chan->priv->parent.sys_enter_registered) {
-		ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
-				(void *) syscall_entry_event_probe, chan);
-		if (ret)
-			return ret;
-		chan->priv->parent.sys_enter_registered = 1;
+		event->priv->u.syscall.syscall_id = syscall_nr;
+		break;
 	}
-	/*
-	 * We change the name of sys_exit tracepoint due to namespace
-	 * conflict with sys_exit syscall entry.
-	 */
-	if (!chan->priv->parent.sys_exit_registered) {
-		ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
-				(void *) syscall_exit_event_probe, chan);
-		if (ret) {
-			WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
-				(void *) syscall_entry_event_probe, chan));
-			return ret;
-		}
-		chan->priv->parent.sys_exit_registered = 1;
+	default:
+		break;
 	}
-	return ret;
 }
 
-/*
- * Should be called with sessions lock held.
- */
-int lttng_syscalls_register_event_notifier(
-		struct lttng_event_notifier_enabler *event_notifier_enabler)
+static
+void lttng_syscall_event_enabler_create_matching_syscall_table_events(struct lttng_event_enabler_common *syscall_event_enabler_common,
+		const struct trace_syscall_entry *table, size_t table_len, enum sc_type type)
 {
-	struct lttng_event_notifier_group *group = event_notifier_enabler->group;
+	struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(syscall_event_enabler_common);
+	const struct lttng_kernel_event_desc *desc;
 	unsigned int i;
-	int ret = 0;
-
-	wrapper_vmalloc_sync_mappings();
-
-	if (!group->event_notifier_syscall_dispatch) {
-		group->event_notifier_syscall_dispatch =
-				kzalloc(sizeof(struct hlist_head) * sc_table.len,
-					GFP_KERNEL);
-		if (!group->event_notifier_syscall_dispatch)
-			return -ENOMEM;
-
-		/* Initialize all list_head */
-		for (i = 0; i < sc_table.len; i++)
-			INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
-
-		/* Init the unknown syscall notifier list. */
-		INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
-	}
-
-	if (!group->event_notifier_exit_syscall_dispatch) {
-		group->event_notifier_exit_syscall_dispatch =
-				kzalloc(sizeof(struct hlist_head) * sc_table.len,
-					GFP_KERNEL);
-		if (!group->event_notifier_exit_syscall_dispatch)
-			return -ENOMEM;
 
-		/* Initialize all list_head */
-		for (i = 0; i < sc_table.len; i++)
-			INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
-
-		/* Init the unknown exit syscall notifier list. */
-		INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
-	}
-
-#ifdef CONFIG_COMPAT
-	if (!group->event_notifier_compat_syscall_dispatch) {
-		group->event_notifier_compat_syscall_dispatch =
-				kzalloc(sizeof(struct hlist_head) * compat_sc_table.len,
-					GFP_KERNEL);
-		if (!group->event_notifier_syscall_dispatch)
-			return -ENOMEM;
-
-		/* Initialize all list_head */
-		for (i = 0; i < compat_sc_table.len; i++)
-			INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
-
-		/* Init the unknown syscall notifier list. */
-		INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
-	}
-
-	if (!group->event_notifier_exit_compat_syscall_dispatch) {
-		group->event_notifier_exit_compat_syscall_dispatch =
-				kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len,
-					GFP_KERNEL);
-		if (!group->event_notifier_exit_syscall_dispatch)
-			return -ENOMEM;
-
-		/* Initialize all list_head */
-		for (i = 0; i < compat_sc_exit_table.len; i++)
-			INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
-
-		/* Init the unknown exit syscall notifier list. */
-		INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
-	}
+#ifndef CONFIG_COMPAT
+	if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
+		return;
 #endif
+	/* iterate over all syscall and create event that match */
+	for (i = 0; i < table_len; i++) {
+		struct lttng_kernel_event_common_private *event_priv;
+		struct hlist_head *head;
+		bool found = false;
 
-	if (!group->sc_filter) {
-		group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
-				GFP_KERNEL);
-		if (!group->sc_filter)
-			return -ENOMEM;
-	}
+		desc = table[i].desc;
+		if (!desc) {
+			/* Unknown syscall */
+			continue;
+		}
 
-	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;
-	}
+		if (!lttng_desc_match_enabler(desc, syscall_event_enabler_common))
+			continue;
 
-	if (!group->sys_exit_registered) {
-		ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
-				(void *) syscall_exit_event_notifier_probe, group);
-		if (ret) {
-			WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
-				(void *) syscall_entry_event_notifier_probe, group));
-			return ret;
+		/*
+		 * Check if already created.
+		 */
+		head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
+		lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
+			if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub)) {
+				found = true;
+				break;
+			}
 		}
-		group->sys_exit_registered = 1;
+		if (found)
+			continue;
+
+		lttng_syscall_event_enabler_create_event(syscall_event_enabler_common, desc, type, i);
 	}
+}
 
-	return ret;
+static
+bool lttng_syscall_event_enabler_is_wildcard_all(struct lttng_event_enabler_common *event_enabler)
+{
+	if (event_enabler->event_param.instrumentation != LTTNG_KERNEL_ABI_SYSCALL)
+		return false;
+	if (event_enabler->event_param.u.syscall.abi != LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL)
+		return false;
+	if (event_enabler->event_param.u.syscall.match != LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME)
+		return false;
+	if (strcmp(event_enabler->event_param.name, "*"))
+		return false;
+	return true;
 }
 
 static
-int create_unknown_event_notifier(
-		struct lttng_event_notifier_enabler *event_notifier_enabler,
-		enum sc_type type)
+void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabler, enum sc_type type)
 {
-	struct lttng_kernel_event_notifier_private *event_notifier_priv;
-	struct lttng_kernel_event_notifier *event_notifier;
+	struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(event_enabler);
+	struct lttng_kernel_event_common_private *event_priv;
 	const struct lttng_kernel_event_desc *desc;
-	struct lttng_event_notifier_group *group = event_notifier_enabler->group;
-	struct lttng_kernel_abi_event_notifier event_notifier_param;
-	uint64_t user_token = event_notifier_enabler->base.user_token;
-	uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
-	struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
-		event_notifier_enabler);
-	struct hlist_head *unknown_dispatch_list;
-	int ret = 0;
 	bool found = false;
-	enum lttng_kernel_abi_syscall_abi abi;
-	enum lttng_kernel_abi_syscall_entryexit entryexit;
 	struct hlist_head *head;
 
+#ifndef CONFIG_COMPAT
+	if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
+		return;
+#endif
+	/*
+	 * Considering that currently system calls can only be enabled on a per
+	 * name basis (or wildcard based on a name), unknown syscall events are
+	 * only used when matching *all* system calls, because this is the only
+	 * case which can be associated with an unknown system call.
+	 *
+	 * When enabling system call on a per system call number basis will be
+	 * supported, this will need to be revisited.
+	 */
+	if (!lttng_syscall_event_enabler_is_wildcard_all(event_enabler))
+		return;
+
 	switch (type) {
 	case SC_TYPE_ENTRY:
 		desc = &__event_desc___syscall_entry_unknown;
-		unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
-		entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-		abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
 		break;
 	case SC_TYPE_EXIT:
 		desc = &__event_desc___syscall_exit_unknown;
-		unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
-		entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-		abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
 		break;
 	case SC_TYPE_COMPAT_ENTRY:
 		desc = &__event_desc___compat_syscall_entry_unknown;
-		unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
-		entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-		abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
 		break;
 	case SC_TYPE_COMPAT_EXIT:
 		desc = &__event_desc___compat_syscall_exit_unknown;
-		unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
-		entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-		abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
 		break;
 	default:
-		BUG_ON(1);
+		WARN_ON_ONCE(1);
 	}
 
 	/*
 	 * Check if already created.
 	 */
-	head = utils_borrow_hash_table_bucket(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 == base_enabler->user_token)
+	head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
+	lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
+		if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) {
 			found = true;
-	}
-	if (found)
-		goto end;
-
-	memset(&event_notifier_param, 0, sizeof(event_notifier_param));
-	strncat(event_notifier_param.event.name, desc->event_name,
-		LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
-
-	event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-
-	event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-	event_notifier_param.event.u.syscall.abi = abi;
-	event_notifier_param.event.u.syscall.entryexit = entryexit;
-
-	event_notifier = _lttng_event_notifier_create(desc, user_token,
-		error_counter_index, group, &event_notifier_param,
-		event_notifier_param.event.instrumentation);
-	if (IS_ERR(event_notifier)) {
-		printk(KERN_INFO "Unable to create unknown notifier %s\n",
-			desc->event_name);
-		ret = -ENOMEM;
-		goto end;
-	}
-
-	hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, unknown_dispatch_list);
-
-end:
-	return ret;
-}
-
-static int create_matching_event_notifiers(
-		struct lttng_event_notifier_enabler *event_notifier_enabler,
-		const struct trace_syscall_entry *table,
-		size_t table_len, enum sc_type type)
-{
-	struct lttng_event_notifier_group *group = event_notifier_enabler->group;
-	const struct lttng_kernel_event_desc *desc;
-	uint64_t user_token = event_notifier_enabler->base.user_token;
-	uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
-	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_kernel_event_notifier_private *event_notifier_priv;
-		struct lttng_kernel_event_notifier *event_notifier;
-		struct lttng_kernel_abi_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->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->base.user_token)
-				found = 1;
-		}
-		if (found)
-			continue;
-
-		memset(&event_notifier_param, 0, sizeof(event_notifier_param));
-		switch (type) {
-		case SC_TYPE_ENTRY:
-			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
-			break;
-		case SC_TYPE_EXIT:
-			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
-			break;
-		case SC_TYPE_COMPAT_ENTRY:
-			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
-			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
-			break;
-		case SC_TYPE_COMPAT_EXIT:
-			event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
-			event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
 			break;
 		}
-		strncat(event_notifier_param.event.name, desc->event_name,
-			LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
-		event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
-		event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
-
-		event_notifier = _lttng_event_notifier_create(desc, user_token,
-			error_counter_index, group, &event_notifier_param,
-			event_notifier_param.event.instrumentation);
-		if (IS_ERR(event_notifier)) {
-			printk(KERN_INFO "Unable to create event_notifier %s\n",
-				desc->event_name);
-			ret = -ENOMEM;
-			goto end;
-		}
-
-		event_notifier->priv->parent.u.syscall.syscall_id = i;
 	}
-
-end:
-	return ret;
-
+	if (!found)
+		lttng_syscall_event_enabler_create_event(event_enabler, desc, type, -1U);
 }
 
-int lttng_syscalls_create_matching_event_notifiers(
-		struct lttng_event_notifier_enabler *event_notifier_enabler)
+static
+void lttng_syscall_event_enabler_create_matching_events(struct lttng_event_enabler_common *event_enabler)
 {
-	int ret;
-	struct lttng_enabler *base_enabler =
-			lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
-	enum lttng_kernel_abi_syscall_entryexit entryexit =
-			base_enabler->event_param.u.syscall.entryexit;
+	enum lttng_kernel_abi_syscall_entryexit entryexit = event_enabler->event_param.u.syscall.entryexit;
 
 	if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
-		ret = create_matching_event_notifiers(event_notifier_enabler,
+		lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
 			sc_table.table, sc_table.len, SC_TYPE_ENTRY);
-		if (ret)
-			goto end;
-
-		ret = create_matching_event_notifiers(event_notifier_enabler,
-			compat_sc_table.table, compat_sc_table.len,
-			SC_TYPE_COMPAT_ENTRY);
-		if (ret)
-			goto end;
-
-		ret = create_unknown_event_notifier(event_notifier_enabler,
-				SC_TYPE_ENTRY);
-		if (ret)
-			goto end;
-
-		ret = create_unknown_event_notifier(event_notifier_enabler,
-				SC_TYPE_COMPAT_ENTRY);
-		if (ret)
-			goto end;
+		lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
+			compat_sc_table.table, compat_sc_table.len, SC_TYPE_COMPAT_ENTRY);
+		create_unknown_syscall_event(event_enabler, SC_TYPE_ENTRY);
+		create_unknown_syscall_event(event_enabler, SC_TYPE_COMPAT_ENTRY);
 	}
 
 	if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
-		ret = create_matching_event_notifiers(event_notifier_enabler,
-			sc_exit_table.table, sc_exit_table.len,
-			SC_TYPE_EXIT);
-		if (ret)
-			goto end;
-
-		ret = create_unknown_event_notifier(event_notifier_enabler,
-				SC_TYPE_EXIT);
-		if (ret)
-			goto end;
-
-		ret = create_matching_event_notifiers(event_notifier_enabler,
-			compat_sc_exit_table.table, compat_sc_exit_table.len,
-			SC_TYPE_COMPAT_EXIT);
-		if (ret)
-			goto end;
-
-		ret = create_unknown_event_notifier(event_notifier_enabler,
-				SC_TYPE_COMPAT_EXIT);
-		if (ret)
-			goto end;
+		lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
+			sc_exit_table.table, sc_exit_table.len, SC_TYPE_EXIT);
+		lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
+			compat_sc_exit_table.table, compat_sc_exit_table.len, SC_TYPE_COMPAT_EXIT);
+		create_unknown_syscall_event(event_enabler, SC_TYPE_EXIT);
+		create_unknown_syscall_event(event_enabler, SC_TYPE_COMPAT_EXIT);
 	}
-
-end:
-	return ret;
 }
 
 /*
- * Unregister the syscall event_notifier probes from the callsites.
+ * Should be called with sessions lock held.
  */
-int lttng_syscalls_unregister_event_notifier_group(
-		struct lttng_event_notifier_group *event_notifier_group)
+int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enabler_common *syscall_event_enabler)
 {
+	struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(syscall_event_enabler);
 	int ret;
 
-	/*
-	 * Only register the event_notifier probe on the `sys_enter` callsite for now.
-	 * At the moment, we don't think it's desirable to have one fired
-	 * event_notifier for the entry and one for the exit of a syscall.
-	 */
-	if (event_notifier_group->sys_enter_registered) {
-		ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
-				(void *) syscall_entry_event_notifier_probe, event_notifier_group);
+	if (!syscall_table->syscall_dispatch) {
+		/* create syscall table mapping syscall to events */
+		syscall_table->syscall_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
+		if (!syscall_table->syscall_dispatch)
+			return -ENOMEM;
+	}
+	if (!syscall_table->syscall_exit_dispatch) {
+		/* create syscall table mapping syscall to events */
+		syscall_table->syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * sc_exit_table.len, GFP_KERNEL);
+		if (!syscall_table->syscall_exit_dispatch)
+			return -ENOMEM;
+	}
+
+#ifdef CONFIG_COMPAT
+	if (!syscall_table->compat_syscall_dispatch) {
+		/* create syscall table mapping compat syscall to events */
+		syscall_table->compat_syscall_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_table.len, GFP_KERNEL);
+		if (!syscall_table->compat_syscall_dispatch)
+			return -ENOMEM;
+	}
+
+	if (!syscall_table->compat_syscall_exit_dispatch) {
+		/* create syscall table mapping compat syscall to events */
+		syscall_table->compat_syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len, GFP_KERNEL);
+		if (!syscall_table->compat_syscall_exit_dispatch)
+			return -ENOMEM;
+	}
+#endif
+	if (!syscall_table->sc_filter) {
+		syscall_table->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
+				GFP_KERNEL);
+		if (!syscall_table->sc_filter)
+			return -ENOMEM;
+	}
+
+	if (!syscall_table->sys_enter_registered) {
+		ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
+				(void *) syscall_entry_event_probe, syscall_table);
 		if (ret)
 			return ret;
-		event_notifier_group->sys_enter_registered = 0;
+		syscall_table->sys_enter_registered = 1;
 	}
-	if (event_notifier_group->sys_exit_registered) {
-		ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
-				(void *) syscall_exit_event_notifier_probe, event_notifier_group);
-		if (ret)
+	if (!syscall_table->sys_exit_registered) {
+		ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
+				(void *) syscall_exit_event_probe, syscall_table);
+		if (ret) {
+			WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
+				(void *) syscall_entry_event_probe, syscall_table));
 			return ret;
-		event_notifier_group->sys_enter_registered = 0;
+		}
+		syscall_table->sys_exit_registered = 1;
 	}
 
-	kfree(event_notifier_group->event_notifier_syscall_dispatch);
-	kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
-#ifdef CONFIG_COMPAT
-	kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
-	kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
-#endif
+	lttng_syscall_event_enabler_create_matching_events(syscall_event_enabler);
+
 	return 0;
 }
 
-int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
+int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
 	int ret;
 
-	if (!chan->priv->parent.sc_table)
+	if (!syscall_table->syscall_dispatch)
 		return 0;
-	if (chan->priv->parent.sys_enter_registered) {
+	if (syscall_table->sys_enter_registered) {
 		ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
-				(void *) syscall_entry_event_probe, chan);
+				(void *) syscall_entry_event_probe, syscall_table);
 		if (ret)
 			return ret;
-		chan->priv->parent.sys_enter_registered = 0;
+		syscall_table->sys_enter_registered = 0;
 	}
-	if (chan->priv->parent.sys_exit_registered) {
+	if (syscall_table->sys_exit_registered) {
 		ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
-				(void *) syscall_exit_event_probe, chan);
+				(void *) syscall_exit_event_probe, syscall_table);
 		if (ret)
 			return ret;
-		chan->priv->parent.sys_exit_registered = 0;
+		syscall_table->sys_exit_registered = 0;
 	}
 	return 0;
 }
 
-int lttng_syscalls_destroy_event(struct lttng_kernel_channel_buffer *chan)
+int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
 {
-	kfree(chan->priv->parent.sc_table);
-	kfree(chan->priv->parent.sc_exit_table);
+	kfree(syscall_table->syscall_dispatch);
+	kfree(syscall_table->syscall_exit_dispatch);
 #ifdef CONFIG_COMPAT
-	kfree(chan->priv->parent.compat_sc_table);
-	kfree(chan->priv->parent.compat_sc_exit_table);
+	kfree(syscall_table->compat_syscall_dispatch);
+	kfree(syscall_table->compat_syscall_exit_dispatch);
 #endif
-	kfree(chan->priv->parent.sc_filter);
+	kfree(syscall_table->sc_filter);
 	return 0;
 }
 
-static
-int get_syscall_nr(const char *syscall_name)
-{
-	int syscall_nr = -1;
-	int i;
-
-	for (i = 0; i < sc_table.len; i++) {
-		const struct trace_syscall_entry *entry;
-		const char *it_name;
-
-		entry = &sc_table.table[i];
-		if (!entry->desc)
-			continue;
-		it_name = entry->desc->event_name;
-		it_name += strlen(SYSCALL_ENTRY_STR);
-		if (!strcmp(syscall_name, it_name)) {
-			syscall_nr = i;
-			break;
-		}
-	}
-	return syscall_nr;
-}
-
-static
-int get_compat_syscall_nr(const char *syscall_name)
-{
-	int syscall_nr = -1;
-	int i;
-
-	for (i = 0; i < compat_sc_table.len; i++) {
-		const struct trace_syscall_entry *entry;
-		const char *it_name;
-
-		entry = &compat_sc_table.table[i];
-		if (!entry->desc)
-			continue;
-		it_name = entry->desc->event_name;
-		it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
-		if (!strcmp(syscall_name, it_name)) {
-			syscall_nr = i;
-			break;
-		}
-	}
-	return syscall_nr;
-}
-
 static
 uint32_t get_sc_tables_len(void)
 {
@@ -1373,28 +922,15 @@ static
 int lttng_syscall_filter_enable(
 		struct lttng_syscall_filter *filter,
 		const char *desc_name, enum lttng_syscall_abi abi,
-		enum lttng_syscall_entryexit entryexit)
+		enum lttng_syscall_entryexit entryexit,
+		unsigned int syscall_id)
 {
 	const char *syscall_name;
 	unsigned long *bitmap;
 	u32 *refcount_map;
-	int syscall_nr;
 
 	syscall_name = get_syscall_name(desc_name, abi, entryexit);
 
-	switch (abi) {
-	case LTTNG_SYSCALL_ABI_NATIVE:
-		syscall_nr = get_syscall_nr(syscall_name);
-		break;
-	case LTTNG_SYSCALL_ABI_COMPAT:
-		syscall_nr = get_compat_syscall_nr(syscall_name);
-		break;
-	default:
-		return -EINVAL;
-	}
-	if (syscall_nr < 0)
-		return -ENOENT;
-
 	switch (entryexit) {
 	case LTTNG_SYSCALL_ENTRY:
 		switch (abi) {
@@ -1427,116 +963,112 @@ int lttng_syscall_filter_enable(
 	default:
 		return -EINVAL;
 	}
-	if (refcount_map[syscall_nr] == U32_MAX)
+	if (refcount_map[syscall_id] == U32_MAX)
 		return -EOVERFLOW;
-	if (refcount_map[syscall_nr]++ == 0)
-		bitmap_set(bitmap, syscall_nr, 1);
+	if (refcount_map[syscall_id]++ == 0)
+		bitmap_set(bitmap, syscall_id, 1);
 	return 0;
 }
 
-int lttng_syscall_filter_enable_event_notifier(
-		struct lttng_kernel_event_notifier *event_notifier)
+int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
 {
-	struct lttng_event_notifier_group *group = event_notifier->priv->group;
-	unsigned int syscall_id = event_notifier->priv->parent.u.syscall.syscall_id;
+	struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
+	unsigned int syscall_id = event->priv->u.syscall.syscall_id;
 	struct hlist_head *dispatch_list;
 	int ret = 0;
 
-	WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
-
-	/* Skip unknown syscall */
-	if (syscall_id == -1U)
-		return 0;
-
-	ret = lttng_syscall_filter_enable(group->sc_filter,
-		event_notifier->priv->parent.desc->event_name,
-		event_notifier->priv->parent.u.syscall.abi,
-		event_notifier->priv->parent.u.syscall.entryexit);
-	if (ret)
-		return ret;
-
-	switch (event_notifier->priv->parent.u.syscall.entryexit) {
-	case LTTNG_SYSCALL_ENTRY:
-		switch (event_notifier->priv->parent.u.syscall.abi) {
-		case LTTNG_SYSCALL_ABI_NATIVE:
-			dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
+	WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
+
+	/* Unknown syscall */
+	if (syscall_id == -1U) {
+		switch (event->priv->u.syscall.entryexit) {
+		case LTTNG_SYSCALL_ENTRY:
+			switch (event->priv->u.syscall.abi) {
+			case LTTNG_SYSCALL_ABI_NATIVE:
+				dispatch_list = &syscall_table->unknown_syscall_dispatch;
+				break;
+			case LTTNG_SYSCALL_ABI_COMPAT:
+				dispatch_list = &syscall_table->compat_unknown_syscall_dispatch;
+				break;
+			default:
+				ret = -EINVAL;
+				goto end;
+			}
 			break;
-		case LTTNG_SYSCALL_ABI_COMPAT:
-			dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
+		case LTTNG_SYSCALL_EXIT:
+			switch (event->priv->u.syscall.abi) {
+			case LTTNG_SYSCALL_ABI_NATIVE:
+				dispatch_list = &syscall_table->unknown_syscall_exit_dispatch;
+				break;
+			case LTTNG_SYSCALL_ABI_COMPAT:
+				dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
+				break;
+			default:
+				ret = -EINVAL;
+				goto end;
+			}
 			break;
 		default:
 			ret = -EINVAL;
 			goto end;
 		}
-		break;
-	case LTTNG_SYSCALL_EXIT:
-		switch (event_notifier->priv->parent.u.syscall.abi) {
-		case LTTNG_SYSCALL_ABI_NATIVE:
-			dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
+	} else {
+		ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
+			event->priv->desc->event_name, event->priv->u.syscall.abi,
+			event->priv->u.syscall.entryexit, syscall_id);
+		if (ret)
+			return ret;
+
+		switch (event->priv->u.syscall.entryexit) {
+		case LTTNG_SYSCALL_ENTRY:
+			switch (event->priv->u.syscall.abi) {
+			case LTTNG_SYSCALL_ABI_NATIVE:
+				dispatch_list = &syscall_table->syscall_dispatch[syscall_id];
+				break;
+			case LTTNG_SYSCALL_ABI_COMPAT:
+				dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id];
+				break;
+			default:
+				ret = -EINVAL;
+				goto end;
+			}
 			break;
-		case LTTNG_SYSCALL_ABI_COMPAT:
-			dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
+		case LTTNG_SYSCALL_EXIT:
+			switch (event->priv->u.syscall.abi) {
+			case LTTNG_SYSCALL_ABI_NATIVE:
+				dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id];
+				break;
+			case LTTNG_SYSCALL_ABI_COMPAT:
+				dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id];
+				break;
+			default:
+				ret = -EINVAL;
+				goto end;
+			}
 			break;
 		default:
 			ret = -EINVAL;
 			goto end;
 		}
-		break;
-	default:
-		ret = -EINVAL;
-		goto end;
 	}
 
-	hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, dispatch_list);
-
+	hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list);
 end:
 	return ret;
 }
 
-int lttng_syscall_filter_enable_event(
-		struct lttng_kernel_channel_buffer *channel,
-		struct lttng_kernel_event_recorder *event_recorder)
-{
-	unsigned int syscall_id = event_recorder->priv->parent.u.syscall.syscall_id;
-
-	WARN_ON_ONCE(event_recorder->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
-
-	/* Skip unknown syscall */
-	if (syscall_id == -1U)
-		return 0;
-
-	return lttng_syscall_filter_enable(channel->priv->parent.sc_filter,
-		event_recorder->priv->parent.desc->event_name,
-		event_recorder->priv->parent.u.syscall.abi,
-		event_recorder->priv->parent.u.syscall.entryexit);
-}
-
 static
-int lttng_syscall_filter_disable(
-		struct lttng_syscall_filter *filter,
+int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter,
 		const char *desc_name, enum lttng_syscall_abi abi,
-		enum lttng_syscall_entryexit entryexit)
+		enum lttng_syscall_entryexit entryexit,
+		unsigned int syscall_id)
 {
 	const char *syscall_name;
 	unsigned long *bitmap;
 	u32 *refcount_map;
-	int syscall_nr;
 
 	syscall_name = get_syscall_name(desc_name, abi, entryexit);
 
-	switch (abi) {
-	case LTTNG_SYSCALL_ABI_NATIVE:
-		syscall_nr = get_syscall_nr(syscall_name);
-		break;
-	case LTTNG_SYSCALL_ABI_COMPAT:
-		syscall_nr = get_compat_syscall_nr(syscall_name);
-		break;
-	default:
-		return -EINVAL;
-	}
-	if (syscall_nr < 0)
-		return -ENOENT;
-
 	switch (entryexit) {
 	case LTTNG_SYSCALL_ENTRY:
 		switch (abi) {
@@ -1569,51 +1101,45 @@ int lttng_syscall_filter_disable(
 	default:
 		return -EINVAL;
 	}
-	if (refcount_map[syscall_nr] == 0)
+	if (refcount_map[syscall_id] == 0)
 		return -ENOENT;
-	if (--refcount_map[syscall_nr] == 0)
-		bitmap_clear(bitmap, syscall_nr, 1);
+	if (--refcount_map[syscall_id] == 0)
+		bitmap_clear(bitmap, syscall_id, 1);
 	return 0;
 }
 
-int lttng_syscall_filter_disable_event_notifier(
-		struct lttng_kernel_event_notifier *event_notifier)
+int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
 {
-	struct lttng_event_notifier_group *group = event_notifier->priv->group;
-	unsigned int syscall_id = event_notifier->priv->parent.u.syscall.syscall_id;
+	struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
+	unsigned int syscall_id = event->priv->u.syscall.syscall_id;
 	int ret;
 
-	WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
-
-	/* Skip unknown syscall */
-	if (syscall_id == -1U)
-		return 0;
-
-	ret = lttng_syscall_filter_disable(group->sc_filter,
-		event_notifier->priv->parent.desc->event_name,
-		event_notifier->priv->parent.u.syscall.abi,
-		event_notifier->priv->parent.u.syscall.entryexit);
-	if (ret)
-		return ret;
-
-	hlist_del_rcu(&event_notifier->priv->parent.u.syscall.node);
+	/* Except for unknown syscall */
+	if (syscall_id != -1U) {
+		ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
+			event->priv->desc->event_name, event->priv->u.syscall.abi,
+			event->priv->u.syscall.entryexit, syscall_id);
+		if (ret)
+			return ret;
+	}
+	hlist_del_rcu(&event->priv->u.syscall.node);
 	return 0;
 }
 
-int lttng_syscall_filter_disable_event(
-		struct lttng_kernel_channel_buffer *channel,
-		struct lttng_kernel_event_recorder *event_recorder)
+void lttng_syscall_table_set_wildcard_all(struct lttng_event_enabler_common *event_enabler)
 {
-	unsigned int syscall_id = event_recorder->priv->parent.u.syscall.syscall_id;
+	struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(event_enabler);
+	enum lttng_kernel_abi_syscall_entryexit entryexit;
+	int enabled = event_enabler->enabled;
 
-	/* Skip unknown syscall */
-	if (syscall_id == -1U)
-		return 0;
+	if (!lttng_syscall_event_enabler_is_wildcard_all(event_enabler))
+		return;
+	entryexit = event_enabler->event_param.u.syscall.entryexit;
+	if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
+		WRITE_ONCE(syscall_table->syscall_all_entry, enabled);
 
-	return lttng_syscall_filter_disable(channel->priv->parent.sc_filter,
-		event_recorder->priv->parent.desc->event_name,
-		event_recorder->priv->parent.u.syscall.abi,
-		event_recorder->priv->parent.u.syscall.entryexit);
+	if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
+		WRITE_ONCE(syscall_table->syscall_all_exit, enabled);
 }
 
 static
@@ -1730,7 +1256,7 @@ const struct file_operations lttng_syscall_list_fops = {
 /*
  * A syscall is enabled if it is traced for either entry or exit.
  */
-long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
+long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
 		struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
 {
 	uint32_t len, sc_tables_len, bitmask_len;
@@ -1750,14 +1276,14 @@ long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
 	tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
 	if (!tmp_mask)
 		return -ENOMEM;
-	filter = channel->priv->parent.sc_filter;
+	filter = syscall_table->sc_filter;
 
 	for (bit = 0; bit < sc_table.len; bit++) {
 		char state;
 
-		if (channel->priv->parent.sc_table) {
-			if (!(READ_ONCE(channel->priv->parent.syscall_all_entry)
-					|| READ_ONCE(channel->priv->parent.syscall_all_exit)) && filter)
+		if (syscall_table->syscall_dispatch) {
+			if (!(READ_ONCE(syscall_table->syscall_all_entry)
+					|| READ_ONCE(syscall_table->syscall_all_exit)) && filter)
 				state = test_bit(bit, filter->sc_entry)
 					|| test_bit(bit, filter->sc_exit);
 			else
@@ -1770,9 +1296,9 @@ long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
 	for (; bit < sc_tables_len; bit++) {
 		char state;
 
-		if (channel->priv->parent.compat_sc_table) {
-			if (!(READ_ONCE(channel->priv->parent.syscall_all_entry)
-					|| READ_ONCE(channel->priv->parent.syscall_all_exit)) && filter)
+		if (syscall_table->compat_syscall_dispatch) {
+			if (!(READ_ONCE(syscall_table->syscall_all_entry)
+					|| READ_ONCE(syscall_table->syscall_all_exit)) && filter)
 				state = test_bit(bit - sc_table.len,
 						filter->sc_compat_entry)
 					|| test_bit(bit - sc_table.len,
diff --git a/src/probes/lttng-kprobes.c b/src/probes/lttng-kprobes.c
index 12de611..1f49c07 100644
--- a/src/probes/lttng-kprobes.c
+++ b/src/probes/lttng-kprobes.c
@@ -103,7 +103,7 @@ static const struct lttng_kernel_tracepoint_class tp_class = {
  * Create event description
  */
 static
-int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_recorder *event_recorder)
+int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_common *event)
 {
 	struct lttng_kernel_event_desc *desc;
 	int ret;
@@ -118,35 +118,7 @@ int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_record
 		goto error_str;
 	}
 	desc->owner = THIS_MODULE;
-	event_recorder->priv->parent.desc = desc;
-
-	return 0;
-
-error_str:
-	kfree(desc);
-	return ret;
-}
-
-/*
- * Create event_notifier description
- */
-static
-int lttng_create_kprobe_event_notifier(const char *name, struct lttng_kernel_event_notifier *event_notifier)
-{
-	struct lttng_kernel_event_desc *desc;
-	int ret;
-
-	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
-	if (!desc)
-		return -ENOMEM;
-	desc->tp_class = &tp_class;
-	desc->event_name = kstrdup(name, GFP_KERNEL);
-	if (!desc->event_name) {
-		ret = -ENOMEM;
-		goto error_str;
-	}
-	desc->owner = THIS_MODULE;
-	event_notifier->priv->parent.desc = desc;
+	event->priv->desc = desc;
 
 	return 0;
 
@@ -210,82 +182,43 @@ int lttng_kprobes_register_event(const char *name,
 			   const char *symbol_name,
 			   uint64_t offset,
 			   uint64_t addr,
-			   struct lttng_kernel_event_recorder *event_recorder)
+			   struct lttng_kernel_event_common *event)
 {
 	int ret;
 
-	ret = lttng_create_kprobe_event(name, event_recorder);
+	ret = lttng_create_kprobe_event(name, event);
 	if (ret)
 		goto error;
 
 	ret = _lttng_kprobes_register(symbol_name, offset, addr,
-		&event_recorder->priv->parent.u.kprobe, lttng_kprobes_event_handler_pre);
+		&event->priv->u.kprobe, lttng_kprobes_event_handler_pre);
 	if (ret)
 		goto register_error;
 
 	return 0;
 
 register_error:
-	kfree(event_recorder->priv->parent.desc->event_name);
-	kfree(event_recorder->priv->parent.desc);
+	kfree(event->priv->desc->event_name);
+	kfree(event->priv->desc);
 error:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(lttng_kprobes_register_event);
 
-int lttng_kprobes_register_event_notifier(const char *symbol_name,
-			   uint64_t offset,
-			   uint64_t addr,
-			   struct lttng_kernel_event_notifier *event_notifier)
-{
-	int ret;
-	ret = lttng_create_kprobe_event_notifier(symbol_name, event_notifier);
-	if (ret)
-		goto error;
-
-	ret = _lttng_kprobes_register(symbol_name, offset, addr,
-		&event_notifier->priv->parent.u.kprobe, lttng_kprobes_event_handler_pre);
-	if (ret)
-		goto register_error;
-
-	return 0;
-
-register_error:
-	kfree(event_notifier->priv->parent.desc->event_name);
-	kfree(event_notifier->priv->parent.desc);
-error:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(lttng_kprobes_register_event_notifier);
-
-void lttng_kprobes_unregister_event(struct lttng_kernel_event_recorder *event_recorder)
+void lttng_kprobes_unregister_event(struct lttng_kernel_event_common *event)
 {
-	unregister_kprobe(&event_recorder->priv->parent.u.kprobe.kp);
+	unregister_kprobe(&event->priv->u.kprobe.kp);
 }
 EXPORT_SYMBOL_GPL(lttng_kprobes_unregister_event);
 
-void lttng_kprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
+void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_common *event)
 {
-	unregister_kprobe(&event_notifier->priv->parent.u.kprobe.kp);
-}
-EXPORT_SYMBOL_GPL(lttng_kprobes_unregister_event_notifier);
-
-void lttng_kprobes_destroy_event_private(struct lttng_kernel_event_recorder *event_recorder)
-{
-	kfree(event_recorder->priv->parent.u.kprobe.symbol_name);
-	kfree(event_recorder->priv->parent.desc->event_name);
-	kfree(event_recorder->priv->parent.desc);
+	kfree(event->priv->u.kprobe.symbol_name);
+	kfree(event->priv->desc->event_name);
+	kfree(event->priv->desc);
 }
 EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_event_private);
 
-void lttng_kprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier)
-{
-	kfree(event_notifier->priv->parent.u.kprobe.symbol_name);
-	kfree(event_notifier->priv->parent.desc->event_name);
-	kfree(event_notifier->priv->parent.desc);
-}
-EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_event_notifier_private);
-
 MODULE_LICENSE("GPL and additional rights");
 MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
 MODULE_DESCRIPTION("LTTng kprobes probes");
diff --git a/src/probes/lttng-kretprobes.c b/src/probes/lttng-kretprobes.c
index 1d0a5ec..5cb2e95 100644
--- a/src/probes/lttng-kretprobes.c
+++ b/src/probes/lttng-kretprobes.c
@@ -132,7 +132,7 @@ static const struct lttng_kernel_tracepoint_class tp_class = {
  * Create event description
  */
 static
-int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_recorder *event_recorder,
+int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_common *event,
 			      enum lttng_kretprobe_type type)
 {
 	struct lttng_kernel_event_desc *desc;
@@ -164,7 +164,7 @@ int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_record
 	desc->event_name = alloc_name;
 	desc->tp_class = &tp_class;
 	desc->owner = THIS_MODULE;
-	event_recorder->priv->parent.desc = desc;
+	event->priv->desc = desc;
 
 	return 0;
 
@@ -177,8 +177,8 @@ int lttng_kretprobes_register(const char *name,
 			   const char *symbol_name,
 			   uint64_t offset,
 			   uint64_t addr,
-			   struct lttng_kernel_event_recorder *event_recorder_entry,
-			   struct lttng_kernel_event_recorder *event_recorder_exit)
+			   struct lttng_kernel_event_common *event_entry,
+			   struct lttng_kernel_event_common *event_exit)
 {
 	int ret;
 	struct lttng_krp *lttng_krp;
@@ -187,10 +187,10 @@ int lttng_kretprobes_register(const char *name,
 	if (symbol_name[0] == '\0')
 		symbol_name = NULL;
 
-	ret = lttng_create_kprobe_event(name, event_recorder_entry, EVENT_ENTRY);
+	ret = lttng_create_kprobe_event(name, event_entry, EVENT_ENTRY);
 	if (ret)
 		goto error;
-	ret = lttng_create_kprobe_event(name, event_recorder_exit, EVENT_EXIT);
+	ret = lttng_create_kprobe_event(name, event_exit, EVENT_EXIT);
 	if (ret)
 		goto event_exit_error;
 	lttng_krp = kzalloc(sizeof(*lttng_krp), GFP_KERNEL);
@@ -206,21 +206,18 @@ int lttng_kretprobes_register(const char *name,
 			ret = -ENOMEM;
 			goto name_error;
 		}
-		lttng_krp->krp.kp.symbol_name =
-			alloc_symbol;
-		event_recorder_entry->priv->parent.u.kretprobe.symbol_name =
-			alloc_symbol;
-		event_recorder_exit->priv->parent.u.kretprobe.symbol_name =
-			alloc_symbol;
+		lttng_krp->krp.kp.symbol_name = alloc_symbol;
+		event_entry->priv->u.kretprobe.symbol_name = alloc_symbol;
+		event_exit->priv->u.kretprobe.symbol_name = alloc_symbol;
 	}
 	lttng_krp->krp.kp.offset = offset;
 	lttng_krp->krp.kp.addr = (void *) (unsigned long) addr;
 
 	/* Allow probe handler to find event structures */
-	lttng_krp->event[EVENT_ENTRY] = &event_recorder_entry->parent;
-	lttng_krp->event[EVENT_EXIT] = &event_recorder_exit->parent;
-	event_recorder_entry->priv->parent.u.kretprobe.lttng_krp = lttng_krp;
-	event_recorder_exit->priv->parent.u.kretprobe.lttng_krp = lttng_krp;
+	lttng_krp->event[EVENT_ENTRY] = event_entry;
+	lttng_krp->event[EVENT_EXIT] = event_exit;
+	event_entry->priv->u.kretprobe.lttng_krp = lttng_krp;
+	event_exit->priv->u.kretprobe.lttng_krp = lttng_krp;
 
 	/*
 	 * Both events must be unregistered before the kretprobe is
@@ -248,11 +245,11 @@ register_error:
 name_error:
 	kfree(lttng_krp);
 krp_error:
-	kfree(event_recorder_exit->priv->parent.desc->event_name);
-	kfree(event_recorder_exit->priv->parent.desc);
+	kfree(event_exit->priv->desc->event_name);
+	kfree(event_exit->priv->desc);
 event_exit_error:
-	kfree(event_recorder_entry->priv->parent.desc->event_name);
-	kfree(event_recorder_entry->priv->parent.desc);
+	kfree(event_entry->priv->desc->event_name);
+	kfree(event_entry->priv->desc);
 error:
 	return ret;
 }
@@ -266,9 +263,9 @@ void _lttng_kretprobes_unregister_release(struct kref *kref)
 	unregister_kretprobe(&lttng_krp->krp);
 }
 
-void lttng_kretprobes_unregister(struct lttng_kernel_event_recorder *event_recorder)
+void lttng_kretprobes_unregister(struct lttng_kernel_event_common *event)
 {
-	kref_put(&event_recorder->priv->parent.u.kretprobe.lttng_krp->kref_register,
+	kref_put(&event->priv->u.kretprobe.lttng_krp->kref_register,
 		_lttng_kretprobes_unregister_release);
 }
 EXPORT_SYMBOL_GPL(lttng_kretprobes_unregister);
@@ -281,11 +278,11 @@ void _lttng_kretprobes_release(struct kref *kref)
 	kfree(lttng_krp->krp.kp.symbol_name);
 }
 
-void lttng_kretprobes_destroy_private(struct lttng_kernel_event_recorder *event_recorder)
+void lttng_kretprobes_destroy_private(struct lttng_kernel_event_common *event)
 {
-	kfree(event_recorder->priv->parent.desc->event_name);
-	kfree(event_recorder->priv->parent.desc);
-	kref_put(&event_recorder->priv->parent.u.kretprobe.lttng_krp->kref_alloc,
+	kfree(event->priv->desc->event_name);
+	kfree(event->priv->desc);
+	kref_put(&event->priv->u.kretprobe.lttng_krp->kref_alloc,
 		_lttng_kretprobes_release);
 }
 EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private);
diff --git a/src/probes/lttng-uprobes.c b/src/probes/lttng-uprobes.c
index fed3a1d..b6531a7 100644
--- a/src/probes/lttng-uprobes.c
+++ b/src/probes/lttng-uprobes.c
@@ -113,7 +113,7 @@ static const struct lttng_kernel_tracepoint_class tp_class = {
  * Create event description.
  */
 static
-int lttng_create_uprobe_event(const char *name, struct lttng_kernel_event_recorder *event_recorder)
+int lttng_create_uprobe_event(const char *name, struct lttng_kernel_event_common *event)
 {
 	struct lttng_kernel_event_desc *desc;
 	int ret;
@@ -128,35 +128,7 @@ int lttng_create_uprobe_event(const char *name, struct lttng_kernel_event_record
 		goto error_str;
 	}
 	desc->owner = THIS_MODULE;
-	event_recorder->priv->parent.desc = desc;
-
-	return 0;
-
-error_str:
-	kfree(desc);
-	return ret;
-}
-
-/*
- * Create event_notifier description.
- */
-static
-int lttng_create_uprobe_event_notifier(const char *name, struct lttng_kernel_event_notifier *event_notifier)
-{
-	struct lttng_kernel_event_desc *desc;
-	int ret;
-
-	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
-	if (!desc)
-		return -ENOMEM;
-	desc->tp_class = &tp_class;
-	desc->event_name = kstrdup(name, GFP_KERNEL);
-	if (!desc->event_name) {
-		ret = -ENOMEM;
-		goto error_str;
-	}
-	desc->owner = THIS_MODULE;
-	event_notifier->priv->parent.desc = desc;
+	event->priv->desc = desc;
 
 	return 0;
 
@@ -276,51 +248,28 @@ inode_error:
 	return ret;
 }
 
-int lttng_uprobes_register_event(const char *name, int fd, struct lttng_kernel_event_recorder *event_recorder)
+int lttng_uprobes_register_event(const char *name, int fd, struct lttng_kernel_event_common *event)
 {
 	int ret = 0;
 
-	ret = lttng_create_uprobe_event(name, event_recorder);
+	ret = lttng_create_uprobe_event(name, event);
 	if (ret)
 		goto error;
 
-	ret = lttng_uprobes_register(&event_recorder->priv->parent.u.uprobe, fd);
+	ret = lttng_uprobes_register(&event->priv->u.uprobe, fd);
 	if (ret)
 		goto register_error;
 
 	return 0;
 
 register_error:
-	kfree(event_recorder->priv->parent.desc->event_name);
-	kfree(event_recorder->priv->parent.desc);
+	kfree(event->priv->desc->event_name);
+	kfree(event->priv->desc);
 error:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(lttng_uprobes_register_event);
 
-int lttng_uprobes_register_event_notifier(const char *name, int fd,
-		struct lttng_kernel_event_notifier *event_notifier)
-{
-	int ret = 0;
-
-	ret = lttng_create_uprobe_event_notifier(name, event_notifier);
-	if (ret)
-		goto error;
-
-	ret = lttng_uprobes_register(&event_notifier->priv->parent.u.uprobe, fd);
-	if (ret)
-		goto register_error;
-
-	return 0;
-
-register_error:
-	kfree(event_notifier->priv->parent.desc->event_name);
-	kfree(event_notifier->priv->parent.desc);
-error:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(lttng_uprobes_register_event_notifier);
-
 static
 void lttng_uprobes_unregister(struct inode *inode, struct list_head *head)
 {
@@ -337,23 +286,17 @@ void lttng_uprobes_unregister(struct inode *inode, struct list_head *head)
 	}
 }
 
-void lttng_uprobes_unregister_event(struct lttng_kernel_event_recorder *event_recorder)
+void lttng_uprobes_unregister_event(struct lttng_kernel_event_common *event)
 {
-	lttng_uprobes_unregister(event_recorder->priv->parent.u.uprobe.inode, &event_recorder->priv->parent.u.uprobe.head);
+	lttng_uprobes_unregister(event->priv->u.uprobe.inode, &event->priv->u.uprobe.head);
 }
 EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event);
 
-void lttng_uprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
-{
-	lttng_uprobes_unregister(event_notifier->priv->parent.u.uprobe.inode, &event_notifier->priv->parent.u.uprobe.head);
-}
-EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event_notifier);
-
-void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_recorder *event_recorder)
+void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_common *event)
 {
-	iput(event_recorder->priv->parent.u.uprobe.inode);
-	kfree(event_recorder->priv->parent.desc->event_name);
-	kfree(event_recorder->priv->parent.desc);
+	iput(event->priv->u.uprobe.inode);
+	kfree(event->priv->desc->event_name);
+	kfree(event->priv->desc);
 }
 EXPORT_SYMBOL_GPL(lttng_uprobes_destroy_event_private);