]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: use perf_events probes
authorTimothy J Fontaine <tj.fontaine@oracle.com>
Wed, 18 May 2016 15:51:20 +0000 (16:51 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 4 Jul 2016 16:14:28 +0000 (17:14 +0100)
For every trace point defined, also define an SDT probe. This allows
DTrace to expose probe points maintained by upstream.

[nca: fixed TODOs: added DTRACE_UINTPTR_CAST_EACH so that tracepoints
      that pass structures by value will still compile: we jam the
      structure into a uintptr if it will fit, otherwise passing its
      address in.

      This is only partial, so far: there is no CTF type info for any
      of these new probes, but this is a relatively minor issue that can
      be fixed later.]

Orabug: 23004534
Signed-off-by: Timothy J Fontaine <tj.fontaine@oracle.com>
Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Acked-by: Kris Van Hees <kris.van.hees@oracle.com>
include/linux/sdt.h
include/linux/tracepoint.h

index a1f12e7a0c9d7717547b835f9e65fcbee837726b..c44db3de6654954402c32c6fd8f5349c5be8f00e 100644 (file)
@@ -122,6 +122,68 @@ extern "C" {
            (uintptr_t)(arg6), (uintptr_t)(arg7), (uintptr_t)(arg8));   \
 }
 
+/* This counts the number of args */
+#define DTRACE_NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,N,...) N
+#define DTRACE_NARGS(...) DTRACE_NARGS_SEQ(__VA_ARGS__, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+
+/* This will let macros expand before concating them */
+#define DTRACE_PRIMITIVE_CAT(x, y) x ## y
+#define DTRACE_CAT(x, y) DTRACE_PRIMITIVE_CAT(x, y)
+
+/* This will call a macro on each argument passed in */
+#define DTRACE_APPLY(macro, ...) DTRACE_CAT(DTRACE_APPLY_, DTRACE_NARGS(__VA_ARGS__))(macro, __VA_ARGS__)
+#define DTRACE_APPLY_1(m, x1) m(x1)
+#define DTRACE_APPLY_2(m, x1, x2) m(x1), m(x2)
+#define DTRACE_APPLY_3(m, x1, x2, x3) m(x1), m(x2), m(x3)
+#define DTRACE_APPLY_4(m, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
+#define DTRACE_APPLY_5(m, x1, x2, x3, x4, x5) m(x1), m(x2), m(x3), m(x4), m(x5)
+#define DTRACE_APPLY_6(m, x1, x2, x3, x4, x5, x6) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
+#define DTRACE_APPLY_7(m, x1, x2, x3, x4, x5, x6, x7) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
+#define DTRACE_APPLY_8(m, x1, x2, x3, x4, x5, x6, x7, x8) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+
+/*
+ * Without investigation I went ahead and assumed the most arguments that could
+ * be passed would be 8, but this is purely arbitrary. However, inexplicably
+ * there are existing tracepoints that pass as many as 18 arguments!
+ */
+
+#define DTRACE_APPLY_9(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_10(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_11(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_12(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_13(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_14(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_15(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_16(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_17(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+#define DTRACE_APPLY_18(m, x1, x2, x3, x4, x5, x6, x7, x8, ...) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
+
+/*
+ * Convert everything to the appropriate integral type, unless too large to fit
+ * into any of them, in which case its address is taken instead.
+ */
+
+#define DTRACE_UINTPTR_CAST_EACH(x) ({                                 \
+  union {                                                              \
+    typeof((x)) __val;                                                 \
+    unsigned char __c;                                                 \
+    unsigned short __s;                                                        \
+    unsigned int __i;                                                  \
+    unsigned long __l;                                                 \
+    unsigned long long __ll; } __u = { .__val = (x) };                 \
+  __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__c), __u.__c, \
+  __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__s), __u.__s,         \
+  __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__i), __u.__i,         \
+  __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__l), __u.__l,         \
+  __builtin_choose_expr(sizeof(__u.__val) == sizeof(__u.__ll), __u.__ll,\
+  (uintptr_t)&(__u.__val))))));})
+#define DTRACE_UINTPTR_EACH(x) uintptr_t
+
+#define DTRACE_PROBE_TRACEPOINT(name, args...) {                       \
+       extern void __dtrace_probe_##name(DTRACE_APPLY(DTRACE_UINTPTR_EACH, args)); \
+       __dtrace_probe_##name(DTRACE_APPLY(DTRACE_UINTPTR_CAST_EACH, args));    \
+}
+
 typedef struct sdt_probedesc {
        char                    *sdpd_name;     /* probe name */
        char                    *sdpd_func;     /* probe function */
@@ -150,6 +212,7 @@ typedef struct sdt_probedesc {
 #define        DTRACE_PROBE8(name, type1, arg1, type2, arg2, type3, arg3,      \
        type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8) \
                                                        DTRACE_PROBE(name)
+#define DTRACE_PROBE_TRACEPOINT(name, args...)
 
 #endif /* CONFIG_DTRACE */
 
index a5f7f3ecafa3a77123531ca2a07a01b086906db0..c913baf53e36d451c572f342d8c349ea20bcc136 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/rcupdate.h>
 #include <linux/static_key.h>
+#include <linux/sdt.h>
 
 struct module;
 struct tracepoint;
@@ -176,6 +177,7 @@ extern void syscall_unregfunc(void);
        extern struct tracepoint __tracepoint_##name;                   \
        static inline void trace_##name(proto)                          \
        {                                                               \
+               DTRACE_PROBE_TRACEPOINT(name, args);                    \
                if (static_key_false(&__tracepoint_##name.key))         \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TP_PROTO(data_proto),                   \
@@ -237,7 +239,9 @@ extern void syscall_unregfunc(void);
 #else /* !CONFIG_TRACEPOINTS */
 #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
        static inline void trace_##name(proto)                          \
-       { }                                                             \
+       {                                                               \
+               DTRACE_PROBE_TRACEPOINT(name, args);                    \
+       }                                                               \
        static inline void trace_##name##_rcuidle(proto)                \
        { }                                                             \
        static inline int                                               \