+#define _TP_EXPROTO0() void
+#define _TP_EXPROTO1(a) void
+#define _TP_EXPROTO2(a,b) a b
+#define _TP_EXPROTO4(a,b,c,d) a b,c d
+#define _TP_EXPROTO6(a,b,c,d,e,f) a b,c d,e f
+#define _TP_EXPROTO8(a,b,c,d,e,f,g,h) a b,c d,e f,g h
+#define _TP_EXPROTO10(a,b,c,d,e,f,g,h,i,j) a b,c d,e f,g h,i j
+#define _TP_EXPROTO12(a,b,c,d,e,f,g,h,i,j,k,l) a b,c d,e f,g h,i j,k l
+#define _TP_EXPROTO14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) a b,c d,e f,g h,i j,k l,m n
+#define _TP_EXPROTO16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) a b,c d,e f,g h,i j,k l,m n,o p
+#define _TP_EXPROTO18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) a b,c d,e f,g h,i j,k l,m n,o p,q r
+#define _TP_EXPROTO20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) a b,c d,e f,g h,i j,k l,m n,o p,q r,s t
+
+#define _TP_EXDATA_PROTO0() void *__tp_data
+#define _TP_EXDATA_PROTO1(a) void *__tp_data
+#define _TP_EXDATA_PROTO2(a,b) void *__tp_data,a b
+#define _TP_EXDATA_PROTO4(a,b,c,d) void *__tp_data,a b,c d
+#define _TP_EXDATA_PROTO6(a,b,c,d,e,f) void *__tp_data,a b,c d,e f
+#define _TP_EXDATA_PROTO8(a,b,c,d,e,f,g,h) void *__tp_data,a b,c d,e f,g h
+#define _TP_EXDATA_PROTO10(a,b,c,d,e,f,g,h,i,j) void *__tp_data,a b,c d,e f,g h,i j
+#define _TP_EXDATA_PROTO12(a,b,c,d,e,f,g,h,i,j,k,l) void *__tp_data,a b,c d,e f,g h,i j,k l
+#define _TP_EXDATA_PROTO14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) void *__tp_data,a b,c d,e f,g h,i j,k l,m n
+#define _TP_EXDATA_PROTO16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) void *__tp_data,a b,c d,e f,g h,i j,k l,m n,o p
+#define _TP_EXDATA_PROTO18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) void *__tp_data,a b,c d,e f,g h,i j,k l,m n,o p,q r
+#define _TP_EXDATA_PROTO20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) void *__tp_data,a b,c d,e f,g h,i j,k l,m n,o p,q r,s t
+
+/* 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 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 void __tracepoint_register_##_provider##___##_name(char *name, \
+ void (*func)(void), void *data) \
+{ \
+ __tracepoint_probe_register(name, func, data, \
+ __tracepoint_##_provider##___##_name.signature); \
+} \
+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);