diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-03-19 13:24:42 -0400 |
---|---|---|
committer | Steven Rostedt <srostedt@redhat.com> | 2009-03-19 15:58:38 -0400 |
commit | 2fbcdb35aca614f9529a0e7d340146cf0b71684f (patch) | |
tree | 02b717134d9d82b1f9a7cebd4e3daccde542cf5c /kernel/trace/trace_functions_graph.c | |
parent | 5ef841f6f32dce0b752a4fa0622781ee67a0e874 (diff) |
function-graph: calculate function depth within function graph tracer
Currently, the function graph tracer depends on the trace_printk
to record the depth. All the information is already there in the trace
to calculate function depth, with the exception of having the printk
be the first item. But as soon as a entry or exit is reached, then
we know the depth.
This patch changes the iter->private data from recording a per cpu
last_pid, to a structure that holds both the last_pid and the current
depth. This data is used to determine the function depth for the
printks.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 2d4d185cd0d8..66ea23b64fe6 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -14,6 +14,11 @@ | |||
14 | #include "trace.h" | 14 | #include "trace.h" |
15 | #include "trace_output.h" | 15 | #include "trace_output.h" |
16 | 16 | ||
17 | struct fgraph_data { | ||
18 | pid_t last_pid; | ||
19 | int depth; | ||
20 | }; | ||
21 | |||
17 | #define TRACE_GRAPH_INDENT 2 | 22 | #define TRACE_GRAPH_INDENT 2 |
18 | 23 | ||
19 | /* Flag options */ | 24 | /* Flag options */ |
@@ -231,16 +236,16 @@ print_graph_proc(struct trace_seq *s, pid_t pid) | |||
231 | 236 | ||
232 | /* If the pid changed since the last trace, output this event */ | 237 | /* If the pid changed since the last trace, output this event */ |
233 | static enum print_line_t | 238 | static enum print_line_t |
234 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, pid_t *last_pids_cpu) | 239 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) |
235 | { | 240 | { |
236 | pid_t prev_pid; | 241 | pid_t prev_pid; |
237 | pid_t *last_pid; | 242 | pid_t *last_pid; |
238 | int ret; | 243 | int ret; |
239 | 244 | ||
240 | if (!last_pids_cpu) | 245 | if (!data) |
241 | return TRACE_TYPE_HANDLED; | 246 | return TRACE_TYPE_HANDLED; |
242 | 247 | ||
243 | last_pid = per_cpu_ptr(last_pids_cpu, cpu); | 248 | last_pid = &(per_cpu_ptr(data, cpu)->last_pid); |
244 | 249 | ||
245 | if (*last_pid == pid) | 250 | if (*last_pid == pid) |
246 | return TRACE_TYPE_HANDLED; | 251 | return TRACE_TYPE_HANDLED; |
@@ -471,6 +476,7 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
471 | struct ftrace_graph_ent_entry *entry, | 476 | struct ftrace_graph_ent_entry *entry, |
472 | struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) | 477 | struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) |
473 | { | 478 | { |
479 | struct fgraph_data *data = iter->private; | ||
474 | struct ftrace_graph_ret *graph_ret; | 480 | struct ftrace_graph_ret *graph_ret; |
475 | struct ftrace_graph_ent *call; | 481 | struct ftrace_graph_ent *call; |
476 | unsigned long long duration; | 482 | unsigned long long duration; |
@@ -481,6 +487,18 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
481 | call = &entry->graph_ent; | 487 | call = &entry->graph_ent; |
482 | duration = graph_ret->rettime - graph_ret->calltime; | 488 | duration = graph_ret->rettime - graph_ret->calltime; |
483 | 489 | ||
490 | if (data) { | ||
491 | int cpu = iter->cpu; | ||
492 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
493 | |||
494 | /* | ||
495 | * Comments display at + 1 to depth. Since | ||
496 | * this is a leaf function, keep the comments | ||
497 | * equal to this depth. | ||
498 | */ | ||
499 | *depth = call->depth - 1; | ||
500 | } | ||
501 | |||
484 | /* Overhead */ | 502 | /* Overhead */ |
485 | ret = print_graph_overhead(duration, s); | 503 | ret = print_graph_overhead(duration, s); |
486 | if (!ret) | 504 | if (!ret) |
@@ -512,12 +530,21 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
512 | } | 530 | } |
513 | 531 | ||
514 | static enum print_line_t | 532 | static enum print_line_t |
515 | print_graph_entry_nested(struct ftrace_graph_ent_entry *entry, | 533 | print_graph_entry_nested(struct trace_iterator *iter, |
516 | struct trace_seq *s, pid_t pid, int cpu) | 534 | struct ftrace_graph_ent_entry *entry, |
535 | struct trace_seq *s, int cpu) | ||
517 | { | 536 | { |
518 | int i; | ||
519 | int ret; | ||
520 | struct ftrace_graph_ent *call = &entry->graph_ent; | 537 | struct ftrace_graph_ent *call = &entry->graph_ent; |
538 | struct fgraph_data *data = iter->private; | ||
539 | int ret; | ||
540 | int i; | ||
541 | |||
542 | if (data) { | ||
543 | int cpu = iter->cpu; | ||
544 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
545 | |||
546 | *depth = call->depth; | ||
547 | } | ||
521 | 548 | ||
522 | /* No overhead */ | 549 | /* No overhead */ |
523 | ret = print_graph_overhead(-1, s); | 550 | ret = print_graph_overhead(-1, s); |
@@ -557,13 +584,13 @@ static enum print_line_t | |||
557 | print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, | 584 | print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, |
558 | int type, unsigned long addr) | 585 | int type, unsigned long addr) |
559 | { | 586 | { |
587 | struct fgraph_data *data = iter->private; | ||
560 | struct trace_entry *ent = iter->ent; | 588 | struct trace_entry *ent = iter->ent; |
561 | pid_t *last_pid = iter->private; | ||
562 | int cpu = iter->cpu; | 589 | int cpu = iter->cpu; |
563 | int ret; | 590 | int ret; |
564 | 591 | ||
565 | /* Pid */ | 592 | /* Pid */ |
566 | if (verif_pid(s, ent->pid, cpu, last_pid) == TRACE_TYPE_PARTIAL_LINE) | 593 | if (verif_pid(s, ent->pid, cpu, data) == TRACE_TYPE_PARTIAL_LINE) |
567 | return TRACE_TYPE_PARTIAL_LINE; | 594 | return TRACE_TYPE_PARTIAL_LINE; |
568 | 595 | ||
569 | if (type) { | 596 | if (type) { |
@@ -616,7 +643,7 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, | |||
616 | if (leaf_ret) | 643 | if (leaf_ret) |
617 | return print_graph_entry_leaf(iter, field, leaf_ret, s); | 644 | return print_graph_entry_leaf(iter, field, leaf_ret, s); |
618 | else | 645 | else |
619 | return print_graph_entry_nested(field, s, iter->ent->pid, cpu); | 646 | return print_graph_entry_nested(iter, field, s, cpu); |
620 | 647 | ||
621 | } | 648 | } |
622 | 649 | ||
@@ -624,11 +651,24 @@ static enum print_line_t | |||
624 | print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, | 651 | print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, |
625 | struct trace_entry *ent, struct trace_iterator *iter) | 652 | struct trace_entry *ent, struct trace_iterator *iter) |
626 | { | 653 | { |
627 | int i; | ||
628 | int ret; | ||
629 | int cpu = iter->cpu; | ||
630 | pid_t pid = ent->pid; | ||
631 | unsigned long long duration = trace->rettime - trace->calltime; | 654 | unsigned long long duration = trace->rettime - trace->calltime; |
655 | struct fgraph_data *data = iter->private; | ||
656 | pid_t pid = ent->pid; | ||
657 | int cpu = iter->cpu; | ||
658 | int ret; | ||
659 | int i; | ||
660 | |||
661 | if (data) { | ||
662 | int cpu = iter->cpu; | ||
663 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
664 | |||
665 | /* | ||
666 | * Comments display at + 1 to depth. This is the | ||
667 | * return from a function, we now want the comments | ||
668 | * to display at the same level of the bracket. | ||
669 | */ | ||
670 | *depth = trace->depth - 1; | ||
671 | } | ||
632 | 672 | ||
633 | if (print_graph_prologue(iter, s, 0, 0)) | 673 | if (print_graph_prologue(iter, s, 0, 0)) |
634 | return TRACE_TYPE_PARTIAL_LINE; | 674 | return TRACE_TYPE_PARTIAL_LINE; |
@@ -675,8 +715,13 @@ static enum print_line_t | |||
675 | print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | 715 | print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, |
676 | struct trace_entry *ent, struct trace_iterator *iter) | 716 | struct trace_entry *ent, struct trace_iterator *iter) |
677 | { | 717 | { |
678 | int i; | 718 | struct fgraph_data *data = iter->private; |
719 | int depth = 0; | ||
679 | int ret; | 720 | int ret; |
721 | int i; | ||
722 | |||
723 | if (data) | ||
724 | depth = per_cpu_ptr(data, iter->cpu)->depth; | ||
680 | 725 | ||
681 | if (print_graph_prologue(iter, s, 0, 0)) | 726 | if (print_graph_prologue(iter, s, 0, 0)) |
682 | return TRACE_TYPE_PARTIAL_LINE; | 727 | return TRACE_TYPE_PARTIAL_LINE; |
@@ -694,8 +739,8 @@ print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | |||
694 | } | 739 | } |
695 | 740 | ||
696 | /* Indentation */ | 741 | /* Indentation */ |
697 | if (trace->depth > 0) | 742 | if (depth > 0) |
698 | for (i = 0; i < (trace->depth + 1) * TRACE_GRAPH_INDENT; i++) { | 743 | for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++) { |
699 | ret = trace_seq_printf(s, " "); | 744 | ret = trace_seq_printf(s, " "); |
700 | if (!ret) | 745 | if (!ret) |
701 | return TRACE_TYPE_PARTIAL_LINE; | 746 | return TRACE_TYPE_PARTIAL_LINE; |
@@ -780,19 +825,21 @@ static void print_graph_headers(struct seq_file *s) | |||
780 | 825 | ||
781 | static void graph_trace_open(struct trace_iterator *iter) | 826 | static void graph_trace_open(struct trace_iterator *iter) |
782 | { | 827 | { |
783 | /* pid on the last trace processed */ | 828 | /* pid and depth on the last trace processed */ |
784 | pid_t *last_pid = alloc_percpu(pid_t); | 829 | struct fgraph_data *data = alloc_percpu(struct fgraph_data); |
785 | int cpu; | 830 | int cpu; |
786 | 831 | ||
787 | if (!last_pid) | 832 | if (!data) |
788 | pr_warning("function graph tracer: not enough memory\n"); | 833 | pr_warning("function graph tracer: not enough memory\n"); |
789 | else | 834 | else |
790 | for_each_possible_cpu(cpu) { | 835 | for_each_possible_cpu(cpu) { |
791 | pid_t *pid = per_cpu_ptr(last_pid, cpu); | 836 | pid_t *pid = &(per_cpu_ptr(data, cpu)->last_pid); |
837 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
792 | *pid = -1; | 838 | *pid = -1; |
839 | *depth = 0; | ||
793 | } | 840 | } |
794 | 841 | ||
795 | iter->private = last_pid; | 842 | iter->private = data; |
796 | } | 843 | } |
797 | 844 | ||
798 | static void graph_trace_close(struct trace_iterator *iter) | 845 | static void graph_trace_close(struct trace_iterator *iter) |