diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-09-11 00:30:26 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-09-11 10:59:49 -0400 |
commit | 49ff590390a22c49e9063dcdec4cd5903127526b (patch) | |
tree | f30913673a9d89d2f67cdafeed03afe127511713 /kernel/trace/trace_functions_graph.c | |
parent | fc06b8520b3bf9aaeb2e27debe6719c215bd4916 (diff) |
tracing: add latency format to function_graph tracer
While debugging something with the function_graph tracer, I found the
need to see the preempt count of the traces. Unfortunately, since
the function graph tracer has its own output formatting, it does not
honor the latency-format option.
This patch makes the function_graph tracer honor the latency-format
option, but still keeps control of the output. But now we have the
same details that the latency-format supplies.
# tracer: function_graph
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| /
# ||||
# CPU|||| DURATION FUNCTION CALLS
# | |||| | | | | | |
3) d..1 1.333 us | idle_cpu();
3) d.h1 | tick_check_idle() {
3) d.h1 0.550 us | tick_check_oneshot_broadcast();
3) d.h1 | tick_nohz_stop_idle() {
3) d.h1 | ktime_get() {
3) d.h1 | ktime_get_ts() {
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index b3749a2c3132..ee791a9650c5 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -364,6 +364,29 @@ print_graph_proc(struct trace_seq *s, pid_t pid) | |||
364 | } | 364 | } |
365 | 365 | ||
366 | 366 | ||
367 | static enum print_line_t | ||
368 | print_graph_lat_fmt(struct trace_seq *s, struct trace_entry *entry) | ||
369 | { | ||
370 | int hardirq, softirq; | ||
371 | |||
372 | hardirq = entry->flags & TRACE_FLAG_HARDIRQ; | ||
373 | softirq = entry->flags & TRACE_FLAG_SOFTIRQ; | ||
374 | |||
375 | if (!trace_seq_printf(s, " %c%c%c", | ||
376 | (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : | ||
377 | (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? | ||
378 | 'X' : '.', | ||
379 | (entry->flags & TRACE_FLAG_NEED_RESCHED) ? | ||
380 | 'N' : '.', | ||
381 | (hardirq && softirq) ? 'H' : | ||
382 | hardirq ? 'h' : softirq ? 's' : '.')) | ||
383 | return 0; | ||
384 | |||
385 | if (entry->preempt_count) | ||
386 | return trace_seq_printf(s, "%x", entry->preempt_count); | ||
387 | return trace_seq_puts(s, "."); | ||
388 | } | ||
389 | |||
367 | /* If the pid changed since the last trace, output this event */ | 390 | /* If the pid changed since the last trace, output this event */ |
368 | static enum print_line_t | 391 | static enum print_line_t |
369 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) | 392 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) |
@@ -521,6 +544,7 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, | |||
521 | if (ret == TRACE_TYPE_PARTIAL_LINE) | 544 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
522 | return TRACE_TYPE_PARTIAL_LINE; | 545 | return TRACE_TYPE_PARTIAL_LINE; |
523 | } | 546 | } |
547 | |||
524 | /* Proc */ | 548 | /* Proc */ |
525 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { | 549 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { |
526 | ret = print_graph_proc(s, pid); | 550 | ret = print_graph_proc(s, pid); |
@@ -758,6 +782,13 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, | |||
758 | return TRACE_TYPE_PARTIAL_LINE; | 782 | return TRACE_TYPE_PARTIAL_LINE; |
759 | } | 783 | } |
760 | 784 | ||
785 | /* Latency format */ | ||
786 | if (trace_flags & TRACE_ITER_LATENCY_FMT) { | ||
787 | ret = print_graph_lat_fmt(s, ent); | ||
788 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
789 | return TRACE_TYPE_PARTIAL_LINE; | ||
790 | } | ||
791 | |||
761 | return 0; | 792 | return 0; |
762 | } | 793 | } |
763 | 794 | ||
@@ -952,28 +983,59 @@ print_graph_function(struct trace_iterator *iter) | |||
952 | return TRACE_TYPE_HANDLED; | 983 | return TRACE_TYPE_HANDLED; |
953 | } | 984 | } |
954 | 985 | ||
986 | static void print_lat_header(struct seq_file *s) | ||
987 | { | ||
988 | static const char spaces[] = " " /* 16 spaces */ | ||
989 | " " /* 4 spaces */ | ||
990 | " "; /* 17 spaces */ | ||
991 | int size = 0; | ||
992 | |||
993 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) | ||
994 | size += 16; | ||
995 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) | ||
996 | size += 4; | ||
997 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) | ||
998 | size += 17; | ||
999 | |||
1000 | seq_printf(s, "#%.*s _-----=> irqs-off \n", size, spaces); | ||
1001 | seq_printf(s, "#%.*s / _----=> need-resched \n", size, spaces); | ||
1002 | seq_printf(s, "#%.*s| / _---=> hardirq/softirq \n", size, spaces); | ||
1003 | seq_printf(s, "#%.*s|| / _--=> preempt-depth \n", size, spaces); | ||
1004 | seq_printf(s, "#%.*s||| / \n", size, spaces); | ||
1005 | seq_printf(s, "#%.*s|||| \n", size, spaces); | ||
1006 | } | ||
1007 | |||
955 | static void print_graph_headers(struct seq_file *s) | 1008 | static void print_graph_headers(struct seq_file *s) |
956 | { | 1009 | { |
1010 | int lat = trace_flags & TRACE_ITER_LATENCY_FMT; | ||
1011 | |||
1012 | if (lat) | ||
1013 | print_lat_header(s); | ||
1014 | |||
957 | /* 1st line */ | 1015 | /* 1st line */ |
958 | seq_printf(s, "# "); | 1016 | seq_printf(s, "#"); |
959 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) | 1017 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) |
960 | seq_printf(s, " TIME "); | 1018 | seq_printf(s, " TIME "); |
961 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) | 1019 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) |
962 | seq_printf(s, "CPU"); | 1020 | seq_printf(s, " CPU"); |
963 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) | 1021 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) |
964 | seq_printf(s, " TASK/PID "); | 1022 | seq_printf(s, " TASK/PID "); |
1023 | if (lat) | ||
1024 | seq_printf(s, "||||"); | ||
965 | if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) | 1025 | if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) |
966 | seq_printf(s, " DURATION "); | 1026 | seq_printf(s, " DURATION "); |
967 | seq_printf(s, " FUNCTION CALLS\n"); | 1027 | seq_printf(s, " FUNCTION CALLS\n"); |
968 | 1028 | ||
969 | /* 2nd line */ | 1029 | /* 2nd line */ |
970 | seq_printf(s, "# "); | 1030 | seq_printf(s, "#"); |
971 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) | 1031 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) |
972 | seq_printf(s, " | "); | 1032 | seq_printf(s, " | "); |
973 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) | 1033 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) |
974 | seq_printf(s, "| "); | 1034 | seq_printf(s, " | "); |
975 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) | 1035 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) |
976 | seq_printf(s, " | | "); | 1036 | seq_printf(s, " | | "); |
1037 | if (lat) | ||
1038 | seq_printf(s, "||||"); | ||
977 | if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) | 1039 | if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) |
978 | seq_printf(s, " | | "); | 1040 | seq_printf(s, " | | "); |
979 | seq_printf(s, " | | | |\n"); | 1041 | seq_printf(s, " | | | |\n"); |