callsite: move after the call
[lttng-ust.git] / include / lttng / tracepoint.h
index 4b773bbc2eead7a60e11415ead1d364e979afa6d..8e4704c47f3e264e653b1539f45e30234f4080cf 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>    /* for memset */
 #include <assert.h>
 #include <lttng/ust-config.h>  /* for sdt */
+#include <lttng/ust-compiler.h>
 
 #ifdef LTTNG_UST_HAVE_SDT_INTEGRATION
 #define SDT_USE_VARIADIC
 extern "C" {
 #endif
 
-#define tracepoint(provider, name, ...)                                            \
-       do {                                                                \
-               STAP_PROBEV(provider, name, ## __VA_ARGS__);                \
-               if (caa_unlikely(__tracepoint_##provider##___##name.state)) \
-                       __tracepoint_cb_##provider##___##name(__VA_ARGS__); \
+#define tracepoint(provider, name, ...)                                              \
+       do {                                                                  \
+               STAP_PROBEV(provider, name, ## __VA_ARGS__);                  \
+               if (caa_unlikely(__tracepoint_##provider##___##name.state)) { \
+                       __tracepoint_cb_##provider##___##name(__VA_ARGS__);   \
+                       TRACEPOINT_CALLSITE(provider, name);                  \
+               }                                                             \
        } while (0)
 
 #define TP_ARGS(...)       __VA_ARGS__
@@ -62,8 +65,12 @@ extern "C" {
 #define _TP_COMBINE_TOKENS4(_tokena, _tokenb, _tokenc, _tokend)                \
                __TP_COMBINE_TOKENS4(_tokena, _tokenb, _tokenc, _tokend)
 
-/* _TP_EXVAR* extract the var names. */
+/*
+ * _TP_EXVAR* extract the var names.
+ * _TP_EXVAR1 and _TP_EXDATA_VAR1 are needed for -std=c99.
+ */
 #define _TP_EXVAR0()
+#define _TP_EXVAR1(a)
 #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
@@ -76,6 +83,7 @@ extern "C" {
 #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_VAR1(a)                                             __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
@@ -87,8 +95,12 @@ extern "C" {
 #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()
+/*
+ * _TP_EXPROTO* extract tuples of type, var.
+ * _TP_EXPROTO1 and _TP_EXDATA_PROTO1 are needed for -std=c99.
+ */
+#define _TP_EXPROTO0()                                         void
+#define _TP_EXPROTO1(a)                                                void
 #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
@@ -101,6 +113,7 @@ extern "C" {
 #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_PROTO1(a)                                           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
@@ -127,7 +140,10 @@ extern "C" {
 
 #define _DECLARE_TRACEPOINT(_provider, _name, ...)                                     \
 extern struct tracepoint __tracepoint_##_provider##___##_name;                         \
-static inline void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_ARGS__))        \
+static inline 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__))              \
 {                                                                                      \
        struct tracepoint_probe *__tp_probe;                                            \
                                                                                        \
@@ -138,7 +154,7 @@ static inline void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_A
        if (caa_unlikely(!__tp_probe))                                                  \
                goto end;                                                               \
        do {                                                                            \
-               void *__tp_cb = __tp_probe->func;                                       \
+               void (*__tp_cb)(void) = __tp_probe->func;                                       \
                void *__tp_data = __tp_probe->data;                                     \
                                                                                        \
                URCU_FORCE_CAST(void (*)(_TP_ARGS_DATA_PROTO(__VA_ARGS__)), __tp_cb)    \
@@ -147,21 +163,30 @@ static inline void __tracepoint_cb_##_provider##___##_name(_TP_ARGS_PROTO(__VA_A
 end:                                                                                   \
        tp_rcu_read_unlock_bp();                                                        \
 }                                                                                      \
-static inline void __tracepoint_register_##_provider##___##_name(char *name,           \
-               void *func, void *data)                                                 \
+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 (*func)(void), 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)                                                 \
+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 (*func)(void), 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);
+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);
 
 /*
  * tracepoint dynamic linkage handling (callbacks). Hidden visibility:
@@ -182,6 +207,112 @@ struct tracepoint_dlopen {
 
 extern struct tracepoint_dlopen tracepoint_dlopen;
 
+struct tracepoint_callsite_dlopen {
+       void *liblttngust_handle;
+
+       int (*tracepoint_register_lib_callsite)(struct tracepoint_callsite * const *tp_start,
+               int tp_count);
+       int (*tracepoint_unregister_lib_callsite)(struct tracepoint_callsite * const *tp_start,
+               int tp_count);
+};
+
+struct tracepoint_callsite_dlopen tracepoint_callsite_dlopen
+       __attribute__((weak, visibility("hidden")));
+int __tracepoint_callsite_registered
+       __attribute__((weak, visibility("hidden")));
+
+#if (CAA_BITS_PER_LONG == 64)
+#define __TP_ASM_PTR   ".quad "
+#else
+#define __TP_ASM_PTR   ".long "
+#endif
+
+/*
+ * Note: to allow PIC code, we need to allow the linker to update the pointers
+ * in the __tracepoints_callsite_ptrs section.
+ * Therefore, this section is _not_ const (read-only).
+ */
+#define TRACEPOINT_CALLSITE(_provider, _name)                                  \
+do {                                                                           \
+       asm volatile (  ".pushsection __tracepoint_callsite, \"aw\"\n\t"        \
+                       "1:\n\t"                                                \
+                       __TP_ASM_PTR "%c0, %c1, %c2, 2f\n\t"                    \
+                       ".int %c3\n\t"                                          \
+                       ".space 16\n\t" /* padding */                           \
+                       ".popsection\n\t"                                       \
+                       ".pushsection __tracepoint_callsite_ptrs, \"aw\"\n\t"   \
+                       __TP_ASM_PTR "1b\n\t"                                   \
+                       ".popsection\n\t"                                       \
+                       "2:\n\t"                                                \
+               : : "i" (#_provider ":" #_name),                                \
+                       "i" (__func__),                                         \
+                       "i" (__FILE__),                                         \
+                       "i" (__LINE__));                                        \
+} while (0)
+
+/*
+ * These weak symbols, the constructor, and destructor take care of
+ * registering only _one_ instance of the tracepoint callsite per
+ * shared-ojbect (or for the whole main program).
+ */
+extern struct tracepoint_callsite * const __start___tracepoint_callsite_ptrs[]
+       __attribute__((weak, visibility("hidden")));
+extern struct tracepoint_callsite * const __stop___tracepoint_callsite_ptrs[]
+       __attribute__((weak, visibility("hidden")));
+
+/*
+ * We need at least one pointer in the section.
+ */
+static struct tracepoint_callsite *
+       __tracepoint_callsite_ptr_dummy
+       __attribute__((used, section("__tracepoint_callsite_ptrs"))) =
+               NULL;
+
+static void lttng_ust_notrace __attribute__((constructor))
+__tracepoint_callsite__init(void);
+static void
+__tracepoint_callsite__init(void)
+{
+       if (__tracepoint_callsite_registered++)
+               return;
+
+       tracepoint_callsite_dlopen.liblttngust_handle =
+               dlopen("liblttng-ust-tracepoint.so.0", RTLD_NOW | RTLD_GLOBAL);
+       if (!tracepoint_callsite_dlopen.liblttngust_handle)
+               return;
+       tracepoint_callsite_dlopen.tracepoint_register_lib_callsite =
+               URCU_FORCE_CAST(int (*)(struct tracepoint_callsite * const *, int),
+                               dlsym(tracepoint_callsite_dlopen.liblttngust_handle,
+                                       "tracepoint_register_lib_callsite"));
+       tracepoint_callsite_dlopen.tracepoint_unregister_lib_callsite =
+               URCU_FORCE_CAST(int (*)(struct tracepoint_callsite * const *, int),
+                               dlsym(tracepoint_callsite_dlopen.liblttngust_handle,
+                                       "tracepoint_unregister_lib_callsite"));
+       tracepoint_callsite_dlopen.tracepoint_register_lib_callsite(__start___tracepoint_callsite_ptrs,
+                               __stop___tracepoint_callsite_ptrs -
+                               __start___tracepoint_callsite_ptrs);
+}
+
+static void lttng_ust_notrace __attribute__((destructor))
+__tracepoint_callsite__destroy(void);
+static void
+__tracepoint_callsite__destroy(void)
+{
+       int ret;
+
+       if (--__tracepoint_callsite_registered)
+               return;
+       if (tracepoint_callsite_dlopen.tracepoint_unregister_lib_callsite)
+               tracepoint_callsite_dlopen.tracepoint_unregister_lib_callsite(__start___tracepoint_callsite_ptrs,
+                               __stop___tracepoint_callsite_ptrs -
+                               __start___tracepoint_callsite_ptrs);
+       if (tracepoint_callsite_dlopen.liblttngust_handle) {
+               ret = dlclose(tracepoint_callsite_dlopen.liblttngust_handle);
+               assert(!ret);
+               memset(&tracepoint_callsite_dlopen, 0, sizeof(tracepoint_callsite_dlopen));
+       }
+}
+
 #ifdef TRACEPOINT_DEFINE
 
 /*
@@ -238,7 +369,10 @@ int __tracepoint_registered
 struct tracepoint_dlopen tracepoint_dlopen
        __attribute__((weak, visibility("hidden")));
 
-static void __attribute__((constructor)) __tracepoints__init(void)
+static void lttng_ust_notrace __attribute__((constructor))
+__tracepoints__init(void);
+static void
+__tracepoints__init(void)
 {
        if (__tracepoint_registered++)
                return;
@@ -274,7 +408,10 @@ static void __attribute__((constructor)) __tracepoints__init(void)
                                __start___tracepoints_ptrs);
 }
 
-static void __attribute__((destructor)) __tracepoints__destroy(void)
+static void lttng_ust_notrace __attribute__((destructor))
+__tracepoints__destroy(void);
+static void
+__tracepoints__destroy(void)
 {
        int ret;
 
@@ -489,3 +626,9 @@ enum {
 #define TRACEPOINT_LOGLEVEL(provider, name, loglevel)
 
 #endif /* #ifndef TRACEPOINT_LOGLEVEL */
+
+#ifndef TRACEPOINT_MODEL_EMF_URI
+
+#define TRACEPOINT_MODEL_EMF_URI(provider, name, uri)
+
+#endif /* #ifndef TRACEPOINT_MODEL_EMF_URI */
This page took 0.026587 seconds and 4 git commands to generate.