aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2010-09-07 10:53:44 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-09-14 20:18:07 -0400
commit2bd16212b8eb86f9574e78d6605a5ba9e9aa8c4e (patch)
treedc26de82f9830265eef31d9eebffce22f0ef632c /kernel/trace
parent469917ce8717b9f8c5298bf279fa138859baab8d (diff)
tracing: Add funcgraph-irq option for function graph tracer.
It's handy to be able to disable the irq related output and not to have to jump over each irq related code, when you have no interrest in it. The option is by default enabled, so there's no change to current behaviour. It affects only the final output, so all the irq related data stay in the ring buffer. Signed-off-by: Jiri Olsa <jolsa@redhat.com> LKML-Reference: <20100907145344.GC1912@jolsa.brq.redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_functions_graph.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index c93bcb248638..8674750a5ece 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -18,6 +18,7 @@
18struct fgraph_cpu_data { 18struct fgraph_cpu_data {
19 pid_t last_pid; 19 pid_t last_pid;
20 int depth; 20 int depth;
21 int depth_irq;
21 int ignore; 22 int ignore;
22 unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH]; 23 unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH];
23}; 24};
@@ -41,6 +42,7 @@ struct fgraph_data {
41#define TRACE_GRAPH_PRINT_PROC 0x8 42#define TRACE_GRAPH_PRINT_PROC 0x8
42#define TRACE_GRAPH_PRINT_DURATION 0x10 43#define TRACE_GRAPH_PRINT_DURATION 0x10
43#define TRACE_GRAPH_PRINT_ABS_TIME 0x20 44#define TRACE_GRAPH_PRINT_ABS_TIME 0x20
45#define TRACE_GRAPH_PRINT_IRQS 0x40
44 46
45static struct tracer_opt trace_opts[] = { 47static struct tracer_opt trace_opts[] = {
46 /* Display overruns? (for self-debug purpose) */ 48 /* Display overruns? (for self-debug purpose) */
@@ -55,13 +57,15 @@ static struct tracer_opt trace_opts[] = {
55 { TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) }, 57 { TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
56 /* Display absolute time of an entry */ 58 /* Display absolute time of an entry */
57 { TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) }, 59 { TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
60 /* Display interrupts */
61 { TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) },
58 { } /* Empty entry */ 62 { } /* Empty entry */
59}; 63};
60 64
61static struct tracer_flags tracer_flags = { 65static struct tracer_flags tracer_flags = {
62 /* Don't display overruns and proc by default */ 66 /* Don't display overruns and proc by default */
63 .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD | 67 .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
64 TRACE_GRAPH_PRINT_DURATION, 68 TRACE_GRAPH_PRINT_DURATION | TRACE_GRAPH_PRINT_IRQS,
65 .opts = trace_opts 69 .opts = trace_opts
66}; 70};
67 71
@@ -855,6 +859,92 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
855 return 0; 859 return 0;
856} 860}
857 861
862/*
863 * Entry check for irq code
864 *
865 * returns 1 if
866 * - we are inside irq code
867 * - we just extered irq code
868 *
869 * retunns 0 if
870 * - funcgraph-interrupts option is set
871 * - we are not inside irq code
872 */
873static int
874check_irq_entry(struct trace_iterator *iter, u32 flags,
875 unsigned long addr, int depth)
876{
877 int cpu = iter->cpu;
878 struct fgraph_data *data = iter->private;
879 int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
880
881 if (flags & TRACE_GRAPH_PRINT_IRQS)
882 return 0;
883
884 /*
885 * We are inside the irq code
886 */
887 if (*depth_irq >= 0)
888 return 1;
889
890 if ((addr < (unsigned long)__irqentry_text_start) ||
891 (addr >= (unsigned long)__irqentry_text_end))
892 return 0;
893
894 /*
895 * We are entering irq code.
896 */
897 *depth_irq = depth;
898 return 1;
899}
900
901/*
902 * Return check for irq code
903 *
904 * returns 1 if
905 * - we are inside irq code
906 * - we just left irq code
907 *
908 * returns 0 if
909 * - funcgraph-interrupts option is set
910 * - we are not inside irq code
911 */
912static int
913check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
914{
915 int cpu = iter->cpu;
916 struct fgraph_data *data = iter->private;
917 int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
918
919 if (flags & TRACE_GRAPH_PRINT_IRQS)
920 return 0;
921
922 /*
923 * We are not inside the irq code.
924 */
925 if (*depth_irq == -1)
926 return 0;
927
928 /*
929 * We are inside the irq code, and this is returning entry.
930 * Let's not trace it and clear the entry depth, since
931 * we are out of irq code.
932 *
933 * This condition ensures that we 'leave the irq code' once
934 * we are out of the entry depth. Thus protecting us from
935 * the RETURN entry loss.
936 */
937 if (*depth_irq >= depth) {
938 *depth_irq = -1;
939 return 1;
940 }
941
942 /*
943 * We are inside the irq code, and this is not the entry.
944 */
945 return 1;
946}
947
858static enum print_line_t 948static enum print_line_t
859print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, 949print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
860 struct trace_iterator *iter, u32 flags) 950 struct trace_iterator *iter, u32 flags)
@@ -865,6 +955,9 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
865 static enum print_line_t ret; 955 static enum print_line_t ret;
866 int cpu = iter->cpu; 956 int cpu = iter->cpu;
867 957
958 if (check_irq_entry(iter, flags, call->func, call->depth))
959 return TRACE_TYPE_HANDLED;
960
868 if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags)) 961 if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags))
869 return TRACE_TYPE_PARTIAL_LINE; 962 return TRACE_TYPE_PARTIAL_LINE;
870 963
@@ -902,6 +995,9 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
902 int ret; 995 int ret;
903 int i; 996 int i;
904 997
998 if (check_irq_return(iter, flags, trace->depth))
999 return TRACE_TYPE_HANDLED;
1000
905 if (data) { 1001 if (data) {
906 struct fgraph_cpu_data *cpu_data; 1002 struct fgraph_cpu_data *cpu_data;
907 int cpu = iter->cpu; 1003 int cpu = iter->cpu;
@@ -1210,9 +1306,12 @@ void graph_trace_open(struct trace_iterator *iter)
1210 pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid); 1306 pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
1211 int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth); 1307 int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
1212 int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore); 1308 int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore);
1309 int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
1310
1213 *pid = -1; 1311 *pid = -1;
1214 *depth = 0; 1312 *depth = 0;
1215 *ignore = 0; 1313 *ignore = 0;
1314 *depth_irq = -1;
1216 } 1315 }
1217 1316
1218 iter->private = data; 1317 iter->private = data;