2 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
4 * Handle the callchains from the stream in an ad-hoc radix tree and then
5 * sort them in an rbtree.
7 * Using a radix for code path provides a fast retrieval and factorizes
8 * memory use. Also that lets us use the paths in a hierarchical graph view.
25 #include "callchain.h"
27 #define CALLCHAIN_PARAM_DEFAULT \
28 .mode = CHAIN_GRAPH_ABS, \
30 .order = ORDER_CALLEE, \
31 .key = CCKEY_FUNCTION, \
32 .value = CCVAL_PERCENT, \
34 struct callchain_param callchain_param = {
35 CALLCHAIN_PARAM_DEFAULT
38 struct callchain_param callchain_param_default
= {
39 CALLCHAIN_PARAM_DEFAULT
42 __thread
struct callchain_cursor callchain_cursor
;
44 int parse_callchain_record_opt(const char *arg
, struct callchain_param
*param
)
46 return parse_callchain_record(arg
, param
);
49 static int parse_callchain_mode(const char *value
)
51 if (!strncmp(value
, "graph", strlen(value
))) {
52 callchain_param
.mode
= CHAIN_GRAPH_ABS
;
55 if (!strncmp(value
, "flat", strlen(value
))) {
56 callchain_param
.mode
= CHAIN_FLAT
;
59 if (!strncmp(value
, "fractal", strlen(value
))) {
60 callchain_param
.mode
= CHAIN_GRAPH_REL
;
63 if (!strncmp(value
, "folded", strlen(value
))) {
64 callchain_param
.mode
= CHAIN_FOLDED
;
68 pr_err("Invalid callchain mode: %s\n", value
);
72 static int parse_callchain_order(const char *value
)
74 if (!strncmp(value
, "caller", strlen(value
))) {
75 callchain_param
.order
= ORDER_CALLER
;
76 callchain_param
.order_set
= true;
79 if (!strncmp(value
, "callee", strlen(value
))) {
80 callchain_param
.order
= ORDER_CALLEE
;
81 callchain_param
.order_set
= true;
85 pr_err("Invalid callchain order: %s\n", value
);
89 static int parse_callchain_sort_key(const char *value
)
91 if (!strncmp(value
, "function", strlen(value
))) {
92 callchain_param
.key
= CCKEY_FUNCTION
;
95 if (!strncmp(value
, "address", strlen(value
))) {
96 callchain_param
.key
= CCKEY_ADDRESS
;
99 if (!strncmp(value
, "srcline", strlen(value
))) {
100 callchain_param
.key
= CCKEY_SRCLINE
;
103 if (!strncmp(value
, "branch", strlen(value
))) {
104 callchain_param
.branch_callstack
= 1;
108 pr_err("Invalid callchain sort key: %s\n", value
);
112 static int parse_callchain_value(const char *value
)
114 if (!strncmp(value
, "percent", strlen(value
))) {
115 callchain_param
.value
= CCVAL_PERCENT
;
118 if (!strncmp(value
, "period", strlen(value
))) {
119 callchain_param
.value
= CCVAL_PERIOD
;
122 if (!strncmp(value
, "count", strlen(value
))) {
123 callchain_param
.value
= CCVAL_COUNT
;
127 pr_err("Invalid callchain config key: %s\n", value
);
131 static int get_stack_size(const char *str
, unsigned long *_size
)
135 unsigned long max_size
= round_down(USHRT_MAX
, sizeof(u64
));
137 size
= strtoul(str
, &endptr
, 0);
143 size
= round_up(size
, sizeof(u64
));
144 if (!size
|| size
> max_size
)
152 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
158 __parse_callchain_report_opt(const char *arg
, bool allow_record_opt
)
161 char *endptr
, *saveptr
= NULL
;
162 bool minpcnt_set
= false;
163 bool record_opt_set
= false;
164 bool try_stack_size
= false;
166 callchain_param
.enabled
= true;
167 symbol_conf
.use_callchain
= true;
172 while ((tok
= strtok_r((char *)arg
, ",", &saveptr
)) != NULL
) {
173 if (!strncmp(tok
, "none", strlen(tok
))) {
174 callchain_param
.mode
= CHAIN_NONE
;
175 callchain_param
.enabled
= false;
176 symbol_conf
.use_callchain
= false;
180 if (!parse_callchain_mode(tok
) ||
181 !parse_callchain_order(tok
) ||
182 !parse_callchain_sort_key(tok
) ||
183 !parse_callchain_value(tok
)) {
184 /* parsing ok - move on to the next */
185 try_stack_size
= false;
187 } else if (allow_record_opt
&& !record_opt_set
) {
188 if (parse_callchain_record(tok
, &callchain_param
))
191 /* assume that number followed by 'dwarf' is stack size */
192 if (callchain_param
.record_mode
== CALLCHAIN_DWARF
)
193 try_stack_size
= true;
195 record_opt_set
= true;
200 if (try_stack_size
) {
201 unsigned long size
= 0;
203 if (get_stack_size(tok
, &size
) < 0)
205 callchain_param
.dump_size
= size
;
206 try_stack_size
= false;
207 } else if (!minpcnt_set
) {
208 /* try to get the min percent */
209 callchain_param
.min_percent
= strtod(tok
, &endptr
);
214 /* try print limit at last */
215 callchain_param
.print_limit
= strtoul(tok
, &endptr
, 0);
223 if (callchain_register_param(&callchain_param
) < 0) {
224 pr_err("Can't register callchain params\n");
230 int parse_callchain_report_opt(const char *arg
)
232 return __parse_callchain_report_opt(arg
, false);
235 int parse_callchain_top_opt(const char *arg
)
237 return __parse_callchain_report_opt(arg
, true);
240 int parse_callchain_record(const char *arg
, struct callchain_param
*param
)
242 char *tok
, *name
, *saveptr
= NULL
;
246 /* We need buffer that we know we can write to. */
247 buf
= malloc(strlen(arg
) + 1);
253 tok
= strtok_r((char *)buf
, ",", &saveptr
);
254 name
= tok
? : (char *)buf
;
257 /* Framepointer style */
258 if (!strncmp(name
, "fp", sizeof("fp"))) {
259 if (!strtok_r(NULL
, ",", &saveptr
)) {
260 param
->record_mode
= CALLCHAIN_FP
;
263 pr_err("callchain: No more arguments "
264 "needed for --call-graph fp\n");
268 } else if (!strncmp(name
, "dwarf", sizeof("dwarf"))) {
269 const unsigned long default_stack_dump_size
= 8192;
272 param
->record_mode
= CALLCHAIN_DWARF
;
273 param
->dump_size
= default_stack_dump_size
;
275 tok
= strtok_r(NULL
, ",", &saveptr
);
277 unsigned long size
= 0;
279 ret
= get_stack_size(tok
, &size
);
280 param
->dump_size
= size
;
282 } else if (!strncmp(name
, "lbr", sizeof("lbr"))) {
283 if (!strtok_r(NULL
, ",", &saveptr
)) {
284 param
->record_mode
= CALLCHAIN_LBR
;
287 pr_err("callchain: No more arguments "
288 "needed for --call-graph lbr\n");
291 pr_err("callchain: Unknown --call-graph option "
302 int perf_callchain_config(const char *var
, const char *value
)
306 if (prefixcmp(var
, "call-graph."))
308 var
+= sizeof("call-graph.") - 1;
310 if (!strcmp(var
, "record-mode"))
311 return parse_callchain_record_opt(value
, &callchain_param
);
312 if (!strcmp(var
, "dump-size")) {
313 unsigned long size
= 0;
316 ret
= get_stack_size(value
, &size
);
317 callchain_param
.dump_size
= size
;
321 if (!strcmp(var
, "print-type"))
322 return parse_callchain_mode(value
);
323 if (!strcmp(var
, "order"))
324 return parse_callchain_order(value
);
325 if (!strcmp(var
, "sort-key"))
326 return parse_callchain_sort_key(value
);
327 if (!strcmp(var
, "threshold")) {
328 callchain_param
.min_percent
= strtod(value
, &endptr
);
329 if (value
== endptr
) {
330 pr_err("Invalid callchain threshold: %s\n", value
);
334 if (!strcmp(var
, "print-limit")) {
335 callchain_param
.print_limit
= strtod(value
, &endptr
);
336 if (value
== endptr
) {
337 pr_err("Invalid callchain print limit: %s\n", value
);
346 rb_insert_callchain(struct rb_root
*root
, struct callchain_node
*chain
,
347 enum chain_mode mode
)
349 struct rb_node
**p
= &root
->rb_node
;
350 struct rb_node
*parent
= NULL
;
351 struct callchain_node
*rnode
;
352 u64 chain_cumul
= callchain_cumul_hits(chain
);
358 rnode
= rb_entry(parent
, struct callchain_node
, rb_node
);
359 rnode_cumul
= callchain_cumul_hits(rnode
);
364 if (rnode
->hit
< chain
->hit
)
369 case CHAIN_GRAPH_ABS
: /* Falldown */
370 case CHAIN_GRAPH_REL
:
371 if (rnode_cumul
< chain_cumul
)
382 rb_link_node(&chain
->rb_node
, parent
, p
);
383 rb_insert_color(&chain
->rb_node
, root
);
387 __sort_chain_flat(struct rb_root
*rb_root
, struct callchain_node
*node
,
391 struct callchain_node
*child
;
393 n
= rb_first(&node
->rb_root_in
);
395 child
= rb_entry(n
, struct callchain_node
, rb_node_in
);
398 __sort_chain_flat(rb_root
, child
, min_hit
);
401 if (node
->hit
&& node
->hit
>= min_hit
)
402 rb_insert_callchain(rb_root
, node
, CHAIN_FLAT
);
406 * Once we get every callchains from the stream, we can now
410 sort_chain_flat(struct rb_root
*rb_root
, struct callchain_root
*root
,
411 u64 min_hit
, struct callchain_param
*param __maybe_unused
)
414 __sort_chain_flat(rb_root
, &root
->node
, min_hit
);
417 static void __sort_chain_graph_abs(struct callchain_node
*node
,
421 struct callchain_node
*child
;
423 node
->rb_root
= RB_ROOT
;
424 n
= rb_first(&node
->rb_root_in
);
427 child
= rb_entry(n
, struct callchain_node
, rb_node_in
);
430 __sort_chain_graph_abs(child
, min_hit
);
431 if (callchain_cumul_hits(child
) >= min_hit
)
432 rb_insert_callchain(&node
->rb_root
, child
,
438 sort_chain_graph_abs(struct rb_root
*rb_root
, struct callchain_root
*chain_root
,
439 u64 min_hit
, struct callchain_param
*param __maybe_unused
)
441 __sort_chain_graph_abs(&chain_root
->node
, min_hit
);
442 rb_root
->rb_node
= chain_root
->node
.rb_root
.rb_node
;
445 static void __sort_chain_graph_rel(struct callchain_node
*node
,
449 struct callchain_node
*child
;
452 node
->rb_root
= RB_ROOT
;
453 min_hit
= ceil(node
->children_hit
* min_percent
);
455 n
= rb_first(&node
->rb_root_in
);
457 child
= rb_entry(n
, struct callchain_node
, rb_node_in
);
460 __sort_chain_graph_rel(child
, min_percent
);
461 if (callchain_cumul_hits(child
) >= min_hit
)
462 rb_insert_callchain(&node
->rb_root
, child
,
468 sort_chain_graph_rel(struct rb_root
*rb_root
, struct callchain_root
*chain_root
,
469 u64 min_hit __maybe_unused
, struct callchain_param
*param
)
471 __sort_chain_graph_rel(&chain_root
->node
, param
->min_percent
/ 100.0);
472 rb_root
->rb_node
= chain_root
->node
.rb_root
.rb_node
;
475 int callchain_register_param(struct callchain_param
*param
)
477 switch (param
->mode
) {
478 case CHAIN_GRAPH_ABS
:
479 param
->sort
= sort_chain_graph_abs
;
481 case CHAIN_GRAPH_REL
:
482 param
->sort
= sort_chain_graph_rel
;
486 param
->sort
= sort_chain_flat
;
496 * Create a child for a parent. If inherit_children, then the new child
497 * will become the new parent of it's parent children
499 static struct callchain_node
*
500 create_child(struct callchain_node
*parent
, bool inherit_children
)
502 struct callchain_node
*new;
504 new = zalloc(sizeof(*new));
506 perror("not enough memory to create child for code path tree");
509 new->parent
= parent
;
510 INIT_LIST_HEAD(&new->val
);
511 INIT_LIST_HEAD(&new->parent_val
);
513 if (inherit_children
) {
515 struct callchain_node
*child
;
517 new->rb_root_in
= parent
->rb_root_in
;
518 parent
->rb_root_in
= RB_ROOT
;
520 n
= rb_first(&new->rb_root_in
);
522 child
= rb_entry(n
, struct callchain_node
, rb_node_in
);
527 /* make it the first child */
528 rb_link_node(&new->rb_node_in
, NULL
, &parent
->rb_root_in
.rb_node
);
529 rb_insert_color(&new->rb_node_in
, &parent
->rb_root_in
);
537 * Fill the node with callchain values
540 fill_node(struct callchain_node
*node
, struct callchain_cursor
*cursor
)
542 struct callchain_cursor_node
*cursor_node
;
544 node
->val_nr
= cursor
->nr
- cursor
->pos
;
546 pr_warning("Warning: empty node in callchain tree\n");
548 cursor_node
= callchain_cursor_current(cursor
);
550 while (cursor_node
) {
551 struct callchain_list
*call
;
553 call
= zalloc(sizeof(*call
));
555 perror("not enough memory for the code path tree");
558 call
->ip
= cursor_node
->ip
;
559 call
->ms
.sym
= cursor_node
->sym
;
560 call
->ms
.map
= map__get(cursor_node
->map
);
562 if (cursor_node
->branch
) {
563 call
->branch_count
= 1;
565 if (cursor_node
->branch_flags
.predicted
)
566 call
->predicted_count
= 1;
568 if (cursor_node
->branch_flags
.abort
)
569 call
->abort_count
= 1;
571 call
->cycles_count
= cursor_node
->branch_flags
.cycles
;
572 call
->iter_count
= cursor_node
->nr_loop_iter
;
573 call
->samples_count
= cursor_node
->samples
;
576 list_add_tail(&call
->list
, &node
->val
);
578 callchain_cursor_advance(cursor
);
579 cursor_node
= callchain_cursor_current(cursor
);
584 static struct callchain_node
*
585 add_child(struct callchain_node
*parent
,
586 struct callchain_cursor
*cursor
,
589 struct callchain_node
*new;
591 new = create_child(parent
, false);
595 if (fill_node(new, cursor
) < 0) {
596 struct callchain_list
*call
, *tmp
;
598 list_for_each_entry_safe(call
, tmp
, &new->val
, list
) {
599 list_del(&call
->list
);
600 map__zput(call
->ms
.map
);
607 new->children_hit
= 0;
609 new->children_count
= 0;
621 static enum match_result
match_chain_srcline(struct callchain_cursor_node
*node
,
622 struct callchain_list
*cnode
)
626 enum match_result ret
= MATCH_EQ
;
630 left
= get_srcline(cnode
->ms
.map
->dso
,
631 map__rip_2objdump(cnode
->ms
.map
, cnode
->ip
),
632 cnode
->ms
.sym
, true, false);
634 right
= get_srcline(node
->map
->dso
,
635 map__rip_2objdump(node
->map
, node
->ip
),
636 node
->sym
, true, false);
639 cmp
= strcmp(left
, right
);
640 else if (!left
&& right
)
642 else if (left
&& !right
)
644 else if (cnode
->ip
== node
->ip
)
647 cmp
= (cnode
->ip
< node
->ip
) ? -1 : 1;
650 ret
= cmp
< 0 ? MATCH_LT
: MATCH_GT
;
657 static enum match_result
match_chain(struct callchain_cursor_node
*node
,
658 struct callchain_list
*cnode
)
660 struct symbol
*sym
= node
->sym
;
663 if (callchain_param
.key
== CCKEY_SRCLINE
) {
664 enum match_result match
= match_chain_srcline(node
, cnode
);
666 if (match
!= MATCH_ERROR
)
670 if (cnode
->ms
.sym
&& sym
&& callchain_param
.key
== CCKEY_FUNCTION
) {
671 left
= cnode
->ms
.sym
->start
;
680 cnode
->branch_count
++;
682 if (node
->branch_flags
.predicted
)
683 cnode
->predicted_count
++;
685 if (node
->branch_flags
.abort
)
686 cnode
->abort_count
++;
688 cnode
->cycles_count
+= node
->branch_flags
.cycles
;
689 cnode
->iter_count
+= node
->nr_loop_iter
;
690 cnode
->samples_count
+= node
->samples
;
696 return left
> right
? MATCH_GT
: MATCH_LT
;
700 * Split the parent in two parts (a new child is created) and
701 * give a part of its callchain to the created child.
702 * Then create another child to host the given callchain of new branch
705 split_add_child(struct callchain_node
*parent
,
706 struct callchain_cursor
*cursor
,
707 struct callchain_list
*to_split
,
708 u64 idx_parents
, u64 idx_local
, u64 period
)
710 struct callchain_node
*new;
711 struct list_head
*old_tail
;
712 unsigned int idx_total
= idx_parents
+ idx_local
;
715 new = create_child(parent
, true);
719 /* split the callchain and move a part to the new child */
720 old_tail
= parent
->val
.prev
;
721 list_del_range(&to_split
->list
, old_tail
);
722 new->val
.next
= &to_split
->list
;
723 new->val
.prev
= old_tail
;
724 to_split
->list
.prev
= &new->val
;
725 old_tail
->next
= &new->val
;
728 new->hit
= parent
->hit
;
729 new->children_hit
= parent
->children_hit
;
730 parent
->children_hit
= callchain_cumul_hits(new);
731 new->val_nr
= parent
->val_nr
- idx_local
;
732 parent
->val_nr
= idx_local
;
733 new->count
= parent
->count
;
734 new->children_count
= parent
->children_count
;
735 parent
->children_count
= callchain_cumul_counts(new);
737 /* create a new child for the new branch if any */
738 if (idx_total
< cursor
->nr
) {
739 struct callchain_node
*first
;
740 struct callchain_list
*cnode
;
741 struct callchain_cursor_node
*node
;
742 struct rb_node
*p
, **pp
;
745 parent
->children_hit
+= period
;
747 parent
->children_count
+= 1;
749 node
= callchain_cursor_current(cursor
);
750 new = add_child(parent
, cursor
, period
);
755 * This is second child since we moved parent's children
756 * to new (first) child above.
758 p
= parent
->rb_root_in
.rb_node
;
759 first
= rb_entry(p
, struct callchain_node
, rb_node_in
);
760 cnode
= list_first_entry(&first
->val
, struct callchain_list
,
763 if (match_chain(node
, cnode
) == MATCH_LT
)
768 rb_link_node(&new->rb_node_in
, p
, pp
);
769 rb_insert_color(&new->rb_node_in
, &parent
->rb_root_in
);
771 parent
->hit
= period
;
777 static enum match_result
778 append_chain(struct callchain_node
*root
,
779 struct callchain_cursor
*cursor
,
783 append_chain_children(struct callchain_node
*root
,
784 struct callchain_cursor
*cursor
,
787 struct callchain_node
*rnode
;
788 struct callchain_cursor_node
*node
;
789 struct rb_node
**p
= &root
->rb_root_in
.rb_node
;
790 struct rb_node
*parent
= NULL
;
792 node
= callchain_cursor_current(cursor
);
796 /* lookup in childrens */
798 enum match_result ret
;
801 rnode
= rb_entry(parent
, struct callchain_node
, rb_node_in
);
803 /* If at least first entry matches, rely to children */
804 ret
= append_chain(rnode
, cursor
, period
);
806 goto inc_children_hit
;
807 if (ret
== MATCH_ERROR
)
811 p
= &parent
->rb_left
;
813 p
= &parent
->rb_right
;
815 /* nothing in children, add to the current node */
816 rnode
= add_child(root
, cursor
, period
);
820 rb_link_node(&rnode
->rb_node_in
, parent
, p
);
821 rb_insert_color(&rnode
->rb_node_in
, &root
->rb_root_in
);
824 root
->children_hit
+= period
;
825 root
->children_count
++;
829 static enum match_result
830 append_chain(struct callchain_node
*root
,
831 struct callchain_cursor
*cursor
,
834 struct callchain_list
*cnode
;
835 u64 start
= cursor
->pos
;
838 enum match_result cmp
= MATCH_ERROR
;
841 * Lookup in the current node
842 * If we have a symbol, then compare the start to match
843 * anywhere inside a function, unless function
846 list_for_each_entry(cnode
, &root
->val
, list
) {
847 struct callchain_cursor_node
*node
;
849 node
= callchain_cursor_current(cursor
);
853 cmp
= match_chain(node
, cnode
);
859 callchain_cursor_advance(cursor
);
862 /* matches not, relay no the parent */
864 WARN_ONCE(cmp
== MATCH_ERROR
, "Chain comparison error\n");
868 matches
= cursor
->pos
- start
;
870 /* we match only a part of the node. Split it and add the new chain */
871 if (matches
< root
->val_nr
) {
872 if (split_add_child(root
, cursor
, cnode
, start
, matches
,
879 /* we match 100% of the path, increment the hit */
880 if (matches
== root
->val_nr
&& cursor
->pos
== cursor
->nr
) {
886 /* We match the node and still have a part remaining */
887 if (append_chain_children(root
, cursor
, period
) < 0)
893 int callchain_append(struct callchain_root
*root
,
894 struct callchain_cursor
*cursor
,
900 callchain_cursor_commit(cursor
);
902 if (append_chain_children(&root
->node
, cursor
, period
) < 0)
905 if (cursor
->nr
> root
->max_depth
)
906 root
->max_depth
= cursor
->nr
;
912 merge_chain_branch(struct callchain_cursor
*cursor
,
913 struct callchain_node
*dst
, struct callchain_node
*src
)
915 struct callchain_cursor_node
**old_last
= cursor
->last
;
916 struct callchain_node
*child
;
917 struct callchain_list
*list
, *next_list
;
919 int old_pos
= cursor
->nr
;
922 list_for_each_entry_safe(list
, next_list
, &src
->val
, list
) {
923 callchain_cursor_append(cursor
, list
->ip
,
924 list
->ms
.map
, list
->ms
.sym
,
926 list_del(&list
->list
);
927 map__zput(list
->ms
.map
);
932 callchain_cursor_commit(cursor
);
933 if (append_chain_children(dst
, cursor
, src
->hit
) < 0)
937 n
= rb_first(&src
->rb_root_in
);
939 child
= container_of(n
, struct callchain_node
, rb_node_in
);
941 rb_erase(&child
->rb_node_in
, &src
->rb_root_in
);
943 err
= merge_chain_branch(cursor
, dst
, child
);
950 cursor
->nr
= old_pos
;
951 cursor
->last
= old_last
;
956 int callchain_merge(struct callchain_cursor
*cursor
,
957 struct callchain_root
*dst
, struct callchain_root
*src
)
959 return merge_chain_branch(cursor
, &dst
->node
, &src
->node
);
962 int callchain_cursor_append(struct callchain_cursor
*cursor
,
963 u64 ip
, struct map
*map
, struct symbol
*sym
,
964 bool branch
, struct branch_flags
*flags
,
965 int nr_loop_iter
, int samples
)
967 struct callchain_cursor_node
*node
= *cursor
->last
;
970 node
= calloc(1, sizeof(*node
));
974 *cursor
->last
= node
;
978 map__zput(node
->map
);
979 node
->map
= map__get(map
);
981 node
->branch
= branch
;
982 node
->nr_loop_iter
= nr_loop_iter
;
983 node
->samples
= samples
;
986 memcpy(&node
->branch_flags
, flags
,
987 sizeof(struct branch_flags
));
991 cursor
->last
= &node
->next
;
996 int sample__resolve_callchain(struct perf_sample
*sample
,
997 struct callchain_cursor
*cursor
, struct symbol
**parent
,
998 struct perf_evsel
*evsel
, struct addr_location
*al
,
1001 if (sample
->callchain
== NULL
)
1004 if (symbol_conf
.use_callchain
|| symbol_conf
.cumulate_callchain
||
1005 perf_hpp_list
.parent
) {
1006 return thread__resolve_callchain(al
->thread
, cursor
, evsel
, sample
,
1007 parent
, al
, max_stack
);
1012 int hist_entry__append_callchain(struct hist_entry
*he
, struct perf_sample
*sample
)
1014 if (!symbol_conf
.use_callchain
|| sample
->callchain
== NULL
)
1016 return callchain_append(he
->callchain
, &callchain_cursor
, sample
->period
);
1019 int fill_callchain_info(struct addr_location
*al
, struct callchain_cursor_node
*node
,
1020 bool hide_unresolved
)
1022 al
->map
= node
->map
;
1023 al
->sym
= node
->sym
;
1025 al
->addr
= node
->map
->map_ip(node
->map
, node
->ip
);
1027 al
->addr
= node
->ip
;
1029 if (al
->sym
== NULL
) {
1030 if (hide_unresolved
)
1032 if (al
->map
== NULL
)
1036 if (al
->map
->groups
== &al
->machine
->kmaps
) {
1037 if (machine__is_host(al
->machine
)) {
1038 al
->cpumode
= PERF_RECORD_MISC_KERNEL
;
1041 al
->cpumode
= PERF_RECORD_MISC_GUEST_KERNEL
;
1045 if (machine__is_host(al
->machine
)) {
1046 al
->cpumode
= PERF_RECORD_MISC_USER
;
1048 } else if (perf_guest
) {
1049 al
->cpumode
= PERF_RECORD_MISC_GUEST_USER
;
1052 al
->cpumode
= PERF_RECORD_MISC_HYPERVISOR
;
1061 char *callchain_list__sym_name(struct callchain_list
*cl
,
1062 char *bf
, size_t bfsize
, bool show_dso
)
1064 bool show_addr
= callchain_param
.key
== CCKEY_ADDRESS
;
1065 bool show_srcline
= show_addr
|| callchain_param
.key
== CCKEY_SRCLINE
;
1069 if (show_srcline
&& cl
->ms
.map
&& !cl
->srcline
)
1070 cl
->srcline
= get_srcline(cl
->ms
.map
->dso
,
1071 map__rip_2objdump(cl
->ms
.map
,
1073 cl
->ms
.sym
, false, show_addr
);
1075 printed
= scnprintf(bf
, bfsize
, "%s %s",
1076 cl
->ms
.sym
->name
, cl
->srcline
);
1078 printed
= scnprintf(bf
, bfsize
, "%s", cl
->ms
.sym
->name
);
1080 printed
= scnprintf(bf
, bfsize
, "%#" PRIx64
, cl
->ip
);
1083 scnprintf(bf
+ printed
, bfsize
- printed
, " %s",
1085 cl
->ms
.map
->dso
->short_name
:
1091 char *callchain_node__scnprintf_value(struct callchain_node
*node
,
1092 char *bf
, size_t bfsize
, u64 total
)
1094 double percent
= 0.0;
1095 u64 period
= callchain_cumul_hits(node
);
1096 unsigned count
= callchain_cumul_counts(node
);
1098 if (callchain_param
.mode
== CHAIN_FOLDED
) {
1100 count
= node
->count
;
1103 switch (callchain_param
.value
) {
1105 scnprintf(bf
, bfsize
, "%"PRIu64
, period
);
1108 scnprintf(bf
, bfsize
, "%u", count
);
1113 percent
= period
* 100.0 / total
;
1114 scnprintf(bf
, bfsize
, "%.2f%%", percent
);
1120 int callchain_node__fprintf_value(struct callchain_node
*node
,
1121 FILE *fp
, u64 total
)
1123 double percent
= 0.0;
1124 u64 period
= callchain_cumul_hits(node
);
1125 unsigned count
= callchain_cumul_counts(node
);
1127 if (callchain_param
.mode
== CHAIN_FOLDED
) {
1129 count
= node
->count
;
1132 switch (callchain_param
.value
) {
1134 return fprintf(fp
, "%"PRIu64
, period
);
1136 return fprintf(fp
, "%u", count
);
1140 percent
= period
* 100.0 / total
;
1141 return percent_color_fprintf(fp
, "%.2f%%", percent
);
1146 static void callchain_counts_value(struct callchain_node
*node
,
1147 u64
*branch_count
, u64
*predicted_count
,
1148 u64
*abort_count
, u64
*cycles_count
)
1150 struct callchain_list
*clist
;
1152 list_for_each_entry(clist
, &node
->val
, list
) {
1154 *branch_count
+= clist
->branch_count
;
1156 if (predicted_count
)
1157 *predicted_count
+= clist
->predicted_count
;
1160 *abort_count
+= clist
->abort_count
;
1163 *cycles_count
+= clist
->cycles_count
;
1167 static int callchain_node_branch_counts_cumul(struct callchain_node
*node
,
1169 u64
*predicted_count
,
1173 struct callchain_node
*child
;
1176 n
= rb_first(&node
->rb_root_in
);
1178 child
= rb_entry(n
, struct callchain_node
, rb_node_in
);
1181 callchain_node_branch_counts_cumul(child
, branch_count
,
1186 callchain_counts_value(child
, branch_count
,
1187 predicted_count
, abort_count
,
1194 int callchain_branch_counts(struct callchain_root
*root
,
1195 u64
*branch_count
, u64
*predicted_count
,
1196 u64
*abort_count
, u64
*cycles_count
)
1201 if (predicted_count
)
1202 *predicted_count
= 0;
1210 return callchain_node_branch_counts_cumul(&root
->node
,
1217 static int counts_str_build(char *bf
, int bfsize
,
1218 u64 branch_count
, u64 predicted_count
,
1219 u64 abort_count
, u64 cycles_count
,
1220 u64 iter_count
, u64 samples_count
)
1222 double predicted_percent
= 0.0;
1223 const char *null_str
= "";
1229 if (branch_count
== 0)
1230 return scnprintf(bf
, bfsize
, " (calltrace)");
1232 cycles
= cycles_count
/ branch_count
;
1234 if (iter_count
&& samples_count
) {
1236 scnprintf(iter_str
, sizeof(iter_str
),
1237 " iterations:%" PRId64
"",
1238 iter_count
/ samples_count
);
1240 scnprintf(iter_str
, sizeof(iter_str
),
1241 "iterations:%" PRId64
"",
1242 iter_count
/ samples_count
);
1245 istr
= (char *)null_str
;
1248 scnprintf(cycle_str
, sizeof(cycle_str
),
1249 "cycles:%" PRId64
"", cycles
);
1252 cstr
= (char *)null_str
;
1254 predicted_percent
= predicted_count
* 100.0 / branch_count
;
1256 if ((predicted_count
== branch_count
) && (abort_count
== 0)) {
1257 if ((cycles
> 0) || (istr
!= (char *)null_str
))
1258 return scnprintf(bf
, bfsize
, " (%s%s)", cstr
, istr
);
1260 return scnprintf(bf
, bfsize
, "%s", (char *)null_str
);
1263 if ((predicted_count
< branch_count
) && (abort_count
== 0)) {
1264 if ((cycles
> 0) || (istr
!= (char *)null_str
))
1265 return scnprintf(bf
, bfsize
,
1266 " (predicted:%.1f%% %s%s)",
1267 predicted_percent
, cstr
, istr
);
1269 return scnprintf(bf
, bfsize
,
1270 " (predicted:%.1f%%)",
1275 if ((predicted_count
== branch_count
) && (abort_count
> 0)) {
1276 if ((cycles
> 0) || (istr
!= (char *)null_str
))
1277 return scnprintf(bf
, bfsize
,
1278 " (abort:%" PRId64
" %s%s)",
1279 abort_count
, cstr
, istr
);
1281 return scnprintf(bf
, bfsize
,
1282 " (abort:%" PRId64
")",
1286 if ((cycles
> 0) || (istr
!= (char *)null_str
))
1287 return scnprintf(bf
, bfsize
,
1288 " (predicted:%.1f%% abort:%" PRId64
" %s%s)",
1289 predicted_percent
, abort_count
, cstr
, istr
);
1291 return scnprintf(bf
, bfsize
,
1292 " (predicted:%.1f%% abort:%" PRId64
")",
1293 predicted_percent
, abort_count
);
1296 static int callchain_counts_printf(FILE *fp
, char *bf
, int bfsize
,
1297 u64 branch_count
, u64 predicted_count
,
1298 u64 abort_count
, u64 cycles_count
,
1299 u64 iter_count
, u64 samples_count
)
1303 counts_str_build(str
, sizeof(str
), branch_count
,
1304 predicted_count
, abort_count
, cycles_count
,
1305 iter_count
, samples_count
);
1308 return fprintf(fp
, "%s", str
);
1310 return scnprintf(bf
, bfsize
, "%s", str
);
1313 int callchain_list_counts__printf_value(struct callchain_node
*node
,
1314 struct callchain_list
*clist
,
1315 FILE *fp
, char *bf
, int bfsize
)
1317 u64 branch_count
, predicted_count
;
1318 u64 abort_count
, cycles_count
;
1319 u64 iter_count
= 0, samples_count
= 0;
1321 branch_count
= clist
->branch_count
;
1322 predicted_count
= clist
->predicted_count
;
1323 abort_count
= clist
->abort_count
;
1324 cycles_count
= clist
->cycles_count
;
1327 struct callchain_list
*call
;
1329 list_for_each_entry(call
, &node
->val
, list
) {
1330 iter_count
+= call
->iter_count
;
1331 samples_count
+= call
->samples_count
;
1335 return callchain_counts_printf(fp
, bf
, bfsize
, branch_count
,
1336 predicted_count
, abort_count
,
1337 cycles_count
, iter_count
, samples_count
);
1340 static void free_callchain_node(struct callchain_node
*node
)
1342 struct callchain_list
*list
, *tmp
;
1343 struct callchain_node
*child
;
1346 list_for_each_entry_safe(list
, tmp
, &node
->parent_val
, list
) {
1347 list_del(&list
->list
);
1348 map__zput(list
->ms
.map
);
1352 list_for_each_entry_safe(list
, tmp
, &node
->val
, list
) {
1353 list_del(&list
->list
);
1354 map__zput(list
->ms
.map
);
1358 n
= rb_first(&node
->rb_root_in
);
1360 child
= container_of(n
, struct callchain_node
, rb_node_in
);
1362 rb_erase(&child
->rb_node_in
, &node
->rb_root_in
);
1364 free_callchain_node(child
);
1369 void free_callchain(struct callchain_root
*root
)
1371 if (!symbol_conf
.use_callchain
)
1374 free_callchain_node(&root
->node
);
1377 static u64
decay_callchain_node(struct callchain_node
*node
)
1379 struct callchain_node
*child
;
1383 n
= rb_first(&node
->rb_root_in
);
1385 child
= container_of(n
, struct callchain_node
, rb_node_in
);
1387 child_hits
+= decay_callchain_node(child
);
1391 node
->hit
= (node
->hit
* 7) / 8;
1392 node
->children_hit
= child_hits
;
1397 void decay_callchain(struct callchain_root
*root
)
1399 if (!symbol_conf
.use_callchain
)
1402 decay_callchain_node(&root
->node
);
1405 int callchain_node__make_parent_list(struct callchain_node
*node
)
1407 struct callchain_node
*parent
= node
->parent
;
1408 struct callchain_list
*chain
, *new;
1412 list_for_each_entry_reverse(chain
, &parent
->val
, list
) {
1413 new = malloc(sizeof(*new));
1417 new->has_children
= false;
1418 map__get(new->ms
.map
);
1419 list_add_tail(&new->list
, &head
);
1421 parent
= parent
->parent
;
1424 list_for_each_entry_safe_reverse(chain
, new, &head
, list
)
1425 list_move_tail(&chain
->list
, &node
->parent_val
);
1427 if (!list_empty(&node
->parent_val
)) {
1428 chain
= list_first_entry(&node
->parent_val
, struct callchain_list
, list
);
1429 chain
->has_children
= rb_prev(&node
->rb_node
) || rb_next(&node
->rb_node
);
1431 chain
= list_first_entry(&node
->val
, struct callchain_list
, list
);
1432 chain
->has_children
= false;
1437 list_for_each_entry_safe(chain
, new, &head
, list
) {
1438 list_del(&chain
->list
);
1439 map__zput(chain
->ms
.map
);
1445 int callchain_cursor__copy(struct callchain_cursor
*dst
,
1446 struct callchain_cursor
*src
)
1450 callchain_cursor_reset(dst
);
1451 callchain_cursor_commit(src
);
1454 struct callchain_cursor_node
*node
;
1456 node
= callchain_cursor_current(src
);
1460 rc
= callchain_cursor_append(dst
, node
->ip
, node
->map
, node
->sym
,
1461 node
->branch
, &node
->branch_flags
,
1462 node
->nr_loop_iter
, node
->samples
);
1466 callchain_cursor_advance(src
);