#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)
extern int __tracepoint_probe_register(const char *name, void *func, void *data);
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
/*
__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;
-
/*
* These weak symbols, the constructor, and destructor take care of
* registering only _one_ instance of the tracepoints per shared-ojbect
__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));
}
}
*
* 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 >)