+#ifdef TRACEPOINT_DEFINE
+
+#ifndef _LTTNG_UST_TRACEPOINT_DEFINE_ONCE
+#define _LTTNG_UST_TRACEPOINT_DEFINE_ONCE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These weak symbols, the constructor, and destructor take care of
+ * registering only _one_ instance of the tracepoints per shared-ojbect
+ * (or for the whole main program).
+ */
+extern struct lttng_ust_tracepoint * const __start___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+
+/*
+ * When TRACEPOINT_PROBE_DYNAMIC_LINKAGE is defined, we do not emit a
+ * unresolved symbol that requires the provider to be linked in. When
+ * TRACEPOINT_PROBE_DYNAMIC_LINKAGE is not defined, we emit an
+ * unresolved symbol that depends on having the provider linked in,
+ * otherwise the linker complains. This deals with use of static
+ * libraries, ensuring that the linker does not remove the provider
+ * object from the executable.
+ */
+#ifdef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#define _TRACEPOINT_UNDEFINED_REF(provider) NULL
+#else /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
+#define _TRACEPOINT_UNDEFINED_REF(provider) &__tracepoint_provider_##provider
+#endif /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
+
+/*
+ * Note: to allow PIC code, we need to allow the linker to update the pointers
+ * in the __tracepoints_ptrs section.
+ * Therefore, this section is _not_ const (read-only).
+ */
+#define _TP_EXTRACT_STRING(...) #__VA_ARGS__
+
+#undef _DEFINE_TRACEPOINT
+#define _DEFINE_TRACEPOINT(_provider, _name, _args) \
+ extern int __tracepoint_provider_##_provider; \
+ static const char __tp_strtab_##_provider##___##_name[] \
+ __attribute__((section("__tracepoints_strings"))) = \
+ #_provider ":" #_name; \
+ struct lttng_ust_tracepoint __tracepoint_##_provider##___##_name \
+ __attribute__((section("__tracepoints"))) = \
+ { \
+ __tp_strtab_##_provider##___##_name, \
+ 0, \
+ NULL, \
+ _TRACEPOINT_UNDEFINED_REF(_provider), \
+ _TP_EXTRACT_STRING(_args), \
+ { }, \
+ }; \
+ static struct lttng_ust_tracepoint * \
+ __tracepoint_ptr_##_provider##___##_name \
+ __attribute__((section("__tracepoints_ptrs"), used)) \
+ __lttng_ust_variable_attribute_no_sanitize_address = \
+ &__tracepoint_##_provider##___##_name;
+
+static void lttng_ust_notrace __attribute__((constructor(LTTNG_UST_CONSTRUCTOR_PRIO)))
+__tracepoints__ptrs_init(void);
+static void
+__tracepoints__ptrs_init(void)
+{
+ if (__tracepoint_ptrs_registered++)
+ return;
+ if (!tracepoint_dlopen_ptr)
+ tracepoint_dlopen_ptr = &tracepoint_dlopen;
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ tracepoint_dlopen_ptr->liblttngust_handle =
+ dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
+ if (!tracepoint_dlopen_ptr->liblttngust_handle)
+ return;
+ if (!tracepoint_destructors_syms_ptr)
+ tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+ tracepoint_dlopen_ptr->tracepoint_register_lib =
+ URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *, int),
+ dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+ "tracepoint_register_lib"));
+ tracepoint_dlopen_ptr->tracepoint_unregister_lib =
+ URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *),
+ dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+ "tracepoint_unregister_lib"));
+ tracepoint_destructors_syms_ptr->old_tracepoint_disable_destructors =
+ URCU_FORCE_CAST(int *,
+ dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+ "__tracepoints__disable_destructors"));
+ tracepoint_destructors_syms_ptr->tracepoint_disable_destructors =
+ URCU_FORCE_CAST(void (*)(void),
+ dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+ "tp_disable_destructors"));
+ tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state =
+ URCU_FORCE_CAST(int (*)(void),
+ dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+ "tp_get_destructors_state"));
+ __tracepoint__init_urcu_sym();
+ if (tracepoint_dlopen_ptr->tracepoint_register_lib) {
+ tracepoint_dlopen_ptr->tracepoint_register_lib(__start___tracepoints_ptrs,
+ __stop___tracepoints_ptrs -
+ __start___tracepoints_ptrs);
+ }
+}
+
+static void lttng_ust_notrace __attribute__((destructor(LTTNG_UST_CONSTRUCTOR_PRIO)))
+__tracepoints__ptrs_destroy(void);
+static void
+__tracepoints__ptrs_destroy(void)
+{
+ int ret;
+
+ if (--__tracepoint_ptrs_registered)
+ return;
+ if (!tracepoint_dlopen_ptr)
+ tracepoint_dlopen_ptr = &tracepoint_dlopen;
+ if (!tracepoint_destructors_syms_ptr)
+ tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+ if (tracepoint_dlopen_ptr->tracepoint_unregister_lib)
+ tracepoint_dlopen_ptr->tracepoint_unregister_lib(__start___tracepoints_ptrs);
+ if (tracepoint_dlopen_ptr->liblttngust_handle
+ && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state
+ && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()
+ && !__tracepoint_ptrs_registered) {
+ ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
+ if (ret) {
+ fprintf(stderr, "Error (%d) in dlclose\n", ret);
+ abort();
+ }
+ memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr));
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LTTNG_UST_TRACEPOINT_DEFINE_ONCE */
+
+#else /* TRACEPOINT_DEFINE */
+
+#undef _DEFINE_TRACEPOINT
+#define _DEFINE_TRACEPOINT(_provider, _name, _args)
+
+#endif /* #else TRACEPOINT_DEFINE */
+
+#ifndef TRACEPOINT_ENUM
+
+/*
+ * Tracepoint Enumerations
+ *
+ * The enumeration is a mapping between an integer, or range of integers, and
+ * a string. It can be used to have a more compact trace in cases where the
+ * possible values for a field are limited:
+ *
+ * An example:
+ *
+ * TRACEPOINT_ENUM(someproject_component, enumname,
+ * TP_ENUM_VALUES(
+ * ctf_enum_value("even", 0)
+ * ctf_enum_value("uneven", 1)
+ * ctf_enum_range("twoto4", 2, 4)
+ * ctf_enum_value("five", 5)
+ * )
+ * )
+ *
+ * Where "someproject_component" is the name of the component this enumeration
+ * belongs to and "enumname" identifies this enumeration. Inside the
+ * TP_ENUM_VALUES macro is the actual mapping. Each string value can map
+ * to either a single value with ctf_enum_value or a range of values
+ * with ctf_enum_range.
+ *
+ * Enumeration ranges may overlap, but the behavior is implementation-defined,
+ * each trace reader will handle overlapping as it wishes.
+ *
+ * That enumeration can then be used in a field inside the TP_FIELD macro using
+ * the following line:
+ *
+ * ctf_enum(someproject_component, enumname, enumtype, enumfield, enumval)
+ *
+ * Where "someproject_component" and "enumname" match those in the
+ * TRACEPOINT_ENUM, "enumtype" is a signed or unsigned integer type
+ * backing the enumeration, "enumfield" is the name of the field and
+ * "enumval" is the value.
+ */
+
+#define TRACEPOINT_ENUM(provider, name, values)
+
+#endif /* #ifndef TRACEPOINT_ENUM */
+