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