1 /* 2 * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com> 3 * 4 * Handle the callchains from the stream in an ad-hoc radix tree and then 5 * sort them in an rbtree. 6 * 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. 9 * 10 */ 11 12 #include <stdlib.h> 13 #include <stdio.h> 14 #include <stdbool.h> 15 #include <errno.h> 16 #include <math.h> 17 18 #include "asm/bug.h" 19 20 #include "hist.h" 21 #include "util.h" 22 #include "sort.h" 23 #include "machine.h" 24 #include "callchain.h" 25 26 __thread struct callchain_cursor callchain_cursor; 27 28 int parse_callchain_record_opt(const char *arg, struct callchain_param *param) 29 { 30 return parse_callchain_record(arg, param); 31 } 32 33 static int parse_callchain_mode(const char *value) 34 { 35 if (!strncmp(value, "graph", strlen(value))) { 36 callchain_param.mode = CHAIN_GRAPH_ABS; 37 return 0; 38 } 39 if (!strncmp(value, "flat", strlen(value))) { 40 callchain_param.mode = CHAIN_FLAT; 41 return 0; 42 } 43 if (!strncmp(value, "fractal", strlen(value))) { 44 callchain_param.mode = CHAIN_GRAPH_REL; 45 return 0; 46 } 47 if (!strncmp(value, "folded", strlen(value))) { 48 callchain_param.mode = CHAIN_FOLDED; 49 return 0; 50 } 51 return -1; 52 } 53 54 static int parse_callchain_order(const char *value) 55 { 56 if (!strncmp(value, "caller", strlen(value))) { 57 callchain_param.order = ORDER_CALLER; 58 callchain_param.order_set = true; 59 return 0; 60 } 61 if (!strncmp(value, "callee", strlen(value))) { 62 callchain_param.order = ORDER_CALLEE; 63 callchain_param.order_set = true; 64 return 0; 65 } 66 return -1; 67 } 68 69 static int parse_callchain_sort_key(const char *value) 70 { 71 if (!strncmp(value, "function", strlen(value))) { 72 callchain_param.key = CCKEY_FUNCTION; 73 return 0; 74 } 75 if (!strncmp(value, "address", strlen(value))) { 76 callchain_param.key = CCKEY_ADDRESS; 77 return 0; 78 } 79 if (!strncmp(value, "branch", strlen(value))) { 80 callchain_param.branch_callstack = 1; 81 return 0; 82 } 83 return -1; 84 } 85 86 static int parse_callchain_value(const char *value) 87 { 88 if (!strncmp(value, "percent", strlen(value))) { 89 callchain_param.value = CCVAL_PERCENT; 90 return 0; 91 } 92 if (!strncmp(value, "period", strlen(value))) { 93 callchain_param.value = CCVAL_PERIOD; 94 return 0; 95 } 96 if (!strncmp(value, "count", strlen(value))) { 97 callchain_param.value = CCVAL_COUNT; 98 return 0; 99 } 100 return -1; 101 } 102 103 static int 104 __parse_callchain_report_opt(const char *arg, bool allow_record_opt) 105 { 106 char *tok; 107 char *endptr; 108 bool minpcnt_set = false; 109 bool record_opt_set = false; 110 bool try_stack_size = false; 111 112 callchain_param.enabled = true; 113 symbol_conf.use_callchain = true; 114 115 if (!arg) 116 return 0; 117 118 while ((tok = strtok((char *)arg, ",")) != NULL) { 119 if (!strncmp(tok, "none", strlen(tok))) { 120 callchain_param.mode = CHAIN_NONE; 121 callchain_param.enabled = false; 122 symbol_conf.use_callchain = false; 123 return 0; 124 } 125 126 if (!parse_callchain_mode(tok) || 127 !parse_callchain_order(tok) || 128 !parse_callchain_sort_key(tok) || 129 !parse_callchain_value(tok)) { 130 /* parsing ok - move on to the next */ 131 try_stack_size = false; 132 goto next; 133 } else if (allow_record_opt && !record_opt_set) { 134 if (parse_callchain_record(tok, &callchain_param)) 135 goto try_numbers; 136 137 /* assume that number followed by 'dwarf' is stack size */ 138 if (callchain_param.record_mode == CALLCHAIN_DWARF) 139 try_stack_size = true; 140 141 record_opt_set = true; 142 goto next; 143 } 144 145 try_numbers: 146 if (try_stack_size) { 147 unsigned long size = 0; 148 149 if (get_stack_size(tok, &size) < 0) 150 return -1; 151 callchain_param.dump_size = size; 152 try_stack_size = false; 153 } else if (!minpcnt_set) { 154 /* try to get the min percent */ 155 callchain_param.min_percent = strtod(tok, &endptr); 156 if (tok == endptr) 157 return -1; 158 minpcnt_set = true; 159 } else { 160 /* try print limit at last */ 161 callchain_param.print_limit = strtoul(tok, &endptr, 0); 162 if (tok == endptr) 163 return -1; 164 } 165 next: 166 arg = NULL; 167 } 168 169 if (callchain_register_param(&callchain_param) < 0) { 170 pr_err("Can't register callchain params\n"); 171 return -1; 172 } 173 return 0; 174 } 175 176 int parse_callchain_report_opt(const char *arg) 177 { 178 return __parse_callchain_report_opt(arg, false); 179 } 180 181 int parse_callchain_top_opt(const char *arg) 182 { 183 return __parse_callchain_report_opt(arg, true); 184 } 185 186 int perf_callchain_config(const char *var, const char *value) 187 { 188 char *endptr; 189 190 if (prefixcmp(var, "call-graph.")) 191 return 0; 192 var += sizeof("call-graph.") - 1; 193 194 if (!strcmp(var, "record-mode")) 195 return parse_callchain_record_opt(value, &callchain_param); 196 if (!strcmp(var, "dump-size")) { 197 unsigned long size = 0; 198 int ret; 199 200 ret = get_stack_size(value, &size); 201 callchain_param.dump_size = size; 202 203 return ret; 204 } 205 if (!strcmp(var, "print-type")) 206 return parse_callchain_mode(value); 207 if (!strcmp(var, "order")) 208 return parse_callchain_order(value); 209 if (!strcmp(var, "sort-key")) 210 return parse_callchain_sort_key(value); 211 if (!strcmp(var, "threshold")) { 212 callchain_param.min_percent = strtod(value, &endptr); 213 if (value == endptr) 214 return -1; 215 } 216 if (!strcmp(var, "print-limit")) { 217 callchain_param.print_limit = strtod(value, &endptr); 218 if (value == endptr) 219 return -1; 220 } 221 222 return 0; 223 } 224 225 static void 226 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 227 enum chain_mode mode) 228 { 229 struct rb_node **p = &root->rb_node; 230 struct rb_node *parent = NULL; 231 struct callchain_node *rnode; 232 u64 chain_cumul = callchain_cumul_hits(chain); 233 234 while (*p) { 235 u64 rnode_cumul; 236 237 parent = *p; 238 rnode = rb_entry(parent, struct callchain_node, rb_node); 239 rnode_cumul = callchain_cumul_hits(rnode); 240 241 switch (mode) { 242 case CHAIN_FLAT: 243 case CHAIN_FOLDED: 244 if (rnode->hit < chain->hit) 245 p = &(*p)->rb_left; 246 else 247 p = &(*p)->rb_right; 248 break; 249 case CHAIN_GRAPH_ABS: /* Falldown */ 250 case CHAIN_GRAPH_REL: 251 if (rnode_cumul < chain_cumul) 252 p = &(*p)->rb_left; 253 else 254 p = &(*p)->rb_right; 255 break; 256 case CHAIN_NONE: 257 default: 258 break; 259 } 260 } 261 262 rb_link_node(&chain->rb_node, parent, p); 263 rb_insert_color(&chain->rb_node, root); 264 } 265 266 static void 267 __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, 268 u64 min_hit) 269 { 270 struct rb_node *n; 271 struct callchain_node *child; 272 273 n = rb_first(&node->rb_root_in); 274 while (n) { 275 child = rb_entry(n, struct callchain_node, rb_node_in); 276 n = rb_next(n); 277 278 __sort_chain_flat(rb_root, child, min_hit); 279 } 280 281 if (node->hit && node->hit >= min_hit) 282 rb_insert_callchain(rb_root, node, CHAIN_FLAT); 283 } 284 285 /* 286 * Once we get every callchains from the stream, we can now 287 * sort them by hit 288 */ 289 static void 290 sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, 291 u64 min_hit, struct callchain_param *param __maybe_unused) 292 { 293 *rb_root = RB_ROOT; 294 __sort_chain_flat(rb_root, &root->node, min_hit); 295 } 296 297 static void __sort_chain_graph_abs(struct callchain_node *node, 298 u64 min_hit) 299 { 300 struct rb_node *n; 301 struct callchain_node *child; 302 303 node->rb_root = RB_ROOT; 304 n = rb_first(&node->rb_root_in); 305 306 while (n) { 307 child = rb_entry(n, struct callchain_node, rb_node_in); 308 n = rb_next(n); 309 310 __sort_chain_graph_abs(child, min_hit); 311 if (callchain_cumul_hits(child) >= min_hit) 312 rb_insert_callchain(&node->rb_root, child, 313 CHAIN_GRAPH_ABS); 314 } 315 } 316 317 static void 318 sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root, 319 u64 min_hit, struct callchain_param *param __maybe_unused) 320 { 321 __sort_chain_graph_abs(&chain_root->node, min_hit); 322 rb_root->rb_node = chain_root->node.rb_root.rb_node; 323 } 324 325 static void __sort_chain_graph_rel(struct callchain_node *node, 326 double min_percent) 327 { 328 struct rb_node *n; 329 struct callchain_node *child; 330 u64 min_hit; 331 332 node->rb_root = RB_ROOT; 333 min_hit = ceil(node->children_hit * min_percent); 334 335 n = rb_first(&node->rb_root_in); 336 while (n) { 337 child = rb_entry(n, struct callchain_node, rb_node_in); 338 n = rb_next(n); 339 340 __sort_chain_graph_rel(child, min_percent); 341 if (callchain_cumul_hits(child) >= min_hit) 342 rb_insert_callchain(&node->rb_root, child, 343 CHAIN_GRAPH_REL); 344 } 345 } 346 347 static void 348 sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root, 349 u64 min_hit __maybe_unused, struct callchain_param *param) 350 { 351 __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0); 352 rb_root->rb_node = chain_root->node.rb_root.rb_node; 353 } 354 355 int callchain_register_param(struct callchain_param *param) 356 { 357 switch (param->mode) { 358 case CHAIN_GRAPH_ABS: 359 param->sort = sort_chain_graph_abs; 360 break; 361 case CHAIN_GRAPH_REL: 362 param->sort = sort_chain_graph_rel; 363 break; 364 case CHAIN_FLAT: 365 case CHAIN_FOLDED: 366 param->sort = sort_chain_flat; 367 break; 368 case CHAIN_NONE: 369 default: 370 return -1; 371 } 372 return 0; 373 } 374 375 /* 376 * Create a child for a parent. If inherit_children, then the new child 377 * will become the new parent of it's parent children 378 */ 379 static struct callchain_node * 380 create_child(struct callchain_node *parent, bool inherit_children) 381 { 382 struct callchain_node *new; 383 384 new = zalloc(sizeof(*new)); 385 if (!new) { 386 perror("not enough memory to create child for code path tree"); 387 return NULL; 388 } 389 new->parent = parent; 390 INIT_LIST_HEAD(&new->val); 391 INIT_LIST_HEAD(&new->parent_val); 392 393 if (inherit_children) { 394 struct rb_node *n; 395 struct callchain_node *child; 396 397 new->rb_root_in = parent->rb_root_in; 398 parent->rb_root_in = RB_ROOT; 399 400 n = rb_first(&new->rb_root_in); 401 while (n) { 402 child = rb_entry(n, struct callchain_node, rb_node_in); 403 child->parent = new; 404 n = rb_next(n); 405 } 406 407 /* make it the first child */ 408 rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node); 409 rb_insert_color(&new->rb_node_in, &parent->rb_root_in); 410 } 411 412 return new; 413 } 414 415 416 /* 417 * Fill the node with callchain values 418 */ 419 static int 420 fill_node(struct callchain_node *node, struct callchain_cursor *cursor) 421 { 422 struct callchain_cursor_node *cursor_node; 423 424 node->val_nr = cursor->nr - cursor->pos; 425 if (!node->val_nr) 426 pr_warning("Warning: empty node in callchain tree\n"); 427 428 cursor_node = callchain_cursor_current(cursor); 429 430 while (cursor_node) { 431 struct callchain_list *call; 432 433 call = zalloc(sizeof(*call)); 434 if (!call) { 435 perror("not enough memory for the code path tree"); 436 return -1; 437 } 438 call->ip = cursor_node->ip; 439 call->ms.sym = cursor_node->sym; 440 call->ms.map = cursor_node->map; 441 442 if (cursor_node->branch) { 443 call->branch_count = 1; 444 445 if (cursor_node->branch_flags.predicted) 446 call->predicted_count = 1; 447 448 if (cursor_node->branch_flags.abort) 449 call->abort_count = 1; 450 451 call->cycles_count = cursor_node->branch_flags.cycles; 452 call->iter_count = cursor_node->nr_loop_iter; 453 call->samples_count = cursor_node->samples; 454 } 455 456 list_add_tail(&call->list, &node->val); 457 458 callchain_cursor_advance(cursor); 459 cursor_node = callchain_cursor_current(cursor); 460 } 461 return 0; 462 } 463 464 static struct callchain_node * 465 add_child(struct callchain_node *parent, 466 struct callchain_cursor *cursor, 467 u64 period) 468 { 469 struct callchain_node *new; 470 471 new = create_child(parent, false); 472 if (new == NULL) 473 return NULL; 474 475 if (fill_node(new, cursor) < 0) { 476 struct callchain_list *call, *tmp; 477 478 list_for_each_entry_safe(call, tmp, &new->val, list) { 479 list_del(&call->list); 480 free(call); 481 } 482 free(new); 483 return NULL; 484 } 485 486 new->children_hit = 0; 487 new->hit = period; 488 new->children_count = 0; 489 new->count = 1; 490 return new; 491 } 492 493 enum match_result { 494 MATCH_ERROR = -1, 495 MATCH_EQ, 496 MATCH_LT, 497 MATCH_GT, 498 }; 499 500 static enum match_result match_chain(struct callchain_cursor_node *node, 501 struct callchain_list *cnode) 502 { 503 struct symbol *sym = node->sym; 504 u64 left, right; 505 506 if (cnode->ms.sym && sym && 507 callchain_param.key == CCKEY_FUNCTION) { 508 left = cnode->ms.sym->start; 509 right = sym->start; 510 } else { 511 left = cnode->ip; 512 right = node->ip; 513 } 514 515 if (left == right) { 516 if (node->branch) { 517 cnode->branch_count++; 518 519 if (node->branch_flags.predicted) 520 cnode->predicted_count++; 521 522 if (node->branch_flags.abort) 523 cnode->abort_count++; 524 525 cnode->cycles_count += node->branch_flags.cycles; 526 cnode->iter_count += node->nr_loop_iter; 527 cnode->samples_count += node->samples; 528 } 529 530 return MATCH_EQ; 531 } 532 533 return left > right ? MATCH_GT : MATCH_LT; 534 } 535 536 /* 537 * Split the parent in two parts (a new child is created) and 538 * give a part of its callchain to the created child. 539 * Then create another child to host the given callchain of new branch 540 */ 541 static int 542 split_add_child(struct callchain_node *parent, 543 struct callchain_cursor *cursor, 544 struct callchain_list *to_split, 545 u64 idx_parents, u64 idx_local, u64 period) 546 { 547 struct callchain_node *new; 548 struct list_head *old_tail; 549 unsigned int idx_total = idx_parents + idx_local; 550 551 /* split */ 552 new = create_child(parent, true); 553 if (new == NULL) 554 return -1; 555 556 /* split the callchain and move a part to the new child */ 557 old_tail = parent->val.prev; 558 list_del_range(&to_split->list, old_tail); 559 new->val.next = &to_split->list; 560 new->val.prev = old_tail; 561 to_split->list.prev = &new->val; 562 old_tail->next = &new->val; 563 564 /* split the hits */ 565 new->hit = parent->hit; 566 new->children_hit = parent->children_hit; 567 parent->children_hit = callchain_cumul_hits(new); 568 new->val_nr = parent->val_nr - idx_local; 569 parent->val_nr = idx_local; 570 new->count = parent->count; 571 new->children_count = parent->children_count; 572 parent->children_count = callchain_cumul_counts(new); 573 574 /* create a new child for the new branch if any */ 575 if (idx_total < cursor->nr) { 576 struct callchain_node *first; 577 struct callchain_list *cnode; 578 struct callchain_cursor_node *node; 579 struct rb_node *p, **pp; 580 581 parent->hit = 0; 582 parent->children_hit += period; 583 parent->count = 0; 584 parent->children_count += 1; 585 586 node = callchain_cursor_current(cursor); 587 new = add_child(parent, cursor, period); 588 if (new == NULL) 589 return -1; 590 591 /* 592 * This is second child since we moved parent's children 593 * to new (first) child above. 594 */ 595 p = parent->rb_root_in.rb_node; 596 first = rb_entry(p, struct callchain_node, rb_node_in); 597 cnode = list_first_entry(&first->val, struct callchain_list, 598 list); 599 600 if (match_chain(node, cnode) == MATCH_LT) 601 pp = &p->rb_left; 602 else 603 pp = &p->rb_right; 604 605 rb_link_node(&new->rb_node_in, p, pp); 606 rb_insert_color(&new->rb_node_in, &parent->rb_root_in); 607 } else { 608 parent->hit = period; 609 parent->count = 1; 610 } 611 return 0; 612 } 613 614 static enum match_result 615 append_chain(struct callchain_node *root, 616 struct callchain_cursor *cursor, 617 u64 period); 618 619 static int 620 append_chain_children(struct callchain_node *root, 621 struct callchain_cursor *cursor, 622 u64 period) 623 { 624 struct callchain_node *rnode; 625 struct callchain_cursor_node *node; 626 struct rb_node **p = &root->rb_root_in.rb_node; 627 struct rb_node *parent = NULL; 628 629 node = callchain_cursor_current(cursor); 630 if (!node) 631 return -1; 632 633 /* lookup in childrens */ 634 while (*p) { 635 enum match_result ret; 636 637 parent = *p; 638 rnode = rb_entry(parent, struct callchain_node, rb_node_in); 639 640 /* If at least first entry matches, rely to children */ 641 ret = append_chain(rnode, cursor, period); 642 if (ret == MATCH_EQ) 643 goto inc_children_hit; 644 if (ret == MATCH_ERROR) 645 return -1; 646 647 if (ret == MATCH_LT) 648 p = &parent->rb_left; 649 else 650 p = &parent->rb_right; 651 } 652 /* nothing in children, add to the current node */ 653 rnode = add_child(root, cursor, period); 654 if (rnode == NULL) 655 return -1; 656 657 rb_link_node(&rnode->rb_node_in, parent, p); 658 rb_insert_color(&rnode->rb_node_in, &root->rb_root_in); 659 660 inc_children_hit: 661 root->children_hit += period; 662 root->children_count++; 663 return 0; 664 } 665 666 static enum match_result 667 append_chain(struct callchain_node *root, 668 struct callchain_cursor *cursor, 669 u64 period) 670 { 671 struct callchain_list *cnode; 672 u64 start = cursor->pos; 673 bool found = false; 674 u64 matches; 675 enum match_result cmp = MATCH_ERROR; 676 677 /* 678 * Lookup in the current node 679 * If we have a symbol, then compare the start to match 680 * anywhere inside a function, unless function 681 * mode is disabled. 682 */ 683 list_for_each_entry(cnode, &root->val, list) { 684 struct callchain_cursor_node *node; 685 686 node = callchain_cursor_current(cursor); 687 if (!node) 688 break; 689 690 cmp = match_chain(node, cnode); 691 if (cmp != MATCH_EQ) 692 break; 693 694 found = true; 695 696 callchain_cursor_advance(cursor); 697 } 698 699 /* matches not, relay no the parent */ 700 if (!found) { 701 WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n"); 702 return cmp; 703 } 704 705 matches = cursor->pos - start; 706 707 /* we match only a part of the node. Split it and add the new chain */ 708 if (matches < root->val_nr) { 709 if (split_add_child(root, cursor, cnode, start, matches, 710 period) < 0) 711 return MATCH_ERROR; 712 713 return MATCH_EQ; 714 } 715 716 /* we match 100% of the path, increment the hit */ 717 if (matches == root->val_nr && cursor->pos == cursor->nr) { 718 root->hit += period; 719 root->count++; 720 return MATCH_EQ; 721 } 722 723 /* We match the node and still have a part remaining */ 724 if (append_chain_children(root, cursor, period) < 0) 725 return MATCH_ERROR; 726 727 return MATCH_EQ; 728 } 729 730 int callchain_append(struct callchain_root *root, 731 struct callchain_cursor *cursor, 732 u64 period) 733 { 734 if (!cursor->nr) 735 return 0; 736 737 callchain_cursor_commit(cursor); 738 739 if (append_chain_children(&root->node, cursor, period) < 0) 740 return -1; 741 742 if (cursor->nr > root->max_depth) 743 root->max_depth = cursor->nr; 744 745 return 0; 746 } 747 748 static int 749 merge_chain_branch(struct callchain_cursor *cursor, 750 struct callchain_node *dst, struct callchain_node *src) 751 { 752 struct callchain_cursor_node **old_last = cursor->last; 753 struct callchain_node *child; 754 struct callchain_list *list, *next_list; 755 struct rb_node *n; 756 int old_pos = cursor->nr; 757 int err = 0; 758 759 list_for_each_entry_safe(list, next_list, &src->val, list) { 760 callchain_cursor_append(cursor, list->ip, 761 list->ms.map, list->ms.sym, 762 false, NULL, 0, 0); 763 list_del(&list->list); 764 free(list); 765 } 766 767 if (src->hit) { 768 callchain_cursor_commit(cursor); 769 if (append_chain_children(dst, cursor, src->hit) < 0) 770 return -1; 771 } 772 773 n = rb_first(&src->rb_root_in); 774 while (n) { 775 child = container_of(n, struct callchain_node, rb_node_in); 776 n = rb_next(n); 777 rb_erase(&child->rb_node_in, &src->rb_root_in); 778 779 err = merge_chain_branch(cursor, dst, child); 780 if (err) 781 break; 782 783 free(child); 784 } 785 786 cursor->nr = old_pos; 787 cursor->last = old_last; 788 789 return err; 790 } 791 792 int callchain_merge(struct callchain_cursor *cursor, 793 struct callchain_root *dst, struct callchain_root *src) 794 { 795 return merge_chain_branch(cursor, &dst->node, &src->node); 796 } 797 798 int callchain_cursor_append(struct callchain_cursor *cursor, 799 u64 ip, struct map *map, struct symbol *sym, 800 bool branch, struct branch_flags *flags, 801 int nr_loop_iter, int samples) 802 { 803 struct callchain_cursor_node *node = *cursor->last; 804 805 if (!node) { 806 node = calloc(1, sizeof(*node)); 807 if (!node) 808 return -ENOMEM; 809 810 *cursor->last = node; 811 } 812 813 node->ip = ip; 814 node->map = map; 815 node->sym = sym; 816 node->branch = branch; 817 node->nr_loop_iter = nr_loop_iter; 818 node->samples = samples; 819 820 if (flags) 821 memcpy(&node->branch_flags, flags, 822 sizeof(struct branch_flags)); 823 824 cursor->nr++; 825 826 cursor->last = &node->next; 827 828 return 0; 829 } 830 831 int sample__resolve_callchain(struct perf_sample *sample, 832 struct callchain_cursor *cursor, struct symbol **parent, 833 struct perf_evsel *evsel, struct addr_location *al, 834 int max_stack) 835 { 836 if (sample->callchain == NULL) 837 return 0; 838 839 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 840 perf_hpp_list.parent) { 841 return thread__resolve_callchain(al->thread, cursor, evsel, sample, 842 parent, al, max_stack); 843 } 844 return 0; 845 } 846 847 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 848 { 849 if (!symbol_conf.use_callchain || sample->callchain == NULL) 850 return 0; 851 return callchain_append(he->callchain, &callchain_cursor, sample->period); 852 } 853 854 int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node, 855 bool hide_unresolved) 856 { 857 al->map = node->map; 858 al->sym = node->sym; 859 if (node->map) 860 al->addr = node->map->map_ip(node->map, node->ip); 861 else 862 al->addr = node->ip; 863 864 if (al->sym == NULL) { 865 if (hide_unresolved) 866 return 0; 867 if (al->map == NULL) 868 goto out; 869 } 870 871 if (al->map->groups == &al->machine->kmaps) { 872 if (machine__is_host(al->machine)) { 873 al->cpumode = PERF_RECORD_MISC_KERNEL; 874 al->level = 'k'; 875 } else { 876 al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL; 877 al->level = 'g'; 878 } 879 } else { 880 if (machine__is_host(al->machine)) { 881 al->cpumode = PERF_RECORD_MISC_USER; 882 al->level = '.'; 883 } else if (perf_guest) { 884 al->cpumode = PERF_RECORD_MISC_GUEST_USER; 885 al->level = 'u'; 886 } else { 887 al->cpumode = PERF_RECORD_MISC_HYPERVISOR; 888 al->level = 'H'; 889 } 890 } 891 892 out: 893 return 1; 894 } 895 896 char *callchain_list__sym_name(struct callchain_list *cl, 897 char *bf, size_t bfsize, bool show_dso) 898 { 899 int printed; 900 901 if (cl->ms.sym) { 902 if (callchain_param.key == CCKEY_ADDRESS && 903 cl->ms.map && !cl->srcline) 904 cl->srcline = get_srcline(cl->ms.map->dso, 905 map__rip_2objdump(cl->ms.map, 906 cl->ip), 907 cl->ms.sym, false); 908 if (cl->srcline) 909 printed = scnprintf(bf, bfsize, "%s %s", 910 cl->ms.sym->name, cl->srcline); 911 else 912 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); 913 } else 914 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); 915 916 if (show_dso) 917 scnprintf(bf + printed, bfsize - printed, " %s", 918 cl->ms.map ? 919 cl->ms.map->dso->short_name : 920 "unknown"); 921 922 return bf; 923 } 924 925 char *callchain_node__scnprintf_value(struct callchain_node *node, 926 char *bf, size_t bfsize, u64 total) 927 { 928 double percent = 0.0; 929 u64 period = callchain_cumul_hits(node); 930 unsigned count = callchain_cumul_counts(node); 931 932 if (callchain_param.mode == CHAIN_FOLDED) { 933 period = node->hit; 934 count = node->count; 935 } 936 937 switch (callchain_param.value) { 938 case CCVAL_PERIOD: 939 scnprintf(bf, bfsize, "%"PRIu64, period); 940 break; 941 case CCVAL_COUNT: 942 scnprintf(bf, bfsize, "%u", count); 943 break; 944 case CCVAL_PERCENT: 945 default: 946 if (total) 947 percent = period * 100.0 / total; 948 scnprintf(bf, bfsize, "%.2f%%", percent); 949 break; 950 } 951 return bf; 952 } 953 954 int callchain_node__fprintf_value(struct callchain_node *node, 955 FILE *fp, u64 total) 956 { 957 double percent = 0.0; 958 u64 period = callchain_cumul_hits(node); 959 unsigned count = callchain_cumul_counts(node); 960 961 if (callchain_param.mode == CHAIN_FOLDED) { 962 period = node->hit; 963 count = node->count; 964 } 965 966 switch (callchain_param.value) { 967 case CCVAL_PERIOD: 968 return fprintf(fp, "%"PRIu64, period); 969 case CCVAL_COUNT: 970 return fprintf(fp, "%u", count); 971 case CCVAL_PERCENT: 972 default: 973 if (total) 974 percent = period * 100.0 / total; 975 return percent_color_fprintf(fp, "%.2f%%", percent); 976 } 977 return 0; 978 } 979 980 static void callchain_counts_value(struct callchain_node *node, 981 u64 *branch_count, u64 *predicted_count, 982 u64 *abort_count, u64 *cycles_count) 983 { 984 struct callchain_list *clist; 985 986 list_for_each_entry(clist, &node->val, list) { 987 if (branch_count) 988 *branch_count += clist->branch_count; 989 990 if (predicted_count) 991 *predicted_count += clist->predicted_count; 992 993 if (abort_count) 994 *abort_count += clist->abort_count; 995 996 if (cycles_count) 997 *cycles_count += clist->cycles_count; 998 } 999 } 1000 1001 static int callchain_node_branch_counts_cumul(struct callchain_node *node, 1002 u64 *branch_count, 1003 u64 *predicted_count, 1004 u64 *abort_count, 1005 u64 *cycles_count) 1006 { 1007 struct callchain_node *child; 1008 struct rb_node *n; 1009 1010 n = rb_first(&node->rb_root_in); 1011 while (n) { 1012 child = rb_entry(n, struct callchain_node, rb_node_in); 1013 n = rb_next(n); 1014 1015 callchain_node_branch_counts_cumul(child, branch_count, 1016 predicted_count, 1017 abort_count, 1018 cycles_count); 1019 1020 callchain_counts_value(child, branch_count, 1021 predicted_count, abort_count, 1022 cycles_count); 1023 } 1024 1025 return 0; 1026 } 1027 1028 int callchain_branch_counts(struct callchain_root *root, 1029 u64 *branch_count, u64 *predicted_count, 1030 u64 *abort_count, u64 *cycles_count) 1031 { 1032 if (branch_count) 1033 *branch_count = 0; 1034 1035 if (predicted_count) 1036 *predicted_count = 0; 1037 1038 if (abort_count) 1039 *abort_count = 0; 1040 1041 if (cycles_count) 1042 *cycles_count = 0; 1043 1044 return callchain_node_branch_counts_cumul(&root->node, 1045 branch_count, 1046 predicted_count, 1047 abort_count, 1048 cycles_count); 1049 } 1050 1051 static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, 1052 u64 branch_count, u64 predicted_count, 1053 u64 abort_count, u64 cycles_count, 1054 u64 iter_count, u64 samples_count) 1055 { 1056 double predicted_percent = 0.0; 1057 const char *null_str = ""; 1058 char iter_str[32]; 1059 char *str; 1060 u64 cycles = 0; 1061 1062 if (branch_count == 0) { 1063 if (fp) 1064 return fprintf(fp, " (calltrace)"); 1065 1066 return scnprintf(bf, bfsize, " (calltrace)"); 1067 } 1068 1069 if (iter_count && samples_count) { 1070 scnprintf(iter_str, sizeof(iter_str), 1071 ", iterations:%" PRId64 "", 1072 iter_count / samples_count); 1073 str = iter_str; 1074 } else 1075 str = (char *)null_str; 1076 1077 predicted_percent = predicted_count * 100.0 / branch_count; 1078 cycles = cycles_count / branch_count; 1079 1080 if ((predicted_percent >= 100.0) && (abort_count == 0)) { 1081 if (fp) 1082 return fprintf(fp, " (cycles:%" PRId64 "%s)", 1083 cycles, str); 1084 1085 return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)", 1086 cycles, str); 1087 } 1088 1089 if ((predicted_percent < 100.0) && (abort_count == 0)) { 1090 if (fp) 1091 return fprintf(fp, 1092 " (predicted:%.1f%%, cycles:%" PRId64 "%s)", 1093 predicted_percent, cycles, str); 1094 1095 return scnprintf(bf, bfsize, 1096 " (predicted:%.1f%%, cycles:%" PRId64 "%s)", 1097 predicted_percent, cycles, str); 1098 } 1099 1100 if (fp) 1101 return fprintf(fp, 1102 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)", 1103 predicted_percent, abort_count, cycles, str); 1104 1105 return scnprintf(bf, bfsize, 1106 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)", 1107 predicted_percent, abort_count, cycles, str); 1108 } 1109 1110 int callchain_list_counts__printf_value(struct callchain_node *node, 1111 struct callchain_list *clist, 1112 FILE *fp, char *bf, int bfsize) 1113 { 1114 u64 branch_count, predicted_count; 1115 u64 abort_count, cycles_count; 1116 u64 iter_count = 0, samples_count = 0; 1117 1118 branch_count = clist->branch_count; 1119 predicted_count = clist->predicted_count; 1120 abort_count = clist->abort_count; 1121 cycles_count = clist->cycles_count; 1122 1123 if (node) { 1124 struct callchain_list *call; 1125 1126 list_for_each_entry(call, &node->val, list) { 1127 iter_count += call->iter_count; 1128 samples_count += call->samples_count; 1129 } 1130 } 1131 1132 return callchain_counts_printf(fp, bf, bfsize, branch_count, 1133 predicted_count, abort_count, 1134 cycles_count, iter_count, samples_count); 1135 } 1136 1137 static void free_callchain_node(struct callchain_node *node) 1138 { 1139 struct callchain_list *list, *tmp; 1140 struct callchain_node *child; 1141 struct rb_node *n; 1142 1143 list_for_each_entry_safe(list, tmp, &node->parent_val, list) { 1144 list_del(&list->list); 1145 free(list); 1146 } 1147 1148 list_for_each_entry_safe(list, tmp, &node->val, list) { 1149 list_del(&list->list); 1150 free(list); 1151 } 1152 1153 n = rb_first(&node->rb_root_in); 1154 while (n) { 1155 child = container_of(n, struct callchain_node, rb_node_in); 1156 n = rb_next(n); 1157 rb_erase(&child->rb_node_in, &node->rb_root_in); 1158 1159 free_callchain_node(child); 1160 free(child); 1161 } 1162 } 1163 1164 void free_callchain(struct callchain_root *root) 1165 { 1166 if (!symbol_conf.use_callchain) 1167 return; 1168 1169 free_callchain_node(&root->node); 1170 } 1171 1172 static u64 decay_callchain_node(struct callchain_node *node) 1173 { 1174 struct callchain_node *child; 1175 struct rb_node *n; 1176 u64 child_hits = 0; 1177 1178 n = rb_first(&node->rb_root_in); 1179 while (n) { 1180 child = container_of(n, struct callchain_node, rb_node_in); 1181 1182 child_hits += decay_callchain_node(child); 1183 n = rb_next(n); 1184 } 1185 1186 node->hit = (node->hit * 7) / 8; 1187 node->children_hit = child_hits; 1188 1189 return node->hit; 1190 } 1191 1192 void decay_callchain(struct callchain_root *root) 1193 { 1194 if (!symbol_conf.use_callchain) 1195 return; 1196 1197 decay_callchain_node(&root->node); 1198 } 1199 1200 int callchain_node__make_parent_list(struct callchain_node *node) 1201 { 1202 struct callchain_node *parent = node->parent; 1203 struct callchain_list *chain, *new; 1204 LIST_HEAD(head); 1205 1206 while (parent) { 1207 list_for_each_entry_reverse(chain, &parent->val, list) { 1208 new = malloc(sizeof(*new)); 1209 if (new == NULL) 1210 goto out; 1211 *new = *chain; 1212 new->has_children = false; 1213 list_add_tail(&new->list, &head); 1214 } 1215 parent = parent->parent; 1216 } 1217 1218 list_for_each_entry_safe_reverse(chain, new, &head, list) 1219 list_move_tail(&chain->list, &node->parent_val); 1220 1221 if (!list_empty(&node->parent_val)) { 1222 chain = list_first_entry(&node->parent_val, struct callchain_list, list); 1223 chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node); 1224 1225 chain = list_first_entry(&node->val, struct callchain_list, list); 1226 chain->has_children = false; 1227 } 1228 return 0; 1229 1230 out: 1231 list_for_each_entry_safe(chain, new, &head, list) { 1232 list_del(&chain->list); 1233 free(chain); 1234 } 1235 return -ENOMEM; 1236 } 1237 1238 int callchain_cursor__copy(struct callchain_cursor *dst, 1239 struct callchain_cursor *src) 1240 { 1241 int rc = 0; 1242 1243 callchain_cursor_reset(dst); 1244 callchain_cursor_commit(src); 1245 1246 while (true) { 1247 struct callchain_cursor_node *node; 1248 1249 node = callchain_cursor_current(src); 1250 if (node == NULL) 1251 break; 1252 1253 rc = callchain_cursor_append(dst, node->ip, node->map, node->sym, 1254 node->branch, &node->branch_flags, 1255 node->nr_loop_iter, node->samples); 1256 if (rc) 1257 break; 1258 1259 callchain_cursor_advance(src); 1260 } 1261 1262 return rc; 1263 } 1264