+#define __TP_COMBINE_TOKENS(_tokena, _tokenb) \
+ _tokena##_tokenb
+#define _TP_COMBINE_TOKENS(_tokena, _tokenb) \
+ __TP_COMBINE_TOKENS(_tokena, _tokenb)
+#define __TP_COMBINE_TOKENS3(_tokena, _tokenb, _tokenc) \
+ _tokena##_tokenb##_tokenc
+#define _TP_COMBINE_TOKENS3(_tokena, _tokenb, _tokenc) \
+ __TP_COMBINE_TOKENS3(_tokena, _tokenb, _tokenc)
+#define __TP_COMBINE_TOKENS4(_tokena, _tokenb, _tokenc, _tokend) \
+ _tokena##_tokenb##_tokenc##_tokend
+#define _TP_COMBINE_TOKENS4(_tokena, _tokenb, _tokenc, _tokend) \
+ __TP_COMBINE_TOKENS4(_tokena, _tokenb, _tokenc, _tokend)
+
+/* _TP_EXVAR* extract the var names. */
+#define _TP_EXVAR0()
+#define _TP_EXVAR2(a,b) b
+#define _TP_EXVAR4(a,b,c,d) b,d
+#define _TP_EXVAR6(a,b,c,d,e,f) b,d,f
+#define _TP_EXVAR8(a,b,c,d,e,f,g,h) b,d,f,h
+#define _TP_EXVAR10(a,b,c,d,e,f,g,h,i,j) b,d,f,h,j
+#define _TP_EXVAR12(a,b,c,d,e,f,g,h,i,j,k,l) b,d,f,h,j,l
+#define _TP_EXVAR14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) b,d,f,h,j,l,n
+#define _TP_EXVAR16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) b,d,f,h,j,l,n,p
+#define _TP_EXVAR18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) b,d,f,h,j,l,n,p,r
+#define _TP_EXVAR20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) b,d,f,h,j,l,n,p,r,t
+
+#define _TP_EXDATA_VAR0() __tp_data
+#define _TP_EXDATA_VAR2(a,b) __tp_data,b
+#define _TP_EXDATA_VAR4(a,b,c,d) __tp_data,b,d
+#define _TP_EXDATA_VAR6(a,b,c,d,e,f) __tp_data,b,d,f
+#define _TP_EXDATA_VAR8(a,b,c,d,e,f,g,h) __tp_data,b,d,f,h
+#define _TP_EXDATA_VAR10(a,b,c,d,e,f,g,h,i,j) __tp_data,b,d,f,h,j
+#define _TP_EXDATA_VAR12(a,b,c,d,e,f,g,h,i,j,k,l) __tp_data,b,d,f,h,j,l
+#define _TP_EXDATA_VAR14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) __tp_data,b,d,f,h,j,l,n
+#define _TP_EXDATA_VAR16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) __tp_data,b,d,f,h,j,l,n,p
+#define _TP_EXDATA_VAR18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) __tp_data,b,d,f,h,j,l,n,p,r
+#define _TP_EXDATA_VAR20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) __tp_data,b,d,f,h,j,l,n,p,r,t
+
+/* _TP_EXPROTO* extract tuples of type, var */
+#define _TP_EXPROTO0()
+#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_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 = __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 *data) \
+{ \
+ __tracepoint_probe_register(name, func, data, \
+ __tracepoint_##_provider##___##_name.signature); \
+} \
+static inline void __tracepoint_unregister_##_provider##___##_name(char *name, \
+ void *func, void *data) \
+{ \
+ __tracepoint_probe_unregister(name, func, data); \
+}
+
+extern int __tracepoint_probe_register(const char *name, void *func, void *data,
+ const char *signature);
+extern int __tracepoint_probe_unregister(const char *name, void *func, void *data);