tracepoint: split provider and event name
[lttng-ust.git] / include / lttng / tracepoint.h
index 16348b86106c98e15abe58cf62b8fc11cdc43a4c..98c3c8dd89bfd2b6419bca7f6e15b255967209aa 100644 (file)
@@ -1,28 +1,12 @@
-#ifndef _LTTNG_TRACEPOINT_H
-#define _LTTNG_TRACEPOINT_H
-
 /*
- * Copyright 2011-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  */
 
+#ifndef _LTTNG_TRACEPOINT_H
+#define _LTTNG_TRACEPOINT_H
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <lttng/tracepoint-types.h>
 #include <urcu/system.h>
 #include <dlfcn.h>     /* for dlopen */
 #include <string.h>    /* for memset */
+
 #include <lttng/ust-config.h>  /* for sdt */
 #include <lttng/ust-compiler.h>
+#include <lttng/ust-tracer.h>
+
+#define LTTNG_UST_TRACEPOINT_NAME_LEN_MAX      256
 
 #ifdef LTTNG_UST_HAVE_SDT_INTEGRATION
-#define SDT_USE_VARIADIC
+/*
+ * Instead of using SDT_USE_VARIADIC from 'sys/sdt.h', use our own namespaced
+ * macros since the instrumented application might already have included
+ * 'sys/sdt.h' without variadic support.
+ */
 #include <sys/sdt.h>
-#define LTTNG_STAP_PROBEV STAP_PROBEV
+
+#define _LTTNG_UST_SDT_NARG(...) \
+       __LTTNG_UST_SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0)
+
+#define __LTTNG_UST_SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N
+
+#define _LTTNG_UST_SDT_PROBE_N(provider, name, N, ...) \
+       _SDT_PROBE(provider, name, N, (__VA_ARGS__))
+
+#define LTTNG_UST_STAP_PROBEV(provider, name, ...) \
+       _LTTNG_UST_SDT_PROBE_N(provider, name, _LTTNG_UST_SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)
+
 #else
-#define LTTNG_STAP_PROBEV(...)
+#define LTTNG_UST_STAP_PROBEV(...)
 #endif
 
 #ifdef __cplusplus
@@ -54,7 +57,7 @@ extern "C" {
 
 #define tracepoint(provider, name, ...)                                            \
        do {                                                                \
-               LTTNG_STAP_PROBEV(provider, name, ## __VA_ARGS__);          \
+               LTTNG_UST_STAP_PROBEV(provider, name, ## __VA_ARGS__);      \
                if (tracepoint_enabled(provider, name))                     \
                        do_tracepoint(provider, name, __VA_ARGS__);         \
        } while (0)
@@ -153,6 +156,25 @@ extern "C" {
 #define _TP_ARGS_DATA_VAR(...)         _TP_DATA_VAR_N(_TP_NARGS(0, ##__VA_ARGS__), ##__VA_ARGS__)
 #define _TP_PARAMS(...)                        __VA_ARGS__
 
+/*
+ * sizeof(#_provider) - 1 : length of the provider string (excluding \0).
+ * sizeof(#_name) - 1     : length of the name string (excluding \0).
+ * + 1                    : separator between provider and event name.
+ *
+ * Upper bound (inclusive) is LTTNG_UST_TRACEPOINT_NAME_LEN_MAX - 1 to
+ * account for \0.
+ *
+ * The comparison is:
+ *   left hand side:   sizeof(#_provider) - 1 + sizeof(#_name) - 1 + 1
+ *   right hand side:  LTTNG_UST_TRACEPOINT_NAME_LEN_MAX - 1
+ *   operator:         <=  (inclusive)
+ * Simplified in the code below.
+ */
+#define lttng_ust_tracepoint_validate_name_len(_provider, _name)                                               \
+       lttng_ust_static_assert(sizeof(#_provider) + sizeof(#_name) <= LTTNG_UST_TRACEPOINT_NAME_LEN_MAX,       \
+               "Tracepoint name length is too long",                                                           \
+               Tracepoint_name_length_is_too_long)
+
 /*
  * The tracepoint cb is marked always inline so we can distinguish
  * between caller's ip addresses within the probe using the return
@@ -160,17 +182,18 @@ extern "C" {
  */
 #define _DECLARE_TRACEPOINT(_provider, _name, ...)                                     \
 extern struct lttng_ust_tracepoint __tracepoint_##_provider##___##_name;               \
-static inline __attribute__((always_inline, unused)) lttng_ust_notrace                 \
-void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__));             \
+static inline                                                                          \
+void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__))              \
+       __attribute__((always_inline, unused)) lttng_ust_notrace;                       \
 static                                                                                 \
 void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__))              \
 {                                                                                      \
-       struct lttng_ust_tracepoint_probe *__tp_probe;                                          \
+       struct lttng_ust_tracepoint_probe *__tp_probe;                                  \
                                                                                        \
        if (caa_unlikely(!TP_RCU_LINK_TEST()))                                          \
                return;                                                                 \
-       tp_rcu_read_lock_bp();                                                          \
-       __tp_probe = tp_rcu_dereference_bp(__tracepoint_##_provider##___##_name.probes); \
+       tp_rcu_read_lock();                                                             \
+       __tp_probe = tp_rcu_dereference(__tracepoint_##_provider##___##_name.probes);   \
        if (caa_unlikely(!__tp_probe))                                                  \
                goto end;                                                               \
        do {                                                                            \
@@ -181,53 +204,64 @@ void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__))         \
                                (_TP_ARGS_DATA_VAR(__VA_ARGS__));                       \
        } while ((++__tp_probe)->func);                                                 \
 end:                                                                                   \
-       tp_rcu_read_unlock_bp();                                                        \
+       tp_rcu_read_unlock();                                                           \
 }                                                                                      \
-static inline lttng_ust_notrace                                                                \
-void __tracepoint_register_##_provider##___##_name(char *name,                         \
-               void (*func)(void), void *data);                                        \
 static inline                                                                          \
-void __tracepoint_register_##_provider##___##_name(char *name,                         \
+void __tracepoint_register_##_provider##___##_name(char *provider_name, char *event_name, \
+               void (*func)(void), void *data)                                         \
+       lttng_ust_notrace;                                                              \
+static inline                                                                          \
+void __tracepoint_register_##_provider##___##_name(char *provider_name, char *event_name, \
                void (*func)(void), void *data)                                         \
 {                                                                                      \
-       __tracepoint_probe_register(name, func, data,                                   \
+       __tracepoint_probe_register(provider_name, event_name, func, data,              \
                __tracepoint_##_provider##___##_name.signature);                        \
 }                                                                                      \
-static inline lttng_ust_notrace                                                                \
-void __tracepoint_unregister_##_provider##___##_name(char *name,                       \
-               void (*func)(void), void *data);                                        \
 static inline                                                                          \
-void __tracepoint_unregister_##_provider##___##_name(char *name,                       \
+void __tracepoint_unregister_##_provider##___##_name(char *provider_name, char *event_name, \
+               void (*func)(void), void *data)                                         \
+       lttng_ust_notrace;                                                              \
+static inline                                                                          \
+void __tracepoint_unregister_##_provider##___##_name(char *provider_name, char *event_name, \
                void (*func)(void), void *data)                                         \
 {                                                                                      \
-       __tracepoint_probe_unregister(name, func, data);                                \
+       __tracepoint_probe_unregister(provider_name, event_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);
+extern int __tracepoint_probe_register(const char *provider_name, const char *event_name,
+               void (*func)(void), void *data, const char *signature);
+extern int __tracepoint_probe_unregister(const char *provider_name, const char *event_name,
+               void (*func)(void), void *data);
 
 /*
  * tracepoint dynamic linkage handling (callbacks). Hidden visibility:
  * shared across objects in a module/main executable.
+ *
+ * IMPORTANT: this structure is part of the ABI between instrumented
+ * applications and UST. Fields need to be only added at the end, never
+ * reordered, never removed.
+ *
+ * The field @struct_size should be used to determine the size of the
+ * structure. It should be queried before using additional fields added
+ * at the end of the structure.
  */
 struct lttng_ust_tracepoint_dlopen {
+       uint32_t struct_size;
+
        void *liblttngust_handle;
 
        int (*tracepoint_register_lib)(struct lttng_ust_tracepoint * const *tracepoints_start,
                int tracepoints_count);
        int (*tracepoint_unregister_lib)(struct lttng_ust_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
+       void (*rcu_read_lock_sym)(void);
+       void (*rcu_read_unlock_sym)(void);
+       void *(*rcu_dereference_sym)(void *p);
+
+       /* End of base ABI. Fields below should be used after checking struct_size. */
 };
 
 extern struct lttng_ust_tracepoint_dlopen tracepoint_dlopen;
-
-#if defined(TRACEPOINT_DEFINE) || defined(TRACEPOINT_CREATE_PROBES)
+extern struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr;
 
 /*
  * These weak symbols, the constructor, and destructor take care of
@@ -239,61 +273,130 @@ int __tracepoint_registered
 int __tracepoint_ptrs_registered
        __attribute__((weak, visibility("hidden")));
 struct lttng_ust_tracepoint_dlopen tracepoint_dlopen
+               __attribute__((weak, visibility("hidden"))) = {
+       .struct_size = sizeof(struct lttng_ust_tracepoint_dlopen),
+};
+/*
+ * Deal with gcc O1 optimisation issues with weak hidden symbols. gcc
+ * 4.8 and prior does not have the same behavior for symbol scoping on
+ * 32-bit powerpc depending on the object size: symbols for objects of 8
+ * bytes or less have the same address throughout a module, whereas they
+ * have different addresses between compile units for objects larger
+ * than 8 bytes. Add this pointer indirection to ensure that the symbol
+ * scoping match that of the other weak hidden symbols found in this
+ * header.
+ */
+struct lttng_ust_tracepoint_dlopen *tracepoint_dlopen_ptr
        __attribute__((weak, visibility("hidden")));
 
+/*
+ * Tracepoint dynamic linkage handling (callbacks). Hidden visibility: shared
+ * across objects in a module/main executable. The callbacks are used to
+ * control and check if the destructors should be executed.
+ *
+ * IMPORTANT: this structure is part of the ABI between instrumented
+ * applications and UST. Fields need to be only added at the end, never
+ * reordered, never removed.
+ *
+ * The field @struct_size should be used to determine the size of the
+ * structure. It should be queried before using additional fields added
+ * at the end of the structure.
+ */
+struct lttng_ust_tracepoint_destructors_syms {
+       uint32_t struct_size;
+
+       void (*tracepoint_disable_destructors)(void);
+       int (*tracepoint_get_destructors_state)(void);
+
+       /* End of base ABI. Fields below should be used after checking struct_size. */
+};
+
+extern struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms;
+extern struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr;
+
+struct lttng_ust_tracepoint_destructors_syms tracepoint_destructors_syms
+       __attribute__((weak, visibility("hidden"))) = {
+       .struct_size = sizeof(struct lttng_ust_tracepoint_destructors_syms),
+};
+struct lttng_ust_tracepoint_destructors_syms *tracepoint_destructors_syms_ptr
+       __attribute__((weak, visibility("hidden")));
+
+static inline void tracepoint_disable_destructors(void)
+{
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       if (tracepoint_dlopen_ptr->liblttngust_handle
+                       && tracepoint_destructors_syms_ptr->tracepoint_disable_destructors)
+               tracepoint_destructors_syms_ptr->tracepoint_disable_destructors();
+}
+
 #ifndef _LGPL_SOURCE
-static inline void lttng_ust_notrace
-__tracepoint__init_urcu_sym(void);
+static inline void
+__tracepoint__init_urcu_sym(void)
+       lttng_ust_notrace;
 static inline void
 __tracepoint__init_urcu_sym(void)
 {
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
        /*
         * Symbols below are needed by tracepoint call sites and probe
         * providers.
         */
-       if (!tracepoint_dlopen.rcu_read_lock_sym_bp)
-               tracepoint_dlopen.rcu_read_lock_sym_bp =
+       if (!tracepoint_dlopen_ptr->rcu_read_lock_sym)
+               tracepoint_dlopen_ptr->rcu_read_lock_sym =
                        URCU_FORCE_CAST(void (*)(void),
-                               dlsym(tracepoint_dlopen.liblttngust_handle,
-                                       "tp_rcu_read_lock_bp"));
-       if (!tracepoint_dlopen.rcu_read_unlock_sym_bp)
-               tracepoint_dlopen.rcu_read_unlock_sym_bp =
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_rcu_read_lock"));
+       if (!tracepoint_dlopen_ptr->rcu_read_unlock_sym)
+               tracepoint_dlopen_ptr->rcu_read_unlock_sym =
                        URCU_FORCE_CAST(void (*)(void),
-                               dlsym(tracepoint_dlopen.liblttngust_handle,
-                                       "tp_rcu_read_unlock_bp"));
-       if (!tracepoint_dlopen.rcu_dereference_sym_bp)
-               tracepoint_dlopen.rcu_dereference_sym_bp =
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_rcu_read_unlock"));
+       if (!tracepoint_dlopen_ptr->rcu_dereference_sym)
+               tracepoint_dlopen_ptr->rcu_dereference_sym =
                        URCU_FORCE_CAST(void *(*)(void *p),
-                               dlsym(tracepoint_dlopen.liblttngust_handle,
-                                       "tp_rcu_dereference_sym_bp"));
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_rcu_dereference_sym"));
 }
 #else
-static inline void lttng_ust_notrace
-__tracepoint__init_urcu_sym(void);
+static inline void
+__tracepoint__init_urcu_sym(void)
+       lttng_ust_notrace;
 static inline void
 __tracepoint__init_urcu_sym(void)
 {
 }
 #endif
 
-static void lttng_ust_notrace __attribute__((constructor))
-__tracepoints__init(void);
+static void
+__tracepoints__init(void)
+       lttng_ust_notrace __attribute__((constructor));
 static void
 __tracepoints__init(void)
 {
-       if (__tracepoint_registered++)
+       if (__tracepoint_registered++) {
+               if (!tracepoint_dlopen_ptr->liblttngust_handle)
+                       return;
+               __tracepoint__init_urcu_sym();
                return;
+       }
 
-       if (!tracepoint_dlopen.liblttngust_handle)
-               tracepoint_dlopen.liblttngust_handle =
-                       dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
-       if (!tracepoint_dlopen.liblttngust_handle)
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
+               tracepoint_dlopen_ptr->liblttngust_handle =
+                       dlopen(LTTNG_UST_TRACEPOINT_LIB_SONAME, RTLD_NOW | RTLD_GLOBAL);
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
                return;
        __tracepoint__init_urcu_sym();
 }
 
-static void lttng_ust_notrace __attribute__((destructor))
-__tracepoints__destroy(void);
+static void
+__tracepoints__destroy(void)
+       lttng_ust_notrace __attribute__((destructor));
 static void
 __tracepoints__destroy(void)
 {
@@ -301,18 +404,34 @@ __tracepoints__destroy(void)
 
        if (--__tracepoint_registered)
                return;
-       if (tracepoint_dlopen.liblttngust_handle && !__tracepoint_ptrs_registered) {
-               ret = dlclose(tracepoint_dlopen.liblttngust_handle);
-               if (ret) {
-                       fprintf(stderr, "Error (%d) in dlclose\n", ret);
-                       abort();
-               }
-               memset(&tracepoint_dlopen, 0, sizeof(tracepoint_dlopen));
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
+               return;
+       if (__tracepoint_ptrs_registered)
+               return;
+       /*
+        * Lookup if destructors must be executed using the new method.
+        */
+       if (tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state
+               && !tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()) {
+               /*
+                * The tracepoint_get_destructors_state symbol was found with
+                * dlsym but its returned value is 0 meaning that destructors
+                * must not be executed.
+                */
+               return;
        }
+       ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
+       if (ret) {
+               fprintf(stderr, "Error (%d) in dlclose\n", ret);
+               abort();
+       }
+       memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr));
 }
 
-#endif
-
 #ifdef TRACEPOINT_DEFINE
 
 /*
@@ -348,55 +467,74 @@ extern struct lttng_ust_tracepoint * const __stop___tracepoints_ptrs[]
 #define _TP_EXTRACT_STRING(...)        #__VA_ARGS__
 
 #define _DEFINE_TRACEPOINT(_provider, _name, _args)                            \
+       lttng_ust_tracepoint_validate_name_len(_provider, _name);               \
        extern int __tracepoint_provider_##_provider;                           \
-       static const char __tp_strtab_##_provider##___##_name[]                 \
+       static const char __tp_provider_strtab_##_provider##___##_name[]        \
                __attribute__((section("__tracepoints_strings"))) =             \
-                       #_provider ":" #_name;                                  \
+                       #_provider;                                             \
+       static const char __tp_name_strtab_##_provider##___##_name[]            \
+               __attribute__((section("__tracepoints_strings"))) =             \
+                       #_name;                                                 \
        struct lttng_ust_tracepoint __tracepoint_##_provider##___##_name        \
-               __attribute__((section("__tracepoints"))) =                     \
-               {                                                               \
-                       __tp_strtab_##_provider##___##_name,                    \
+               __attribute__((section("__tracepoints"))) = {                   \
+                       sizeof(struct lttng_ust_tracepoint),                    \
+                       __tp_provider_strtab_##_provider##___##_name,           \
+                       __tp_name_strtab_##_provider##___##_name,               \
                        0,                                                      \
                        NULL,                                                   \
                        _TRACEPOINT_UNDEFINED_REF(_provider),                   \
                        _TP_EXTRACT_STRING(_args),                              \
-                       { },                                                    \
                };                                                              \
        static struct lttng_ust_tracepoint *                                    \
                __tracepoint_ptr_##_provider##___##_name                        \
-               __attribute__((used, section("__tracepoints_ptrs"))) =          \
+               __attribute__((section("__tracepoints_ptrs"), used))            \
+               __lttng_ust_variable_attribute_no_sanitize_address =            \
                        &__tracepoint_##_provider##___##_name;
 
-static void lttng_ust_notrace __attribute__((constructor))
-__tracepoints__ptrs_init(void);
+static void
+__tracepoints__ptrs_init(void)
+       lttng_ust_notrace __attribute__((constructor));
 static void
 __tracepoints__ptrs_init(void)
 {
        if (__tracepoint_ptrs_registered++)
                return;
-       if (!tracepoint_dlopen.liblttngust_handle)
-               tracepoint_dlopen.liblttngust_handle =
-                       dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
-       if (!tracepoint_dlopen.liblttngust_handle)
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
+               tracepoint_dlopen_ptr->liblttngust_handle =
+                       dlopen(LTTNG_UST_TRACEPOINT_LIB_SONAME, RTLD_NOW | RTLD_GLOBAL);
+       if (!tracepoint_dlopen_ptr->liblttngust_handle)
                return;
-       tracepoint_dlopen.tracepoint_register_lib =
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       tracepoint_dlopen_ptr->tracepoint_register_lib =
                URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *, int),
-                               dlsym(tracepoint_dlopen.liblttngust_handle,
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
                                        "tracepoint_register_lib"));
-       tracepoint_dlopen.tracepoint_unregister_lib =
+       tracepoint_dlopen_ptr->tracepoint_unregister_lib =
                URCU_FORCE_CAST(int (*)(struct lttng_ust_tracepoint * const *),
-                               dlsym(tracepoint_dlopen.liblttngust_handle,
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
                                        "tracepoint_unregister_lib"));
+       tracepoint_destructors_syms_ptr->tracepoint_disable_destructors =
+               URCU_FORCE_CAST(void (*)(void),
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_disable_destructors"));
+       tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state =
+               URCU_FORCE_CAST(int (*)(void),
+                               dlsym(tracepoint_dlopen_ptr->liblttngust_handle,
+                                       "tp_get_destructors_state"));
        __tracepoint__init_urcu_sym();
-       if (tracepoint_dlopen.tracepoint_register_lib) {
-               tracepoint_dlopen.tracepoint_register_lib(__start___tracepoints_ptrs,
+       if (tracepoint_dlopen_ptr->tracepoint_register_lib) {
+               tracepoint_dlopen_ptr->tracepoint_register_lib(__start___tracepoints_ptrs,
                                __stop___tracepoints_ptrs -
                                __start___tracepoints_ptrs);
        }
 }
 
-static void lttng_ust_notrace __attribute__((destructor))
-__tracepoints__ptrs_destroy(void);
+static void
+__tracepoints__ptrs_destroy(void)
+       lttng_ust_notrace __attribute__((destructor));
 static void
 __tracepoints__ptrs_destroy(void)
 {
@@ -404,15 +542,22 @@ __tracepoints__ptrs_destroy(void)
 
        if (--__tracepoint_ptrs_registered)
                return;
-       if (tracepoint_dlopen.tracepoint_unregister_lib)
-               tracepoint_dlopen.tracepoint_unregister_lib(__start___tracepoints_ptrs);
-       if (tracepoint_dlopen.liblttngust_handle && !__tracepoint_registered) {
-               ret = dlclose(tracepoint_dlopen.liblttngust_handle);
+       if (!tracepoint_dlopen_ptr)
+               tracepoint_dlopen_ptr = &tracepoint_dlopen;
+       if (!tracepoint_destructors_syms_ptr)
+               tracepoint_destructors_syms_ptr = &tracepoint_destructors_syms;
+       if (tracepoint_dlopen_ptr->tracepoint_unregister_lib)
+               tracepoint_dlopen_ptr->tracepoint_unregister_lib(__start___tracepoints_ptrs);
+       if (tracepoint_dlopen_ptr->liblttngust_handle
+                       && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state
+                       && tracepoint_destructors_syms_ptr->tracepoint_get_destructors_state()
+                       && !__tracepoint_ptrs_registered) {
+               ret = dlclose(tracepoint_dlopen_ptr->liblttngust_handle);
                if (ret) {
                        fprintf(stderr, "Error (%d) in dlclose\n", ret);
                        abort();
                }
-               memset(&tracepoint_dlopen, 0, sizeof(tracepoint_dlopen));
+               memset(tracepoint_dlopen_ptr, 0, sizeof(*tracepoint_dlopen_ptr));
        }
 }
 
@@ -480,7 +625,7 @@ __tracepoints__ptrs_destroy(void)
  * How to use the TRACEPOINT_EVENT macro:
  *
  * An example:
- * 
+ *
  * TRACEPOINT_EVENT(someproject_component, event_name,
  *
  *     * TP_ARGS takes from 0 to 10 "type, field_name" pairs *
@@ -491,23 +636,23 @@ __tracepoints__ptrs_destroy(void)
  *     * TP_FIELDS describes the event payload layout in the trace *
  *
  *     TP_FIELDS(
- *         * Integer, printed in base 10 * 
+ *         * Integer, printed in base 10 *
  *         ctf_integer(int, field_a, arg0)
  *
- *         * Integer, printed with 0x base 16 * 
+ *         * Integer, printed with 0x base 16 *
  *         ctf_integer_hex(unsigned long, field_d, arg1)
  *
  *         * Enumeration *
  *         ctf_enum(someproject_component, enum_name, int, field_e, arg0)
  *
- *         * Array Sequence, printed as UTF8-encoded array of bytes * 
+ *         * Array Sequence, printed as UTF8-encoded array of bytes *
  *         ctf_array_text(char, field_b, string, FIXED_LEN)
  *         ctf_sequence_text(char, field_c, string, size_t, strlen)
  *
- *         * String, printed as UTF8-encoded string * 
+ *         * String, printed as UTF8-encoded string *
  *         ctf_string(field_e, string)
  *
- *         * Array sequence of signed integer values * 
+ *         * Array sequence of signed integer values *
  *         ctf_array(long, field_f, arg4, FIXED_LEN4)
  *         ctf_sequence(long, field_g, arg4, size_t, arg4_len)
  *     )
This page took 0.040492 seconds and 4 git commands to generate.