X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=include%2Flttng%2Ftracepoint.h;h=a224caebcd8485cf731648a0b6ce0e718d8d0bae;hb=5cd29ace704432c7a421f7749ef8591e30e1894c;hp=ffae20a2f9854195ab3642651979d13f0883e4ed;hpb=b728d87e617189fe9898a9492a559ecf949d2348;p=lttng-ust.git diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index ffae20a2..a224caeb 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -15,17 +15,18 @@ */ #include -#include +#include #include +#include /* for dlopen */ #ifdef __cplusplus extern "C" { #endif -#define tracepoint(provider, name, ...) \ - do { \ - if (caa_unlikely(__tracepoint_##provider##_##name.state)) \ - __tracepoint_##provider##_##name(__VA_ARGS__); \ +#define tracepoint(provider, name, ...) \ + do { \ + if (caa_unlikely(__tracepoint_##provider##___##name.state)) \ + __tracepoint_cb_##provider##___##name(__VA_ARGS__); \ } while (0) #define TP_ARGS(...) __VA_ARGS__ @@ -36,10 +37,20 @@ extern "C" { * fine too). * Each tuple is also separated by a comma. */ -#define _TP_COMBINE_TOKENS1(_tokena, _tokenb) _tokena##_tokenb -#define _TP_COMBINE_TOKENS(_tokena, _tokenb) _TP_COMBINE_TOKENS1(_tokena, _tokenb) +#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 vars names. */ +/* _TP_EXVAR* extract the var names. */ #define _TP_EXVAR0() #define _TP_EXVAR2(a,b) b #define _TP_EXVAR4(a,b,c,d) b,d @@ -92,45 +103,60 @@ extern "C" { /* 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_SPLIT, N)(__VA_ARGS__)) -#define _TP_VARS_N(N, ...) _TP_PARAMS(TP_COMBINE_TOKENS(_TP_EVEN, N)(__VA_ARGS__)) -#define _TP_DATA_PROTO_N(N, ...) _TP_PARAMS(TP_COMBINE_TOKENS(_TP_SPLIT_DATA, N)(__VA_ARGS__)) -#define _TP_DATA_VARS_N(N, ...) _TP_PARAMS(TP_COMBINE_TOKENS(_TP_EVEN_DATA, N)(__VA_ARGS__)) +#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_VARS(...) _TP_VARS_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_VARS(...) _TP_DATA_VARS_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__ +#ifdef _LGPL_SOURCE +#define _TP_RCU_LINK_TEST() 1 +#else +#define _TP_RCU_LINK_TEST() rcu_read_lock_bp +#endif + #define _DECLARE_TRACEPOINT(provider, name, ...) \ -static inline void __tracepoint_##provider##_##name(_TP_ARGS_DATA_PROTO(__VA_ARGS__)) \ +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; \ rcu_read_lock_bp(); \ - p = rcu_dereference(__tracepoint_##provider##_##name.probes); \ - if (caa_unlikely(!p)) \ + __tp_probe = rcu_dereference_bp(__tracepoint_##provider##___##name.probes); \ + if (caa_unlikely(!__tp_probe)) \ goto end; \ do { \ - void *__tp_data = p->priv; \ + void *__tp_cb = __tp_probe->func; \ + void *__tp_data = __tp_probe->data; \ \ - (*p->callback)(_TP_ARGS_DATA_VARS(__VA_ARGS__)); \ - __tp_probe++; \ - } while (*__tp_probe); \ + URCU_FORCE_CAST(void (*)(_TP_ARGS_DATA_PROTO(__VA_ARGS__)), __tp_cb) \ + (_TP_ARGS_DATA_VAR(__VA_ARGS__)); \ + } while ((++__tp_probe)->func); \ end: \ rcu_read_unlock_bp(); \ } \ -static inline void __tracepoint_register_##provider##_##name(char *name, \ - void *callback, void *priv) \ +static inline void __tracepoint_register_##provider##___##name(char *name, \ + void *func, void *data) \ { \ - __tracepoint_probe_register(name, callback, data); \ + __tracepoint_probe_register(name, func, data); \ } \ -static inline void __tracepoint_unregister_##provider##_##name(char *name, \ - void *callback, void *priv) \ +static inline void __tracepoint_unregister_##provider##___##name(char *name, \ + void *func, void *data) \ { \ - __tracepoint_probe_unregister(name, callback, data); \ + __tracepoint_probe_unregister(name, func, data); \ } +extern int __tracepoint_probe_register(const char *name, void *func, void *data); +extern int __tracepoint_probe_unregister(const char *name, void *func, void *data); + +#ifdef TRACEPOINT_DEFINE + /* * Note: to allow PIC code, we need to allow the linker to update the pointers * in the __tracepoints_ptrs section. @@ -147,11 +173,10 @@ static inline void __tracepoint_unregister_##provider##_##name(char *name, \ __attribute__((used, section("__tracepoints_ptrs"))) = \ &__tracepoint_##provider##___##name; -extern int __tracepoint_probe_register(const char *name, void *callback, void *priv); -extern int __tracepoint_probe_unregister(const char *name, void *callback, void *priv); -extern int tracepoint_register_lib(struct tracepoint * const *tracepoints_start, +static int (*tracepoint_register_lib)(struct tracepoint * const *tracepoints_start, int tracepoints_count); -extern int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start); +static int (*tracepoint_unregister_lib)(struct tracepoint * const *tracepoints_start); +static void *liblttngust_handle; /* * These weak symbols, the constructor, and destructor take care of @@ -169,6 +194,18 @@ static void __attribute__((constructor)) __tracepoints__init(void) { if (__tracepoint_registered++) return; + + liblttngust_handle = dlopen("liblttng-ust.so", RTLD_NOW | RTLD_GLOBAL); + if (!liblttngust_handle) + return; + tracepoint_register_lib = + URCU_FORCE_CAST(int (*)(struct tracepoint * const *, int), + dlsym(liblttngust_handle, + "tracepoint_register_lib")); + tracepoint_unregister_lib = + URCU_FORCE_CAST(int (*)(struct tracepoint * const *), + dlsym(liblttngust_handle, + "tracepoint_unregister_lib")); tracepoint_register_lib(__start___tracepoints_ptrs, __stop___tracepoints_ptrs - __start___tracepoints_ptrs); @@ -176,11 +213,25 @@ static void __attribute__((constructor)) __tracepoints__init(void) static void __attribute__((destructor)) __tracepoints__destroy(void) { + int ret; if (--__tracepoint_registered) return; - tracepoint_unregister_lib(__start___tracepoints_ptrs); + if (tracepoint_unregister_lib) + tracepoint_unregister_lib(__start___tracepoints_ptrs); + if (liblttngust_handle) { + tracepoint_unregister_lib = NULL; + tracepoint_register_lib = NULL; + ret = dlclose(liblttngust_handle); + assert(!ret); + } } +#else /* TRACEPOINT_DEFINE */ + +#define _DEFINE_TRACEPOINT(provider, name) + +#endif /* #else TRACEPOINT_DEFINE */ + #ifdef __cplusplus } #endif @@ -270,14 +321,15 @@ static void __attribute__((destructor)) __tracepoints__destroy(void) * the provider:event identifier is limited to 127 characters. */ - #define TRACEPOINT_EVENT(provider, name, args, fields) \ - _DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) + _DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) \ + _DEFINE_TRACEPOINT(provider, name) #define TRACEPOINT_EVENT_CLASS(provider, name, args, fields) #define TRACEPOINT_EVENT_INSTANCE(provider, _template, name, args) \ - _DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) + _DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) \ + _DEFINE_TRACEPOINT(provider, name) #endif /* #ifndef TRACEPOINT_EVENT */ @@ -292,29 +344,30 @@ static void __attribute__((destructor)) __tracepoints__destroy(void) * Typical use of these loglevels: * * 1) Declare the mapping between loglevel names and an integer values - * within TRACEPOINT_LOGLEVEL_ENUM, using TP_LOGLEVEL for each tuple. - * Do _NOT_ add comma (,) nor semicolon (;) between the - * TRACEPOINT_LOGLEVEL_ENUM entries. Do _NOT_ add comma (,) nor - * semicolon (;) after the TRACEPOINT_LOGLEVEL_ENUM declaration. The - * name should be a proper C99 identifier. + * within TRACEPOINT_LOGLEVEL_ENUM(), using tp_loglevel() for each + * tuple. Do _NOT_ add comma (,) nor semicolon (;) between the + * tp_loglevel entries contained within TRACEPOINT_LOGLEVEL_ENUM(). + * Do _NOT_ add comma (,) nor semicolon (;) after the + * TRACEPOINT_LOGLEVEL_ENUM() declaration. The name should be a + * proper C99 identifier. * * TRACEPOINT_LOGLEVEL_ENUM( - * TP_LOGLEVEL( < loglevel_name >, < value > ) - * TP_LOGLEVEL( < loglevel_name >, < value > ) + * tp_loglevel( < loglevel_name >, < value > ) + * tp_loglevel( < loglevel_name >, < value > ) * ... * ) * * e.g.: * * TRACEPOINT_LOGLEVEL_ENUM( - * TP_LOGLEVEL(LOG_EMERG, 0) - * TP_LOGLEVEL(LOG_ALERT, 1) - * TP_LOGLEVEL(LOG_CRIT, 2) - * TP_LOGLEVEL(LOG_ERR, 3) - * TP_LOGLEVEL(LOG_WARNING, 4) - * TP_LOGLEVEL(LOG_NOTICE, 5) - * TP_LOGLEVEL(LOG_INFO, 6) - * TP_LOGLEVEL(LOG_DEBUG, 7) + * tp_loglevel(LOG_EMERG, 0) + * tp_loglevel(LOG_ALERT, 1) + * tp_loglevel(LOG_CRIT, 2) + * tp_loglevel(LOG_ERR, 3) + * tp_loglevel(LOG_WARNING, 4) + * tp_loglevel(LOG_NOTICE, 5) + * tp_loglevel(LOG_INFO, 6) + * tp_loglevel(LOG_DEBUG, 7) * ) * * 2) Then, declare tracepoint loglevels for tracepoints. A @@ -333,7 +386,7 @@ static void __attribute__((destructor)) __tracepoints__destroy(void) * provider. */ -#define TRACEPOINT_LOGLEVEL_ENUM() -#define TRACEPOINT_LOGLEVEL(name, loglevel) +#define TRACEPOINT_LOGLEVEL_ENUM(...) +#define TRACEPOINT_LOGLEVEL(provider, name, loglevel) #endif /* #ifndef TRACEPOINT_LOGLEVEL */