smp: smp_cross_call function pointer tracing
authorChris Redpath <chris.redpath@arm.com>
Fri, 11 Oct 2013 10:45:01 +0000 (11:45 +0100)
committerJon Medhurst <tixy@linaro.org>
Fri, 11 Oct 2013 14:07:18 +0000 (15:07 +0100)
generic tracing for smp_cross_call function calls

Signed-off-by: Chris Redpath <chris.redpath@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
include/trace/events/smp.h [new file with mode: 0644]
kernel/smp.c

diff --git a/include/trace/events/smp.h b/include/trace/events/smp.h
new file mode 100644 (file)
index 0000000..c8abfd7
--- /dev/null
@@ -0,0 +1,91 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM smp
+
+#if !defined(_TRACE_SMP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SMP_H
+
+#include <linux/tracepoint.h>
+typedef void (*__smp_call_func_t)(void *info);
+
+DECLARE_EVENT_CLASS(smp_call_class,
+
+       TP_PROTO(__smp_call_func_t fnc),
+
+       TP_ARGS(fnc),
+
+       TP_STRUCT__entry(
+               __field( void *, func )
+       ),
+
+       TP_fast_assign(
+               __entry->func = fnc;
+       ),
+
+       TP_printk("func=%pf", __entry->func)
+);
+
+/**
+ * smp_call_func_entry - called in the generic smp-cross-call-handler
+ *                                              immediately before calling the destination
+ *                                              function
+ * @func:  function pointer
+ *
+ * When used in combination with the smp_call_func_exit tracepoint
+ * we can determine the cross-call runtime.
+ */
+DEFINE_EVENT(smp_call_class, smp_call_func_entry,
+
+       TP_PROTO(__smp_call_func_t fnc),
+
+       TP_ARGS(fnc)
+);
+
+/**
+ * smp_call_func_exit - called in the generic smp-cross-call-handler
+ *                                             immediately after the destination function
+ *                                             returns
+ * @func:  function pointer
+ *
+ * When used in combination with the smp_call_entry tracepoint
+ * we can determine the cross-call runtime.
+ */
+DEFINE_EVENT(smp_call_class, smp_call_func_exit,
+
+       TP_PROTO(__smp_call_func_t fnc),
+
+       TP_ARGS(fnc)
+);
+
+/**
+ * smp_call_func_send - called as destination function is set
+ *                                             in the per-cpu storage
+ * @func:  function pointer
+ * @dest:  cpu to send to
+ *
+ * When used in combination with the smp_cross_call_entry tracepoint
+ * we can determine the call-to-run latency.
+ */
+TRACE_EVENT(smp_call_func_send,
+
+       TP_PROTO(__smp_call_func_t func, int dest),
+
+       TP_ARGS(func, dest),
+
+       TP_STRUCT__entry(
+               __field(        void *  ,       func )
+               __field(        int             ,       dest )
+       ),
+
+       TP_fast_assign(
+               __entry->func = func;
+               __entry->dest = dest;
+       ),
+
+       TP_printk("dest=%d func=%pf", __entry->dest,
+                       __entry->func)
+);
+
+#endif /*  _TRACE_SMP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 4dba0f7b72ad716cf447f1fdbdd082ff7e0e73cf..23ccc67dcbb261b6a7dd127c919fe61692ecb97d 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/smp.h>
 
 #include "smpboot.h"
 
@@ -159,8 +161,10 @@ void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
         * locking and barrier primitives. Generic code isn't really
         * equipped to do the right thing...
         */
-       if (ipi)
+       if (ipi) {
+               trace_smp_call_func_send(csd->func, cpu);
                arch_send_call_function_single_ipi(cpu);
+       }
 
        if (wait)
                csd_lock_wait(csd);
@@ -197,8 +201,9 @@ void generic_smp_call_function_single_interrupt(void)
                 * so save them away before making the call:
                 */
                csd_flags = csd->flags;
-
+               trace_smp_call_func_entry(csd->func);
                csd->func(csd->info);
+               trace_smp_call_func_exit(csd->func);
 
                /*
                 * Unlocked CSDs are valid through generic_exec_single():
@@ -228,6 +233,7 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
        int this_cpu;
        int err = 0;
 
+       trace_smp_call_func_send(func, cpu);
        /*
         * prevent preemption and reschedule on another processor,
         * as well as CPU removal
@@ -245,7 +251,9 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 
        if (cpu == this_cpu) {
                local_irq_save(flags);
+               trace_smp_call_func_entry(func);
                func(info);
+               trace_smp_call_func_exit(func);
                local_irq_restore(flags);
        } else {
                if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {