#include <lttng/tracepoint-rcu.h>
#include <urcu/compiler.h>
#include <dlfcn.h> /* for dlopen */
+#include <string.h> /* for memset */
#include <assert.h>
+#include <lttng/ust-config.h> /* for sdt */
+
+#ifdef LTTNG_UST_HAVE_SDT_INTEGRATION
+#define SDT_USE_VARIADIC
+#include <sys/sdt.h>
+#else
+#define STAP_PROBEV(...)
+#endif
#ifdef __cplusplus
extern "C" {
#define tracepoint(provider, name, ...) \
do { \
+ STAP_PROBEV(provider, name, ## __VA_ARGS__); \
if (caa_unlikely(__tracepoint_##provider##___##name.state)) \
__tracepoint_cb_##provider##___##name(__VA_ARGS__); \
} while (0)
static inline void __tracepoint_register_##_provider##___##_name(char *name, \
void *func, void *data) \
{ \
- __tracepoint_probe_register(name, func, 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);
+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);
+/*
+ * tracepoint dynamic linkage handling (callbacks). Hidden visibility:
+ * shared across objects in a module/main executable.
+ */
+struct tracepoint_dlopen {
+ void *liblttngust_handle;
+
+ int (*tracepoint_register_lib)(struct tracepoint * const *tracepoints_start,
+ int tracepoints_count);
+ int (*tracepoint_unregister_lib)(struct tracepoint * const *tracepoints_start);
+#ifndef _LGPL_SOURCE
+ void (*rcu_read_lock_sym_bp)(void);
+ void (*rcu_read_unlock_sym_bp)(void);
+ void *(*rcu_dereference_sym_bp)(void *p);
+#endif
+};
+
+extern struct tracepoint_dlopen tracepoint_dlopen;
+
#ifdef TRACEPOINT_DEFINE
/*
* object from the executable.
*/
#ifdef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
-#define _TRACEPOINT_UNDEFINED_REF(provider)
+#define _TRACEPOINT_UNDEFINED_REF(provider) NULL
#else /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
-#define _TRACEPOINT_UNDEFINED_REF(provider) \
- &__tracepoint_provider_##provider,
+#define _TRACEPOINT_UNDEFINED_REF(provider) &__tracepoint_provider_##provider
#endif /* TRACEPOINT_PROBE_DYNAMIC_LINKAGE */
/*
* in the __tracepoints_ptrs section.
* Therefore, this section is _not_ const (read-only).
*/
-#define _DEFINE_TRACEPOINT(provider, name) \
- extern int __tracepoint_provider_##provider; \
- static const char __tp_strtab_##provider##___##name[] \
+#define _TP_EXTRACT_STRING(...) #__VA_ARGS__
+
+#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 tracepoint __tracepoint_##provider##___##name \
+ #_provider ":" #_name; \
+ struct tracepoint __tracepoint_##_provider##___##_name \
__attribute__((section("__tracepoints"))) = \
- { __tp_strtab_##provider##___##name, 0, NULL, _TRACEPOINT_UNDEFINED_REF(provider) }; \
- static struct tracepoint * __tracepoint_ptr_##provider##___##name \
+ { \
+ __tp_strtab_##_provider##___##_name, \
+ 0, \
+ NULL, \
+ _TRACEPOINT_UNDEFINED_REF(_provider), \
+ _TP_EXTRACT_STRING(_args), \
+ }; \
+ static struct tracepoint * __tracepoint_ptr_##_provider##___##_name \
__attribute__((used, section("__tracepoints_ptrs"))) = \
- &__tracepoint_##provider##___##name;
-
-static int (*tracepoint_register_lib)(struct tracepoint * const *tracepoints_start,
- int tracepoints_count);
-static int (*tracepoint_unregister_lib)(struct tracepoint * const *tracepoints_start);
-static void *liblttngust_handle;
+ &__tracepoint_##_provider##___##_name;
/*
* These weak symbols, the constructor, and destructor take care of
__attribute__((weak, visibility("hidden")));
int __tracepoint_registered
__attribute__((weak, visibility("hidden")));
+struct tracepoint_dlopen tracepoint_dlopen
+ __attribute__((weak, visibility("hidden")));
static void __attribute__((constructor)) __tracepoints__init(void)
{
if (__tracepoint_registered++)
return;
- liblttngust_handle = dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
- if (!liblttngust_handle)
+ tracepoint_dlopen.liblttngust_handle =
+ dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
+ if (!tracepoint_dlopen.liblttngust_handle)
return;
- tracepoint_register_lib =
+ tracepoint_dlopen.tracepoint_register_lib =
URCU_FORCE_CAST(int (*)(struct tracepoint * const *, int),
- dlsym(liblttngust_handle,
+ dlsym(tracepoint_dlopen.liblttngust_handle,
"tracepoint_register_lib"));
- tracepoint_unregister_lib =
+ tracepoint_dlopen.tracepoint_unregister_lib =
URCU_FORCE_CAST(int (*)(struct tracepoint * const *),
- dlsym(liblttngust_handle,
+ dlsym(tracepoint_dlopen.liblttngust_handle,
"tracepoint_unregister_lib"));
#ifndef _LGPL_SOURCE
- tp_rcu_read_lock_bp =
+ tracepoint_dlopen.rcu_read_lock_sym_bp =
URCU_FORCE_CAST(void (*)(void),
- dlsym(liblttngust_handle,
+ dlsym(tracepoint_dlopen.liblttngust_handle,
"tp_rcu_read_lock_bp"));
- tp_rcu_read_unlock_bp =
+ tracepoint_dlopen.rcu_read_unlock_sym_bp =
URCU_FORCE_CAST(void (*)(void),
- dlsym(liblttngust_handle,
+ dlsym(tracepoint_dlopen.liblttngust_handle,
"tp_rcu_read_unlock_bp"));
- tp_rcu_dereference_sym_bp =
+ tracepoint_dlopen.rcu_dereference_sym_bp =
URCU_FORCE_CAST(void *(*)(void *p),
- dlsym(liblttngust_handle,
+ dlsym(tracepoint_dlopen.liblttngust_handle,
"tp_rcu_dereference_sym_bp"));
#endif
- tracepoint_register_lib(__start___tracepoints_ptrs,
+ tracepoint_dlopen.tracepoint_register_lib(__start___tracepoints_ptrs,
__stop___tracepoints_ptrs -
__start___tracepoints_ptrs);
}
static void __attribute__((destructor)) __tracepoints__destroy(void)
{
int ret;
+
if (--__tracepoint_registered)
return;
- 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);
+ if (tracepoint_dlopen.tracepoint_unregister_lib)
+ tracepoint_dlopen.tracepoint_unregister_lib(__start___tracepoints_ptrs);
+ if (tracepoint_dlopen.liblttngust_handle) {
+ ret = dlclose(tracepoint_dlopen.liblttngust_handle);
assert(!ret);
+ memset(&tracepoint_dlopen, 0, sizeof(tracepoint_dlopen));
}
}
#else /* TRACEPOINT_DEFINE */
-#define _DEFINE_TRACEPOINT(provider, name)
+#define _DEFINE_TRACEPOINT(_provider, _name, _args)
#endif /* #else TRACEPOINT_DEFINE */
#define TRACEPOINT_EVENT(provider, name, args, fields) \
_DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) \
- _DEFINE_TRACEPOINT(provider, name)
+ _DEFINE_TRACEPOINT(provider, name, _TP_PARAMS(args))
#define TRACEPOINT_EVENT_CLASS(provider, name, args, fields)
#define TRACEPOINT_EVENT_INSTANCE(provider, _template, name, args) \
_DECLARE_TRACEPOINT(provider, name, _TP_PARAMS(args)) \
- _DEFINE_TRACEPOINT(provider, name)
+ _DEFINE_TRACEPOINT(provider, name, _TP_PARAMS(args))
#endif /* #ifndef TRACEPOINT_EVENT */
*
* Declare tracepoint loglevels for tracepoints. A TRACEPOINT_EVENT
* should be declared prior to the the TRACEPOINT_LOGLEVEL for a given
- * tracepoint name. The first field is the name of the tracepoint, the
- * second field is the loglevel name.
+ * tracepoint name. The first field is the provider name, the second
+ * field is the name of the tracepoint, the third field is the loglevel
+ * name.
*
* TRACEPOINT_LOGLEVEL(< [com_company_]project[_component] >, < event >,
* < loglevel_name >)