All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Linux Kernel <linux-kernel@vger.kernel.org>
Subject: [PATCH 1/2] tracing/function-graph-tracer: signal interrupts entry/exit points on outpout
Date: Mon, 08 Dec 2008 01:54:48 +0100	[thread overview]
Message-ID: <493C7058.4060709@gmail.com> (raw)

Impact: provide interrupt detection on output

Suggested by Ingo.
If a hardirq is raised, we want it to be signaled on output, so this patch
adds two arrows on the output to find entry and exit points of a hardirq.

Unfortunately, there are many interrupt entrypoints and these can be differents
from one arch to another.

The approach here is one of the easiest, but doesn't shine by its scalability:
we have an array of the interrupt entrypoints names that we compare with the
symbol of the current traced function, if it matches, we draw the arrow.

Ie:

 1)               |                                unlock_buffer() {
 1)               |                                  wake_up_bit() {
 1)               |                                    bit_waitqueue() {
 1)   0.872 us    |                                      __phys_addr();
 1)   2.722 us    |                                    }
 1)               |                                    __wake_up_bit() {
 =================>
 1)               |                                      do_IRQ() {
 1)               |                                        exit_idle() {
 1)               |                                        irq_enter() {
 1)   0.790 us    |                                          idle_cpu();
 1)   2.346 us    |                                        }
 1)               |                                        handle_edge_irq() {
 1)   1.098 us    |                                          _spin_lock();
 1)               |                                          ack_apic_edge() {
 1)   0.722 us    |                                            irq_complete_move();
 1)   0.737 us    |                                            move_native_irq();
 1)   0.707 us    |                                            native_apic_mem_write();
 1)   5.249 us    |                                          }
 1)   0.879 us    |                                          _spin_unlock();
 1)               |                                          handle_IRQ_event() {
 1)               |                                            timer_interrupt() {
 1)               |                                              tick_handle_oneshot_broadcast() {
 1)   1.165 us    |                                                _spin_lock();
 1)               |                                                ktime_get() {
 1)               |                                                  ktime_get_ts() {
 1)               |                                                    getnstimeofday() {
 1)   1.782 us    |                                                      read_hpet();
 1)   3.542 us    |                                                    }
 1)   0.744 us    |                                                    set_normalized_timespec();
 1)   6.640 us    |                                                  }
 1)   8.226 us    |                                                }
 1)               |                                                tick_do_broadcast() {
 1)               |                                                  lapic_timer_broadcast() {
 1)   0.879 us    |                                                    flat_send_IPI_mask();
 1)   2.467 us    |                                                  }
 1)   4.045 us    |                                                }
 1)   0.864 us    |                                                _spin_unlock();
 1) + 18.431 us   |                                              }
 1) + 20.047 us   |                                            }
 1) + 21.611 us   |                                          }
 1)   0.940 us    |                                          note_interrupt();
 1)   1.008 us    |                                          _spin_lock();
 1)   0.992 us    |                                          _spin_unlock();
 1) + 38.711 us   |                                        }
 1)               |                                        irq_exit() {
 1)   0.752 us    |                                          idle_cpu();
 1)   2.609 us    |                                        }
 1) + 48.952 us   |                                      }
 <=================
 1) + 55.314 us   |                                    }
 1) + 60.983 us   |                                  }
 1) + 62.976 us   |                                }
 1) + 64.984 us   |                              }

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 1b43086..26b4d6a 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -324,6 +324,24 @@ int __init ftrace_dyn_arch_init(void *data)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
+/* Used during output to find the interrupts entry/exit points */
+const char *ftrace_graph_irq_entries[] = {
+	"smp_call_function_single_interrupt",
+	"xen_call_function_single_interrupt",
+	"wrapper_smp_local_timer_interrupt",
+	"smp_irq_move_cleanup_interrupt",
+	"smp_call_function_interrupt",
+	"xen_call_function_interrupt",
+	"smp_apic_timer_interrupt",
+	"uv_bau_message_interrupt",
+	"mce_threshold_interrupt",
+	"smp_spurious_interrupt",
+	"smp_thermal_interrupt",
+	"smp_error_interrupt",
+	"do_IRQ",
+	NULL
+};
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 extern void ftrace_graph_call(void);
 
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 11cac81..36065e8 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -411,6 +411,9 @@ static inline void unpause_graph_tracing(void)
 {
 	atomic_dec(&current->tracing_graph_pause);
 }
+
+/* Contains the entrypoints to hardirq (arch defined) */
+extern const char *ftrace_graph_irq_entries[];
 #else
 
 #define __notrace_funcgraph
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 32b7fb9..7ea446d 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -10,6 +10,8 @@
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
 #include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
 
 #include "trace.h"
 
@@ -64,6 +66,31 @@ static void graph_trace_reset(struct trace_array *tr)
 	unregister_ftrace_graph();
 }
 
+/* Signal enter into or exit from an interrupt */
+static enum print_line_t
+print_graph_interrupt(struct trace_seq *s, unsigned long addr,
+				enum trace_type type)
+{
+	char symbol[KSYM_NAME_LEN];
+	const char *arrow;
+	int ret;
+	int i;
+
+	kallsyms_lookup(addr, NULL, NULL, NULL, symbol);
+	for (i = 0; ftrace_graph_irq_entries[i]; i++)
+		if (!strcmp(symbol, ftrace_graph_irq_entries[i])) {
+			if (type == TRACE_GRAPH_ENT)
+				arrow = " =================>\n";
+			else
+				arrow = " <=================\n";
+			ret = trace_seq_printf(s, arrow);
+			if (!ret)
+				return TRACE_TYPE_PARTIAL_LINE;
+			break;
+		}
+	return TRACE_TYPE_HANDLED;
+}
+
 static inline int log10_cpu(int nb)
 {
 	if (nb / 100)
@@ -385,6 +412,10 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
 	int ret;
 	struct trace_entry *ent = iter->ent;
 
+	ret = print_graph_interrupt(s, field->graph_ent.func, TRACE_GRAPH_ENT);
+	if (ret == TRACE_TYPE_PARTIAL_LINE)
+		return TRACE_TYPE_PARTIAL_LINE;
+
 	/* Pid */
 	if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
@@ -474,6 +505,11 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
 	}
+
+	ret = print_graph_interrupt(s, trace->func, TRACE_GRAPH_RET);
+	if (ret == TRACE_TYPE_PARTIAL_LINE)
+		return TRACE_TYPE_PARTIAL_LINE;
+
 	return TRACE_TYPE_HANDLED;
 }
 
-- 
1.6.0.4


             reply	other threads:[~2008-12-08  0:55 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-08  0:54 Frederic Weisbecker [this message]
2008-12-08  6:19 ` [PATCH 1/2] tracing/function-graph-tracer: signal interrupts entry/exit points on outpout Peter Zijlstra
2008-12-08 13:38   ` Frédéric Weisbecker
2008-12-08 13:47     ` Ingo Molnar
2008-12-08 13:51       ` Frédéric Weisbecker
2008-12-08 12:22 ` Ingo Molnar
2008-12-08 13:47   ` Frédéric Weisbecker
2008-12-08 14:03     ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=493C7058.4060709@gmail.com \
    --to=fweisbec@gmail.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.