+/* Preprocessor trick to count arguments. Inspired from sdt.h. */
+#define _TP_NARGS(...) __TP_NARGS(__VA_ARGS__, 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+#define __TP_NARGS(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, N, ...) N
+#define _TP_PROTO_N(N, ...) _TP_PARAMS(_TP_COMBINE_TOKENS(_TP_EXPROTO, N)(__VA_ARGS__))
+#define _TP_VAR_N(N, ...) _TP_PARAMS(_TP_COMBINE_TOKENS(_TP_EXVAR, N)(__VA_ARGS__))
+#define _TP_DATA_PROTO_N(N, ...) _TP_PARAMS(_TP_COMBINE_TOKENS(_TP_EXDATA_PROTO, N)(__VA_ARGS__))
+#define _TP_DATA_VAR_N(N, ...) _TP_PARAMS(_TP_COMBINE_TOKENS(_TP_EXDATA_VAR, N)(__VA_ARGS__))
+#define _TP_ARGS_PROTO(...) _TP_PROTO_N(_TP_NARGS(0, ##__VA_ARGS__), ##__VA_ARGS__)
+#define _TP_ARGS_VAR(...) _TP_VAR_N(_TP_NARGS(0, ##__VA_ARGS__), ##__VA_ARGS__)
+#define _TP_ARGS_DATA_PROTO(...) _TP_DATA_PROTO_N(_TP_NARGS(0, ##__VA_ARGS__), ##__VA_ARGS__)
+#define _TP_ARGS_DATA_VAR(...) _TP_DATA_VAR_N(_TP_NARGS(0, ##__VA_ARGS__), ##__VA_ARGS__)
+#define _TP_PARAMS(...) __VA_ARGS__
+
+#define _DECLARE_TRACEPOINT(_provider, _name, ...) \
+extern struct tracepoint __tracepoint_##_provider##___##_name; \
+static inline lttng_ust_notrace \
+void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__)); \
+static inline \
+void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__)) \
+{ \
+ struct tracepoint_probe *__tp_probe; \
+ \
+ if (!TP_RCU_LINK_TEST()) \
+ return; \
+ tp_rcu_read_lock_bp(); \
+ __tp_probe = tp_rcu_dereference_bp(__tracepoint_##_provider##___##_name.probes); \
+ if (caa_unlikely(!__tp_probe)) \
+ goto end; \
+ do { \
+ void (*__tp_cb)(void) = __tp_probe->func; \
+ void *__tp_data = __tp_probe->data; \
+ \
+ URCU_FORCE_CAST(void (*)(_TP_ARGS_DATA_PROTO(__VA_ARGS__)), __tp_cb) \
+ (_TP_ARGS_DATA_VAR(__VA_ARGS__)); \
+ } while ((++__tp_probe)->func); \
+end: \
+ tp_rcu_read_unlock_bp(); \
+} \
+static inline lttng_ust_notrace \
+void __tracepoint_register_##_provider##___##_name(char *name, \
+ void (*func)(void), void *data); \
+static inline \
+void __tracepoint_register_##_provider##___##_name(char *name, \
+ void (*func)(void), void *data) \
+{ \
+ __tracepoint_probe_register(name, func, data, \
+ __tracepoint_##_provider##___##_name.signature); \
+} \
+static inline lttng_ust_notrace \
+void __tracepoint_unregister_##_provider##___##_name(char *name, \
+ void (*func)(void), void *data); \
+static inline \
+void __tracepoint_unregister_##_provider##___##_name(char *name, \
+ void (*func)(void), void *data) \
+{ \
+ __tracepoint_probe_unregister(name, func, data); \
+}
+
+extern int __tracepoint_probe_register(const char *name, void (*func)(void),
+ void *data, const char *signature);
+extern int __tracepoint_probe_unregister(const char *name, void (*func)(void),
+ void *data);