1 // SPDX-License-Identifier: GPL-2.0 2 #include "util.h" 3 #include "build-id.h" 4 #include "hist.h" 5 #include "map.h" 6 #include "session.h" 7 #include "namespaces.h" 8 #include "sort.h" 9 #include "units.h" 10 #include "evlist.h" 11 #include "evsel.h" 12 #include "annotate.h" 13 #include "srcline.h" 14 #include "thread.h" 15 #include "ui/progress.h" 16 #include <errno.h> 17 #include <math.h> 18 #include <inttypes.h> 19 #include <sys/param.h> 20 21 static bool hists__filter_entry_by_dso(struct hists *hists, 22 struct hist_entry *he); 23 static bool hists__filter_entry_by_thread(struct hists *hists, 24 struct hist_entry *he); 25 static bool hists__filter_entry_by_symbol(struct hists *hists, 26 struct hist_entry *he); 27 static bool hists__filter_entry_by_socket(struct hists *hists, 28 struct hist_entry *he); 29 30 u16 hists__col_len(struct hists *hists, enum hist_column col) 31 { 32 return hists->col_len[col]; 33 } 34 35 void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len) 36 { 37 hists->col_len[col] = len; 38 } 39 40 bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len) 41 { 42 if (len > hists__col_len(hists, col)) { 43 hists__set_col_len(hists, col, len); 44 return true; 45 } 46 return false; 47 } 48 49 void hists__reset_col_len(struct hists *hists) 50 { 51 enum hist_column col; 52 53 for (col = 0; col < HISTC_NR_COLS; ++col) 54 hists__set_col_len(hists, col, 0); 55 } 56 57 static void hists__set_unres_dso_col_len(struct hists *hists, int dso) 58 { 59 const unsigned int unresolved_col_width = BITS_PER_LONG / 4; 60 61 if (hists__col_len(hists, dso) < unresolved_col_width && 62 !symbol_conf.col_width_list_str && !symbol_conf.field_sep && 63 !symbol_conf.dso_list) 64 hists__set_col_len(hists, dso, unresolved_col_width); 65 } 66 67 void hists__calc_col_len(struct hists *hists, struct hist_entry *h) 68 { 69 const unsigned int unresolved_col_width = BITS_PER_LONG / 4; 70 int symlen; 71 u16 len; 72 73 /* 74 * +4 accounts for '[x] ' priv level info 75 * +2 accounts for 0x prefix on raw addresses 76 * +3 accounts for ' y ' symtab origin info 77 */ 78 if (h->ms.sym) { 79 symlen = h->ms.sym->namelen + 4; 80 if (verbose > 0) 81 symlen += BITS_PER_LONG / 4 + 2 + 3; 82 hists__new_col_len(hists, HISTC_SYMBOL, symlen); 83 } else { 84 symlen = unresolved_col_width + 4 + 2; 85 hists__new_col_len(hists, HISTC_SYMBOL, symlen); 86 hists__set_unres_dso_col_len(hists, HISTC_DSO); 87 } 88 89 len = thread__comm_len(h->thread); 90 if (hists__new_col_len(hists, HISTC_COMM, len)) 91 hists__set_col_len(hists, HISTC_THREAD, len + 8); 92 93 if (h->ms.map) { 94 len = dso__name_len(h->ms.map->dso); 95 hists__new_col_len(hists, HISTC_DSO, len); 96 } 97 98 if (h->parent) 99 hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen); 100 101 if (h->branch_info) { 102 if (h->branch_info->from.sym) { 103 symlen = (int)h->branch_info->from.sym->namelen + 4; 104 if (verbose > 0) 105 symlen += BITS_PER_LONG / 4 + 2 + 3; 106 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen); 107 108 symlen = dso__name_len(h->branch_info->from.map->dso); 109 hists__new_col_len(hists, HISTC_DSO_FROM, symlen); 110 } else { 111 symlen = unresolved_col_width + 4 + 2; 112 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen); 113 hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM); 114 } 115 116 if (h->branch_info->to.sym) { 117 symlen = (int)h->branch_info->to.sym->namelen + 4; 118 if (verbose > 0) 119 symlen += BITS_PER_LONG / 4 + 2 + 3; 120 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 121 122 symlen = dso__name_len(h->branch_info->to.map->dso); 123 hists__new_col_len(hists, HISTC_DSO_TO, symlen); 124 } else { 125 symlen = unresolved_col_width + 4 + 2; 126 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 127 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); 128 } 129 130 if (h->branch_info->srcline_from) 131 hists__new_col_len(hists, HISTC_SRCLINE_FROM, 132 strlen(h->branch_info->srcline_from)); 133 if (h->branch_info->srcline_to) 134 hists__new_col_len(hists, HISTC_SRCLINE_TO, 135 strlen(h->branch_info->srcline_to)); 136 } 137 138 if (h->mem_info) { 139 if (h->mem_info->daddr.sym) { 140 symlen = (int)h->mem_info->daddr.sym->namelen + 4 141 + unresolved_col_width + 2; 142 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 143 symlen); 144 hists__new_col_len(hists, HISTC_MEM_DCACHELINE, 145 symlen + 1); 146 } else { 147 symlen = unresolved_col_width + 4 + 2; 148 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, 149 symlen); 150 hists__new_col_len(hists, HISTC_MEM_DCACHELINE, 151 symlen); 152 } 153 154 if (h->mem_info->iaddr.sym) { 155 symlen = (int)h->mem_info->iaddr.sym->namelen + 4 156 + unresolved_col_width + 2; 157 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, 158 symlen); 159 } else { 160 symlen = unresolved_col_width + 4 + 2; 161 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, 162 symlen); 163 } 164 165 if (h->mem_info->daddr.map) { 166 symlen = dso__name_len(h->mem_info->daddr.map->dso); 167 hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, 168 symlen); 169 } else { 170 symlen = unresolved_col_width + 4 + 2; 171 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 172 } 173 174 hists__new_col_len(hists, HISTC_MEM_PHYS_DADDR, 175 unresolved_col_width + 4 + 2); 176 177 } else { 178 symlen = unresolved_col_width + 4 + 2; 179 hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); 180 hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, symlen); 181 hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); 182 } 183 184 hists__new_col_len(hists, HISTC_CGROUP_ID, 20); 185 hists__new_col_len(hists, HISTC_CPU, 3); 186 hists__new_col_len(hists, HISTC_SOCKET, 6); 187 hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); 188 hists__new_col_len(hists, HISTC_MEM_TLB, 22); 189 hists__new_col_len(hists, HISTC_MEM_SNOOP, 12); 190 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); 191 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 192 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 193 194 if (h->srcline) { 195 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header)); 196 hists__new_col_len(hists, HISTC_SRCLINE, len); 197 } 198 199 if (h->srcfile) 200 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile)); 201 202 if (h->transaction) 203 hists__new_col_len(hists, HISTC_TRANSACTION, 204 hist_entry__transaction_len()); 205 206 if (h->trace_output) 207 hists__new_col_len(hists, HISTC_TRACE, strlen(h->trace_output)); 208 } 209 210 void hists__output_recalc_col_len(struct hists *hists, int max_rows) 211 { 212 struct rb_node *next = rb_first(&hists->entries); 213 struct hist_entry *n; 214 int row = 0; 215 216 hists__reset_col_len(hists); 217 218 while (next && row++ < max_rows) { 219 n = rb_entry(next, struct hist_entry, rb_node); 220 if (!n->filtered) 221 hists__calc_col_len(hists, n); 222 next = rb_next(&n->rb_node); 223 } 224 } 225 226 static void he_stat__add_cpumode_period(struct he_stat *he_stat, 227 unsigned int cpumode, u64 period) 228 { 229 switch (cpumode) { 230 case PERF_RECORD_MISC_KERNEL: 231 he_stat->period_sys += period; 232 break; 233 case PERF_RECORD_MISC_USER: 234 he_stat->period_us += period; 235 break; 236 case PERF_RECORD_MISC_GUEST_KERNEL: 237 he_stat->period_guest_sys += period; 238 break; 239 case PERF_RECORD_MISC_GUEST_USER: 240 he_stat->period_guest_us += period; 241 break; 242 default: 243 break; 244 } 245 } 246 247 static void he_stat__add_period(struct he_stat *he_stat, u64 period, 248 u64 weight) 249 { 250 251 he_stat->period += period; 252 he_stat->weight += weight; 253 he_stat->nr_events += 1; 254 } 255 256 static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) 257 { 258 dest->period += src->period; 259 dest->period_sys += src->period_sys; 260 dest->period_us += src->period_us; 261 dest->period_guest_sys += src->period_guest_sys; 262 dest->period_guest_us += src->period_guest_us; 263 dest->nr_events += src->nr_events; 264 dest->weight += src->weight; 265 } 266 267 static void he_stat__decay(struct he_stat *he_stat) 268 { 269 he_stat->period = (he_stat->period * 7) / 8; 270 he_stat->nr_events = (he_stat->nr_events * 7) / 8; 271 /* XXX need decay for weight too? */ 272 } 273 274 static void hists__delete_entry(struct hists *hists, struct hist_entry *he); 275 276 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 277 { 278 u64 prev_period = he->stat.period; 279 u64 diff; 280 281 if (prev_period == 0) 282 return true; 283 284 he_stat__decay(&he->stat); 285 if (symbol_conf.cumulate_callchain) 286 he_stat__decay(he->stat_acc); 287 decay_callchain(he->callchain); 288 289 diff = prev_period - he->stat.period; 290 291 if (!he->depth) { 292 hists->stats.total_period -= diff; 293 if (!he->filtered) 294 hists->stats.total_non_filtered_period -= diff; 295 } 296 297 if (!he->leaf) { 298 struct hist_entry *child; 299 struct rb_node *node = rb_first(&he->hroot_out); 300 while (node) { 301 child = rb_entry(node, struct hist_entry, rb_node); 302 node = rb_next(node); 303 304 if (hists__decay_entry(hists, child)) 305 hists__delete_entry(hists, child); 306 } 307 } 308 309 return he->stat.period == 0; 310 } 311 312 static void hists__delete_entry(struct hists *hists, struct hist_entry *he) 313 { 314 struct rb_root *root_in; 315 struct rb_root *root_out; 316 317 if (he->parent_he) { 318 root_in = &he->parent_he->hroot_in; 319 root_out = &he->parent_he->hroot_out; 320 } else { 321 if (hists__has(hists, need_collapse)) 322 root_in = &hists->entries_collapsed; 323 else 324 root_in = hists->entries_in; 325 root_out = &hists->entries; 326 } 327 328 rb_erase(&he->rb_node_in, root_in); 329 rb_erase(&he->rb_node, root_out); 330 331 --hists->nr_entries; 332 if (!he->filtered) 333 --hists->nr_non_filtered_entries; 334 335 hist_entry__delete(he); 336 } 337 338 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) 339 { 340 struct rb_node *next = rb_first(&hists->entries); 341 struct hist_entry *n; 342 343 while (next) { 344 n = rb_entry(next, struct hist_entry, rb_node); 345 next = rb_next(&n->rb_node); 346 if (((zap_user && n->level == '.') || 347 (zap_kernel && n->level != '.') || 348 hists__decay_entry(hists, n))) { 349 hists__delete_entry(hists, n); 350 } 351 } 352 } 353 354 void hists__delete_entries(struct hists *hists) 355 { 356 struct rb_node *next = rb_first(&hists->entries); 357 struct hist_entry *n; 358 359 while (next) { 360 n = rb_entry(next, struct hist_entry, rb_node); 361 next = rb_next(&n->rb_node); 362 363 hists__delete_entry(hists, n); 364 } 365 } 366 367 /* 368 * histogram, sorted on item, collects periods 369 */ 370 371 static int hist_entry__init(struct hist_entry *he, 372 struct hist_entry *template, 373 bool sample_self, 374 size_t callchain_size) 375 { 376 *he = *template; 377 he->callchain_size = callchain_size; 378 379 if (symbol_conf.cumulate_callchain) { 380 he->stat_acc = malloc(sizeof(he->stat)); 381 if (he->stat_acc == NULL) 382 return -ENOMEM; 383 memcpy(he->stat_acc, &he->stat, sizeof(he->stat)); 384 if (!sample_self) 385 memset(&he->stat, 0, sizeof(he->stat)); 386 } 387 388 map__get(he->ms.map); 389 390 if (he->branch_info) { 391 /* 392 * This branch info is (a part of) allocated from 393 * sample__resolve_bstack() and will be freed after 394 * adding new entries. So we need to save a copy. 395 */ 396 he->branch_info = malloc(sizeof(*he->branch_info)); 397 if (he->branch_info == NULL) { 398 map__zput(he->ms.map); 399 free(he->stat_acc); 400 return -ENOMEM; 401 } 402 403 memcpy(he->branch_info, template->branch_info, 404 sizeof(*he->branch_info)); 405 406 map__get(he->branch_info->from.map); 407 map__get(he->branch_info->to.map); 408 } 409 410 if (he->mem_info) { 411 map__get(he->mem_info->iaddr.map); 412 map__get(he->mem_info->daddr.map); 413 } 414 415 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) 416 callchain_init(he->callchain); 417 418 if (he->raw_data) { 419 he->raw_data = memdup(he->raw_data, he->raw_size); 420 421 if (he->raw_data == NULL) { 422 map__put(he->ms.map); 423 if (he->branch_info) { 424 map__put(he->branch_info->from.map); 425 map__put(he->branch_info->to.map); 426 free(he->branch_info); 427 } 428 if (he->mem_info) { 429 map__put(he->mem_info->iaddr.map); 430 map__put(he->mem_info->daddr.map); 431 } 432 free(he->stat_acc); 433 return -ENOMEM; 434 } 435 } 436 INIT_LIST_HEAD(&he->pairs.node); 437 thread__get(he->thread); 438 he->hroot_in = RB_ROOT; 439 he->hroot_out = RB_ROOT; 440 441 if (!symbol_conf.report_hierarchy) 442 he->leaf = true; 443 444 return 0; 445 } 446 447 static void *hist_entry__zalloc(size_t size) 448 { 449 return zalloc(size + sizeof(struct hist_entry)); 450 } 451 452 static void hist_entry__free(void *ptr) 453 { 454 free(ptr); 455 } 456 457 static struct hist_entry_ops default_ops = { 458 .new = hist_entry__zalloc, 459 .free = hist_entry__free, 460 }; 461 462 static struct hist_entry *hist_entry__new(struct hist_entry *template, 463 bool sample_self) 464 { 465 struct hist_entry_ops *ops = template->ops; 466 size_t callchain_size = 0; 467 struct hist_entry *he; 468 int err = 0; 469 470 if (!ops) 471 ops = template->ops = &default_ops; 472 473 if (symbol_conf.use_callchain) 474 callchain_size = sizeof(struct callchain_root); 475 476 he = ops->new(callchain_size); 477 if (he) { 478 err = hist_entry__init(he, template, sample_self, callchain_size); 479 if (err) { 480 ops->free(he); 481 he = NULL; 482 } 483 } 484 485 return he; 486 } 487 488 static u8 symbol__parent_filter(const struct symbol *parent) 489 { 490 if (symbol_conf.exclude_other && parent == NULL) 491 return 1 << HIST_FILTER__PARENT; 492 return 0; 493 } 494 495 static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period) 496 { 497 if (!hist_entry__has_callchains(he) || !symbol_conf.use_callchain) 498 return; 499 500 he->hists->callchain_period += period; 501 if (!he->filtered) 502 he->hists->callchain_non_filtered_period += period; 503 } 504 505 static struct hist_entry *hists__findnew_entry(struct hists *hists, 506 struct hist_entry *entry, 507 struct addr_location *al, 508 bool sample_self) 509 { 510 struct rb_node **p; 511 struct rb_node *parent = NULL; 512 struct hist_entry *he; 513 int64_t cmp; 514 u64 period = entry->stat.period; 515 u64 weight = entry->stat.weight; 516 517 p = &hists->entries_in->rb_node; 518 519 while (*p != NULL) { 520 parent = *p; 521 he = rb_entry(parent, struct hist_entry, rb_node_in); 522 523 /* 524 * Make sure that it receives arguments in a same order as 525 * hist_entry__collapse() so that we can use an appropriate 526 * function when searching an entry regardless which sort 527 * keys were used. 528 */ 529 cmp = hist_entry__cmp(he, entry); 530 531 if (!cmp) { 532 if (sample_self) { 533 he_stat__add_period(&he->stat, period, weight); 534 hist_entry__add_callchain_period(he, period); 535 } 536 if (symbol_conf.cumulate_callchain) 537 he_stat__add_period(he->stat_acc, period, weight); 538 539 /* 540 * This mem info was allocated from sample__resolve_mem 541 * and will not be used anymore. 542 */ 543 mem_info__zput(entry->mem_info); 544 545 /* If the map of an existing hist_entry has 546 * become out-of-date due to an exec() or 547 * similar, update it. Otherwise we will 548 * mis-adjust symbol addresses when computing 549 * the history counter to increment. 550 */ 551 if (he->ms.map != entry->ms.map) { 552 map__put(he->ms.map); 553 he->ms.map = map__get(entry->ms.map); 554 } 555 goto out; 556 } 557 558 if (cmp < 0) 559 p = &(*p)->rb_left; 560 else 561 p = &(*p)->rb_right; 562 } 563 564 he = hist_entry__new(entry, sample_self); 565 if (!he) 566 return NULL; 567 568 if (sample_self) 569 hist_entry__add_callchain_period(he, period); 570 hists->nr_entries++; 571 572 rb_link_node(&he->rb_node_in, parent, p); 573 rb_insert_color(&he->rb_node_in, hists->entries_in); 574 out: 575 if (sample_self) 576 he_stat__add_cpumode_period(&he->stat, al->cpumode, period); 577 if (symbol_conf.cumulate_callchain) 578 he_stat__add_cpumode_period(he->stat_acc, al->cpumode, period); 579 return he; 580 } 581 582 static struct hist_entry* 583 __hists__add_entry(struct hists *hists, 584 struct addr_location *al, 585 struct symbol *sym_parent, 586 struct branch_info *bi, 587 struct mem_info *mi, 588 struct perf_sample *sample, 589 bool sample_self, 590 struct hist_entry_ops *ops) 591 { 592 struct namespaces *ns = thread__namespaces(al->thread); 593 struct hist_entry entry = { 594 .thread = al->thread, 595 .comm = thread__comm(al->thread), 596 .cgroup_id = { 597 .dev = ns ? ns->link_info[CGROUP_NS_INDEX].dev : 0, 598 .ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0, 599 }, 600 .ms = { 601 .map = al->map, 602 .sym = al->sym, 603 }, 604 .srcline = al->srcline ? strdup(al->srcline) : NULL, 605 .socket = al->socket, 606 .cpu = al->cpu, 607 .cpumode = al->cpumode, 608 .ip = al->addr, 609 .level = al->level, 610 .stat = { 611 .nr_events = 1, 612 .period = sample->period, 613 .weight = sample->weight, 614 }, 615 .parent = sym_parent, 616 .filtered = symbol__parent_filter(sym_parent) | al->filtered, 617 .hists = hists, 618 .branch_info = bi, 619 .mem_info = mi, 620 .transaction = sample->transaction, 621 .raw_data = sample->raw_data, 622 .raw_size = sample->raw_size, 623 .ops = ops, 624 }, *he = hists__findnew_entry(hists, &entry, al, sample_self); 625 626 if (!hists->has_callchains && he && he->callchain_size != 0) 627 hists->has_callchains = true; 628 return he; 629 } 630 631 struct hist_entry *hists__add_entry(struct hists *hists, 632 struct addr_location *al, 633 struct symbol *sym_parent, 634 struct branch_info *bi, 635 struct mem_info *mi, 636 struct perf_sample *sample, 637 bool sample_self) 638 { 639 return __hists__add_entry(hists, al, sym_parent, bi, mi, 640 sample, sample_self, NULL); 641 } 642 643 struct hist_entry *hists__add_entry_ops(struct hists *hists, 644 struct hist_entry_ops *ops, 645 struct addr_location *al, 646 struct symbol *sym_parent, 647 struct branch_info *bi, 648 struct mem_info *mi, 649 struct perf_sample *sample, 650 bool sample_self) 651 { 652 return __hists__add_entry(hists, al, sym_parent, bi, mi, 653 sample, sample_self, ops); 654 } 655 656 static int 657 iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, 658 struct addr_location *al __maybe_unused) 659 { 660 return 0; 661 } 662 663 static int 664 iter_add_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, 665 struct addr_location *al __maybe_unused) 666 { 667 return 0; 668 } 669 670 static int 671 iter_prepare_mem_entry(struct hist_entry_iter *iter, struct addr_location *al) 672 { 673 struct perf_sample *sample = iter->sample; 674 struct mem_info *mi; 675 676 mi = sample__resolve_mem(sample, al); 677 if (mi == NULL) 678 return -ENOMEM; 679 680 iter->priv = mi; 681 return 0; 682 } 683 684 static int 685 iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al) 686 { 687 u64 cost; 688 struct mem_info *mi = iter->priv; 689 struct hists *hists = evsel__hists(iter->evsel); 690 struct perf_sample *sample = iter->sample; 691 struct hist_entry *he; 692 693 if (mi == NULL) 694 return -EINVAL; 695 696 cost = sample->weight; 697 if (!cost) 698 cost = 1; 699 700 /* 701 * must pass period=weight in order to get the correct 702 * sorting from hists__collapse_resort() which is solely 703 * based on periods. We want sorting be done on nr_events * weight 704 * and this is indirectly achieved by passing period=weight here 705 * and the he_stat__add_period() function. 706 */ 707 sample->period = cost; 708 709 he = hists__add_entry(hists, al, iter->parent, NULL, mi, 710 sample, true); 711 if (!he) 712 return -ENOMEM; 713 714 iter->he = he; 715 return 0; 716 } 717 718 static int 719 iter_finish_mem_entry(struct hist_entry_iter *iter, 720 struct addr_location *al __maybe_unused) 721 { 722 struct perf_evsel *evsel = iter->evsel; 723 struct hists *hists = evsel__hists(evsel); 724 struct hist_entry *he = iter->he; 725 int err = -EINVAL; 726 727 if (he == NULL) 728 goto out; 729 730 hists__inc_nr_samples(hists, he->filtered); 731 732 err = hist_entry__append_callchain(he, iter->sample); 733 734 out: 735 /* 736 * We don't need to free iter->priv (mem_info) here since the mem info 737 * was either already freed in hists__findnew_entry() or passed to a 738 * new hist entry by hist_entry__new(). 739 */ 740 iter->priv = NULL; 741 742 iter->he = NULL; 743 return err; 744 } 745 746 static int 747 iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) 748 { 749 struct branch_info *bi; 750 struct perf_sample *sample = iter->sample; 751 752 bi = sample__resolve_bstack(sample, al); 753 if (!bi) 754 return -ENOMEM; 755 756 iter->curr = 0; 757 iter->total = sample->branch_stack->nr; 758 759 iter->priv = bi; 760 return 0; 761 } 762 763 static int 764 iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused, 765 struct addr_location *al __maybe_unused) 766 { 767 return 0; 768 } 769 770 static int 771 iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) 772 { 773 struct branch_info *bi = iter->priv; 774 int i = iter->curr; 775 776 if (bi == NULL) 777 return 0; 778 779 if (iter->curr >= iter->total) 780 return 0; 781 782 al->map = bi[i].to.map; 783 al->sym = bi[i].to.sym; 784 al->addr = bi[i].to.addr; 785 return 1; 786 } 787 788 static int 789 iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al) 790 { 791 struct branch_info *bi; 792 struct perf_evsel *evsel = iter->evsel; 793 struct hists *hists = evsel__hists(evsel); 794 struct perf_sample *sample = iter->sample; 795 struct hist_entry *he = NULL; 796 int i = iter->curr; 797 int err = 0; 798 799 bi = iter->priv; 800 801 if (iter->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym)) 802 goto out; 803 804 /* 805 * The report shows the percentage of total branches captured 806 * and not events sampled. Thus we use a pseudo period of 1. 807 */ 808 sample->period = 1; 809 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1; 810 811 he = hists__add_entry(hists, al, iter->parent, &bi[i], NULL, 812 sample, true); 813 if (he == NULL) 814 return -ENOMEM; 815 816 hists__inc_nr_samples(hists, he->filtered); 817 818 out: 819 iter->he = he; 820 iter->curr++; 821 return err; 822 } 823 824 static int 825 iter_finish_branch_entry(struct hist_entry_iter *iter, 826 struct addr_location *al __maybe_unused) 827 { 828 zfree(&iter->priv); 829 iter->he = NULL; 830 831 return iter->curr >= iter->total ? 0 : -1; 832 } 833 834 static int 835 iter_prepare_normal_entry(struct hist_entry_iter *iter __maybe_unused, 836 struct addr_location *al __maybe_unused) 837 { 838 return 0; 839 } 840 841 static int 842 iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location *al) 843 { 844 struct perf_evsel *evsel = iter->evsel; 845 struct perf_sample *sample = iter->sample; 846 struct hist_entry *he; 847 848 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 849 sample, true); 850 if (he == NULL) 851 return -ENOMEM; 852 853 iter->he = he; 854 return 0; 855 } 856 857 static int 858 iter_finish_normal_entry(struct hist_entry_iter *iter, 859 struct addr_location *al __maybe_unused) 860 { 861 struct hist_entry *he = iter->he; 862 struct perf_evsel *evsel = iter->evsel; 863 struct perf_sample *sample = iter->sample; 864 865 if (he == NULL) 866 return 0; 867 868 iter->he = NULL; 869 870 hists__inc_nr_samples(evsel__hists(evsel), he->filtered); 871 872 return hist_entry__append_callchain(he, sample); 873 } 874 875 static int 876 iter_prepare_cumulative_entry(struct hist_entry_iter *iter, 877 struct addr_location *al __maybe_unused) 878 { 879 struct hist_entry **he_cache; 880 881 callchain_cursor_commit(&callchain_cursor); 882 883 /* 884 * This is for detecting cycles or recursions so that they're 885 * cumulated only one time to prevent entries more than 100% 886 * overhead. 887 */ 888 he_cache = malloc(sizeof(*he_cache) * (callchain_cursor.nr + 1)); 889 if (he_cache == NULL) 890 return -ENOMEM; 891 892 iter->priv = he_cache; 893 iter->curr = 0; 894 895 return 0; 896 } 897 898 static int 899 iter_add_single_cumulative_entry(struct hist_entry_iter *iter, 900 struct addr_location *al) 901 { 902 struct perf_evsel *evsel = iter->evsel; 903 struct hists *hists = evsel__hists(evsel); 904 struct perf_sample *sample = iter->sample; 905 struct hist_entry **he_cache = iter->priv; 906 struct hist_entry *he; 907 int err = 0; 908 909 he = hists__add_entry(hists, al, iter->parent, NULL, NULL, 910 sample, true); 911 if (he == NULL) 912 return -ENOMEM; 913 914 iter->he = he; 915 he_cache[iter->curr++] = he; 916 917 hist_entry__append_callchain(he, sample); 918 919 /* 920 * We need to re-initialize the cursor since callchain_append() 921 * advanced the cursor to the end. 922 */ 923 callchain_cursor_commit(&callchain_cursor); 924 925 hists__inc_nr_samples(hists, he->filtered); 926 927 return err; 928 } 929 930 static int 931 iter_next_cumulative_entry(struct hist_entry_iter *iter, 932 struct addr_location *al) 933 { 934 struct callchain_cursor_node *node; 935 936 node = callchain_cursor_current(&callchain_cursor); 937 if (node == NULL) 938 return 0; 939 940 return fill_callchain_info(al, node, iter->hide_unresolved); 941 } 942 943 static int 944 iter_add_next_cumulative_entry(struct hist_entry_iter *iter, 945 struct addr_location *al) 946 { 947 struct perf_evsel *evsel = iter->evsel; 948 struct perf_sample *sample = iter->sample; 949 struct hist_entry **he_cache = iter->priv; 950 struct hist_entry *he; 951 struct hist_entry he_tmp = { 952 .hists = evsel__hists(evsel), 953 .cpu = al->cpu, 954 .thread = al->thread, 955 .comm = thread__comm(al->thread), 956 .ip = al->addr, 957 .ms = { 958 .map = al->map, 959 .sym = al->sym, 960 }, 961 .srcline = al->srcline ? strdup(al->srcline) : NULL, 962 .parent = iter->parent, 963 .raw_data = sample->raw_data, 964 .raw_size = sample->raw_size, 965 }; 966 int i; 967 struct callchain_cursor cursor; 968 969 callchain_cursor_snapshot(&cursor, &callchain_cursor); 970 971 callchain_cursor_advance(&callchain_cursor); 972 973 /* 974 * Check if there's duplicate entries in the callchain. 975 * It's possible that it has cycles or recursive calls. 976 */ 977 for (i = 0; i < iter->curr; i++) { 978 if (hist_entry__cmp(he_cache[i], &he_tmp) == 0) { 979 /* to avoid calling callback function */ 980 iter->he = NULL; 981 return 0; 982 } 983 } 984 985 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 986 sample, false); 987 if (he == NULL) 988 return -ENOMEM; 989 990 iter->he = he; 991 he_cache[iter->curr++] = he; 992 993 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) 994 callchain_append(he->callchain, &cursor, sample->period); 995 return 0; 996 } 997 998 static int 999 iter_finish_cumulative_entry(struct hist_entry_iter *iter, 1000 struct addr_location *al __maybe_unused) 1001 { 1002 zfree(&iter->priv); 1003 iter->he = NULL; 1004 1005 return 0; 1006 } 1007 1008 const struct hist_iter_ops hist_iter_mem = { 1009 .prepare_entry = iter_prepare_mem_entry, 1010 .add_single_entry = iter_add_single_mem_entry, 1011 .next_entry = iter_next_nop_entry, 1012 .add_next_entry = iter_add_next_nop_entry, 1013 .finish_entry = iter_finish_mem_entry, 1014 }; 1015 1016 const struct hist_iter_ops hist_iter_branch = { 1017 .prepare_entry = iter_prepare_branch_entry, 1018 .add_single_entry = iter_add_single_branch_entry, 1019 .next_entry = iter_next_branch_entry, 1020 .add_next_entry = iter_add_next_branch_entry, 1021 .finish_entry = iter_finish_branch_entry, 1022 }; 1023 1024 const struct hist_iter_ops hist_iter_normal = { 1025 .prepare_entry = iter_prepare_normal_entry, 1026 .add_single_entry = iter_add_single_normal_entry, 1027 .next_entry = iter_next_nop_entry, 1028 .add_next_entry = iter_add_next_nop_entry, 1029 .finish_entry = iter_finish_normal_entry, 1030 }; 1031 1032 const struct hist_iter_ops hist_iter_cumulative = { 1033 .prepare_entry = iter_prepare_cumulative_entry, 1034 .add_single_entry = iter_add_single_cumulative_entry, 1035 .next_entry = iter_next_cumulative_entry, 1036 .add_next_entry = iter_add_next_cumulative_entry, 1037 .finish_entry = iter_finish_cumulative_entry, 1038 }; 1039 1040 int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 1041 int max_stack_depth, void *arg) 1042 { 1043 int err, err2; 1044 struct map *alm = NULL; 1045 1046 if (al) 1047 alm = map__get(al->map); 1048 1049 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, 1050 iter->evsel, al, max_stack_depth); 1051 if (err) 1052 return err; 1053 1054 err = iter->ops->prepare_entry(iter, al); 1055 if (err) 1056 goto out; 1057 1058 err = iter->ops->add_single_entry(iter, al); 1059 if (err) 1060 goto out; 1061 1062 if (iter->he && iter->add_entry_cb) { 1063 err = iter->add_entry_cb(iter, al, true, arg); 1064 if (err) 1065 goto out; 1066 } 1067 1068 while (iter->ops->next_entry(iter, al)) { 1069 err = iter->ops->add_next_entry(iter, al); 1070 if (err) 1071 break; 1072 1073 if (iter->he && iter->add_entry_cb) { 1074 err = iter->add_entry_cb(iter, al, false, arg); 1075 if (err) 1076 goto out; 1077 } 1078 } 1079 1080 out: 1081 err2 = iter->ops->finish_entry(iter, al); 1082 if (!err) 1083 err = err2; 1084 1085 map__put(alm); 1086 1087 return err; 1088 } 1089 1090 int64_t 1091 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 1092 { 1093 struct hists *hists = left->hists; 1094 struct perf_hpp_fmt *fmt; 1095 int64_t cmp = 0; 1096 1097 hists__for_each_sort_list(hists, fmt) { 1098 if (perf_hpp__is_dynamic_entry(fmt) && 1099 !perf_hpp__defined_dynamic_entry(fmt, hists)) 1100 continue; 1101 1102 cmp = fmt->cmp(fmt, left, right); 1103 if (cmp) 1104 break; 1105 } 1106 1107 return cmp; 1108 } 1109 1110 int64_t 1111 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) 1112 { 1113 struct hists *hists = left->hists; 1114 struct perf_hpp_fmt *fmt; 1115 int64_t cmp = 0; 1116 1117 hists__for_each_sort_list(hists, fmt) { 1118 if (perf_hpp__is_dynamic_entry(fmt) && 1119 !perf_hpp__defined_dynamic_entry(fmt, hists)) 1120 continue; 1121 1122 cmp = fmt->collapse(fmt, left, right); 1123 if (cmp) 1124 break; 1125 } 1126 1127 return cmp; 1128 } 1129 1130 void hist_entry__delete(struct hist_entry *he) 1131 { 1132 struct hist_entry_ops *ops = he->ops; 1133 1134 thread__zput(he->thread); 1135 map__zput(he->ms.map); 1136 1137 if (he->branch_info) { 1138 map__zput(he->branch_info->from.map); 1139 map__zput(he->branch_info->to.map); 1140 free_srcline(he->branch_info->srcline_from); 1141 free_srcline(he->branch_info->srcline_to); 1142 zfree(&he->branch_info); 1143 } 1144 1145 if (he->mem_info) { 1146 map__zput(he->mem_info->iaddr.map); 1147 map__zput(he->mem_info->daddr.map); 1148 mem_info__zput(he->mem_info); 1149 } 1150 1151 zfree(&he->stat_acc); 1152 free_srcline(he->srcline); 1153 if (he->srcfile && he->srcfile[0]) 1154 free(he->srcfile); 1155 free_callchain(he->callchain); 1156 free(he->trace_output); 1157 free(he->raw_data); 1158 ops->free(he); 1159 } 1160 1161 /* 1162 * If this is not the last column, then we need to pad it according to the 1163 * pre-calculated max lenght for this column, otherwise don't bother adding 1164 * spaces because that would break viewing this with, for instance, 'less', 1165 * that would show tons of trailing spaces when a long C++ demangled method 1166 * names is sampled. 1167 */ 1168 int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, 1169 struct perf_hpp_fmt *fmt, int printed) 1170 { 1171 if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { 1172 const int width = fmt->width(fmt, hpp, he->hists); 1173 if (printed < width) { 1174 advance_hpp(hpp, printed); 1175 printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); 1176 } 1177 } 1178 1179 return printed; 1180 } 1181 1182 /* 1183 * collapse the histogram 1184 */ 1185 1186 static void hists__apply_filters(struct hists *hists, struct hist_entry *he); 1187 static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *he, 1188 enum hist_filter type); 1189 1190 typedef bool (*fmt_chk_fn)(struct perf_hpp_fmt *fmt); 1191 1192 static bool check_thread_entry(struct perf_hpp_fmt *fmt) 1193 { 1194 return perf_hpp__is_thread_entry(fmt) || perf_hpp__is_comm_entry(fmt); 1195 } 1196 1197 static void hist_entry__check_and_remove_filter(struct hist_entry *he, 1198 enum hist_filter type, 1199 fmt_chk_fn check) 1200 { 1201 struct perf_hpp_fmt *fmt; 1202 bool type_match = false; 1203 struct hist_entry *parent = he->parent_he; 1204 1205 switch (type) { 1206 case HIST_FILTER__THREAD: 1207 if (symbol_conf.comm_list == NULL && 1208 symbol_conf.pid_list == NULL && 1209 symbol_conf.tid_list == NULL) 1210 return; 1211 break; 1212 case HIST_FILTER__DSO: 1213 if (symbol_conf.dso_list == NULL) 1214 return; 1215 break; 1216 case HIST_FILTER__SYMBOL: 1217 if (symbol_conf.sym_list == NULL) 1218 return; 1219 break; 1220 case HIST_FILTER__PARENT: 1221 case HIST_FILTER__GUEST: 1222 case HIST_FILTER__HOST: 1223 case HIST_FILTER__SOCKET: 1224 case HIST_FILTER__C2C: 1225 default: 1226 return; 1227 } 1228 1229 /* if it's filtered by own fmt, it has to have filter bits */ 1230 perf_hpp_list__for_each_format(he->hpp_list, fmt) { 1231 if (check(fmt)) { 1232 type_match = true; 1233 break; 1234 } 1235 } 1236 1237 if (type_match) { 1238 /* 1239 * If the filter is for current level entry, propagate 1240 * filter marker to parents. The marker bit was 1241 * already set by default so it only needs to clear 1242 * non-filtered entries. 1243 */ 1244 if (!(he->filtered & (1 << type))) { 1245 while (parent) { 1246 parent->filtered &= ~(1 << type); 1247 parent = parent->parent_he; 1248 } 1249 } 1250 } else { 1251 /* 1252 * If current entry doesn't have matching formats, set 1253 * filter marker for upper level entries. it will be 1254 * cleared if its lower level entries is not filtered. 1255 * 1256 * For lower-level entries, it inherits parent's 1257 * filter bit so that lower level entries of a 1258 * non-filtered entry won't set the filter marker. 1259 */ 1260 if (parent == NULL) 1261 he->filtered |= (1 << type); 1262 else 1263 he->filtered |= (parent->filtered & (1 << type)); 1264 } 1265 } 1266 1267 static void hist_entry__apply_hierarchy_filters(struct hist_entry *he) 1268 { 1269 hist_entry__check_and_remove_filter(he, HIST_FILTER__THREAD, 1270 check_thread_entry); 1271 1272 hist_entry__check_and_remove_filter(he, HIST_FILTER__DSO, 1273 perf_hpp__is_dso_entry); 1274 1275 hist_entry__check_and_remove_filter(he, HIST_FILTER__SYMBOL, 1276 perf_hpp__is_sym_entry); 1277 1278 hists__apply_filters(he->hists, he); 1279 } 1280 1281 static struct hist_entry *hierarchy_insert_entry(struct hists *hists, 1282 struct rb_root *root, 1283 struct hist_entry *he, 1284 struct hist_entry *parent_he, 1285 struct perf_hpp_list *hpp_list) 1286 { 1287 struct rb_node **p = &root->rb_node; 1288 struct rb_node *parent = NULL; 1289 struct hist_entry *iter, *new; 1290 struct perf_hpp_fmt *fmt; 1291 int64_t cmp; 1292 1293 while (*p != NULL) { 1294 parent = *p; 1295 iter = rb_entry(parent, struct hist_entry, rb_node_in); 1296 1297 cmp = 0; 1298 perf_hpp_list__for_each_sort_list(hpp_list, fmt) { 1299 cmp = fmt->collapse(fmt, iter, he); 1300 if (cmp) 1301 break; 1302 } 1303 1304 if (!cmp) { 1305 he_stat__add_stat(&iter->stat, &he->stat); 1306 return iter; 1307 } 1308 1309 if (cmp < 0) 1310 p = &parent->rb_left; 1311 else 1312 p = &parent->rb_right; 1313 } 1314 1315 new = hist_entry__new(he, true); 1316 if (new == NULL) 1317 return NULL; 1318 1319 hists->nr_entries++; 1320 1321 /* save related format list for output */ 1322 new->hpp_list = hpp_list; 1323 new->parent_he = parent_he; 1324 1325 hist_entry__apply_hierarchy_filters(new); 1326 1327 /* some fields are now passed to 'new' */ 1328 perf_hpp_list__for_each_sort_list(hpp_list, fmt) { 1329 if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) 1330 he->trace_output = NULL; 1331 else 1332 new->trace_output = NULL; 1333 1334 if (perf_hpp__is_srcline_entry(fmt)) 1335 he->srcline = NULL; 1336 else 1337 new->srcline = NULL; 1338 1339 if (perf_hpp__is_srcfile_entry(fmt)) 1340 he->srcfile = NULL; 1341 else 1342 new->srcfile = NULL; 1343 } 1344 1345 rb_link_node(&new->rb_node_in, parent, p); 1346 rb_insert_color(&new->rb_node_in, root); 1347 return new; 1348 } 1349 1350 static int hists__hierarchy_insert_entry(struct hists *hists, 1351 struct rb_root *root, 1352 struct hist_entry *he) 1353 { 1354 struct perf_hpp_list_node *node; 1355 struct hist_entry *new_he = NULL; 1356 struct hist_entry *parent = NULL; 1357 int depth = 0; 1358 int ret = 0; 1359 1360 list_for_each_entry(node, &hists->hpp_formats, list) { 1361 /* skip period (overhead) and elided columns */ 1362 if (node->level == 0 || node->skip) 1363 continue; 1364 1365 /* insert copy of 'he' for each fmt into the hierarchy */ 1366 new_he = hierarchy_insert_entry(hists, root, he, parent, &node->hpp); 1367 if (new_he == NULL) { 1368 ret = -1; 1369 break; 1370 } 1371 1372 root = &new_he->hroot_in; 1373 new_he->depth = depth++; 1374 parent = new_he; 1375 } 1376 1377 if (new_he) { 1378 new_he->leaf = true; 1379 1380 if (hist_entry__has_callchains(new_he) && 1381 symbol_conf.use_callchain) { 1382 callchain_cursor_reset(&callchain_cursor); 1383 if (callchain_merge(&callchain_cursor, 1384 new_he->callchain, 1385 he->callchain) < 0) 1386 ret = -1; 1387 } 1388 } 1389 1390 /* 'he' is no longer used */ 1391 hist_entry__delete(he); 1392 1393 /* return 0 (or -1) since it already applied filters */ 1394 return ret; 1395 } 1396 1397 static int hists__collapse_insert_entry(struct hists *hists, 1398 struct rb_root *root, 1399 struct hist_entry *he) 1400 { 1401 struct rb_node **p = &root->rb_node; 1402 struct rb_node *parent = NULL; 1403 struct hist_entry *iter; 1404 int64_t cmp; 1405 1406 if (symbol_conf.report_hierarchy) 1407 return hists__hierarchy_insert_entry(hists, root, he); 1408 1409 while (*p != NULL) { 1410 parent = *p; 1411 iter = rb_entry(parent, struct hist_entry, rb_node_in); 1412 1413 cmp = hist_entry__collapse(iter, he); 1414 1415 if (!cmp) { 1416 int ret = 0; 1417 1418 he_stat__add_stat(&iter->stat, &he->stat); 1419 if (symbol_conf.cumulate_callchain) 1420 he_stat__add_stat(iter->stat_acc, he->stat_acc); 1421 1422 if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) { 1423 callchain_cursor_reset(&callchain_cursor); 1424 if (callchain_merge(&callchain_cursor, 1425 iter->callchain, 1426 he->callchain) < 0) 1427 ret = -1; 1428 } 1429 hist_entry__delete(he); 1430 return ret; 1431 } 1432 1433 if (cmp < 0) 1434 p = &(*p)->rb_left; 1435 else 1436 p = &(*p)->rb_right; 1437 } 1438 hists->nr_entries++; 1439 1440 rb_link_node(&he->rb_node_in, parent, p); 1441 rb_insert_color(&he->rb_node_in, root); 1442 return 1; 1443 } 1444 1445 struct rb_root *hists__get_rotate_entries_in(struct hists *hists) 1446 { 1447 struct rb_root *root; 1448 1449 pthread_mutex_lock(&hists->lock); 1450 1451 root = hists->entries_in; 1452 if (++hists->entries_in > &hists->entries_in_array[1]) 1453 hists->entries_in = &hists->entries_in_array[0]; 1454 1455 pthread_mutex_unlock(&hists->lock); 1456 1457 return root; 1458 } 1459 1460 static void hists__apply_filters(struct hists *hists, struct hist_entry *he) 1461 { 1462 hists__filter_entry_by_dso(hists, he); 1463 hists__filter_entry_by_thread(hists, he); 1464 hists__filter_entry_by_symbol(hists, he); 1465 hists__filter_entry_by_socket(hists, he); 1466 } 1467 1468 int hists__collapse_resort(struct hists *hists, struct ui_progress *prog) 1469 { 1470 struct rb_root *root; 1471 struct rb_node *next; 1472 struct hist_entry *n; 1473 int ret; 1474 1475 if (!hists__has(hists, need_collapse)) 1476 return 0; 1477 1478 hists->nr_entries = 0; 1479 1480 root = hists__get_rotate_entries_in(hists); 1481 1482 next = rb_first(root); 1483 1484 while (next) { 1485 if (session_done()) 1486 break; 1487 n = rb_entry(next, struct hist_entry, rb_node_in); 1488 next = rb_next(&n->rb_node_in); 1489 1490 rb_erase(&n->rb_node_in, root); 1491 ret = hists__collapse_insert_entry(hists, &hists->entries_collapsed, n); 1492 if (ret < 0) 1493 return -1; 1494 1495 if (ret) { 1496 /* 1497 * If it wasn't combined with one of the entries already 1498 * collapsed, we need to apply the filters that may have 1499 * been set by, say, the hist_browser. 1500 */ 1501 hists__apply_filters(hists, n); 1502 } 1503 if (prog) 1504 ui_progress__update(prog, 1); 1505 } 1506 return 0; 1507 } 1508 1509 static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) 1510 { 1511 struct hists *hists = a->hists; 1512 struct perf_hpp_fmt *fmt; 1513 int64_t cmp = 0; 1514 1515 hists__for_each_sort_list(hists, fmt) { 1516 if (perf_hpp__should_skip(fmt, a->hists)) 1517 continue; 1518 1519 cmp = fmt->sort(fmt, a, b); 1520 if (cmp) 1521 break; 1522 } 1523 1524 return cmp; 1525 } 1526 1527 static void hists__reset_filter_stats(struct hists *hists) 1528 { 1529 hists->nr_non_filtered_entries = 0; 1530 hists->stats.total_non_filtered_period = 0; 1531 } 1532 1533 void hists__reset_stats(struct hists *hists) 1534 { 1535 hists->nr_entries = 0; 1536 hists->stats.total_period = 0; 1537 1538 hists__reset_filter_stats(hists); 1539 } 1540 1541 static void hists__inc_filter_stats(struct hists *hists, struct hist_entry *h) 1542 { 1543 hists->nr_non_filtered_entries++; 1544 hists->stats.total_non_filtered_period += h->stat.period; 1545 } 1546 1547 void hists__inc_stats(struct hists *hists, struct hist_entry *h) 1548 { 1549 if (!h->filtered) 1550 hists__inc_filter_stats(hists, h); 1551 1552 hists->nr_entries++; 1553 hists->stats.total_period += h->stat.period; 1554 } 1555 1556 static void hierarchy_recalc_total_periods(struct hists *hists) 1557 { 1558 struct rb_node *node; 1559 struct hist_entry *he; 1560 1561 node = rb_first(&hists->entries); 1562 1563 hists->stats.total_period = 0; 1564 hists->stats.total_non_filtered_period = 0; 1565 1566 /* 1567 * recalculate total period using top-level entries only 1568 * since lower level entries only see non-filtered entries 1569 * but upper level entries have sum of both entries. 1570 */ 1571 while (node) { 1572 he = rb_entry(node, struct hist_entry, rb_node); 1573 node = rb_next(node); 1574 1575 hists->stats.total_period += he->stat.period; 1576 if (!he->filtered) 1577 hists->stats.total_non_filtered_period += he->stat.period; 1578 } 1579 } 1580 1581 static void hierarchy_insert_output_entry(struct rb_root *root, 1582 struct hist_entry *he) 1583 { 1584 struct rb_node **p = &root->rb_node; 1585 struct rb_node *parent = NULL; 1586 struct hist_entry *iter; 1587 struct perf_hpp_fmt *fmt; 1588 1589 while (*p != NULL) { 1590 parent = *p; 1591 iter = rb_entry(parent, struct hist_entry, rb_node); 1592 1593 if (hist_entry__sort(he, iter) > 0) 1594 p = &parent->rb_left; 1595 else 1596 p = &parent->rb_right; 1597 } 1598 1599 rb_link_node(&he->rb_node, parent, p); 1600 rb_insert_color(&he->rb_node, root); 1601 1602 /* update column width of dynamic entry */ 1603 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) { 1604 if (perf_hpp__is_dynamic_entry(fmt)) 1605 fmt->sort(fmt, he, NULL); 1606 } 1607 } 1608 1609 static void hists__hierarchy_output_resort(struct hists *hists, 1610 struct ui_progress *prog, 1611 struct rb_root *root_in, 1612 struct rb_root *root_out, 1613 u64 min_callchain_hits, 1614 bool use_callchain) 1615 { 1616 struct rb_node *node; 1617 struct hist_entry *he; 1618 1619 *root_out = RB_ROOT; 1620 node = rb_first(root_in); 1621 1622 while (node) { 1623 he = rb_entry(node, struct hist_entry, rb_node_in); 1624 node = rb_next(node); 1625 1626 hierarchy_insert_output_entry(root_out, he); 1627 1628 if (prog) 1629 ui_progress__update(prog, 1); 1630 1631 hists->nr_entries++; 1632 if (!he->filtered) { 1633 hists->nr_non_filtered_entries++; 1634 hists__calc_col_len(hists, he); 1635 } 1636 1637 if (!he->leaf) { 1638 hists__hierarchy_output_resort(hists, prog, 1639 &he->hroot_in, 1640 &he->hroot_out, 1641 min_callchain_hits, 1642 use_callchain); 1643 continue; 1644 } 1645 1646 if (!use_callchain) 1647 continue; 1648 1649 if (callchain_param.mode == CHAIN_GRAPH_REL) { 1650 u64 total = he->stat.period; 1651 1652 if (symbol_conf.cumulate_callchain) 1653 total = he->stat_acc->period; 1654 1655 min_callchain_hits = total * (callchain_param.min_percent / 100); 1656 } 1657 1658 callchain_param.sort(&he->sorted_chain, he->callchain, 1659 min_callchain_hits, &callchain_param); 1660 } 1661 } 1662 1663 static void __hists__insert_output_entry(struct rb_root *entries, 1664 struct hist_entry *he, 1665 u64 min_callchain_hits, 1666 bool use_callchain) 1667 { 1668 struct rb_node **p = &entries->rb_node; 1669 struct rb_node *parent = NULL; 1670 struct hist_entry *iter; 1671 struct perf_hpp_fmt *fmt; 1672 1673 if (use_callchain) { 1674 if (callchain_param.mode == CHAIN_GRAPH_REL) { 1675 u64 total = he->stat.period; 1676 1677 if (symbol_conf.cumulate_callchain) 1678 total = he->stat_acc->period; 1679 1680 min_callchain_hits = total * (callchain_param.min_percent / 100); 1681 } 1682 callchain_param.sort(&he->sorted_chain, he->callchain, 1683 min_callchain_hits, &callchain_param); 1684 } 1685 1686 while (*p != NULL) { 1687 parent = *p; 1688 iter = rb_entry(parent, struct hist_entry, rb_node); 1689 1690 if (hist_entry__sort(he, iter) > 0) 1691 p = &(*p)->rb_left; 1692 else 1693 p = &(*p)->rb_right; 1694 } 1695 1696 rb_link_node(&he->rb_node, parent, p); 1697 rb_insert_color(&he->rb_node, entries); 1698 1699 perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { 1700 if (perf_hpp__is_dynamic_entry(fmt) && 1701 perf_hpp__defined_dynamic_entry(fmt, he->hists)) 1702 fmt->sort(fmt, he, NULL); /* update column width */ 1703 } 1704 } 1705 1706 static void output_resort(struct hists *hists, struct ui_progress *prog, 1707 bool use_callchain, hists__resort_cb_t cb) 1708 { 1709 struct rb_root *root; 1710 struct rb_node *next; 1711 struct hist_entry *n; 1712 u64 callchain_total; 1713 u64 min_callchain_hits; 1714 1715 callchain_total = hists->callchain_period; 1716 if (symbol_conf.filter_relative) 1717 callchain_total = hists->callchain_non_filtered_period; 1718 1719 min_callchain_hits = callchain_total * (callchain_param.min_percent / 100); 1720 1721 hists__reset_stats(hists); 1722 hists__reset_col_len(hists); 1723 1724 if (symbol_conf.report_hierarchy) { 1725 hists__hierarchy_output_resort(hists, prog, 1726 &hists->entries_collapsed, 1727 &hists->entries, 1728 min_callchain_hits, 1729 use_callchain); 1730 hierarchy_recalc_total_periods(hists); 1731 return; 1732 } 1733 1734 if (hists__has(hists, need_collapse)) 1735 root = &hists->entries_collapsed; 1736 else 1737 root = hists->entries_in; 1738 1739 next = rb_first(root); 1740 hists->entries = RB_ROOT; 1741 1742 while (next) { 1743 n = rb_entry(next, struct hist_entry, rb_node_in); 1744 next = rb_next(&n->rb_node_in); 1745 1746 if (cb && cb(n)) 1747 continue; 1748 1749 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); 1750 hists__inc_stats(hists, n); 1751 1752 if (!n->filtered) 1753 hists__calc_col_len(hists, n); 1754 1755 if (prog) 1756 ui_progress__update(prog, 1); 1757 } 1758 } 1759 1760 void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog) 1761 { 1762 bool use_callchain; 1763 1764 if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) 1765 use_callchain = evsel__has_callchain(evsel); 1766 else 1767 use_callchain = symbol_conf.use_callchain; 1768 1769 use_callchain |= symbol_conf.show_branchflag_count; 1770 1771 output_resort(evsel__hists(evsel), prog, use_callchain, NULL); 1772 } 1773 1774 void hists__output_resort(struct hists *hists, struct ui_progress *prog) 1775 { 1776 output_resort(hists, prog, symbol_conf.use_callchain, NULL); 1777 } 1778 1779 void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, 1780 hists__resort_cb_t cb) 1781 { 1782 output_resort(hists, prog, symbol_conf.use_callchain, cb); 1783 } 1784 1785 static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) 1786 { 1787 if (he->leaf || hmd == HMD_FORCE_SIBLING) 1788 return false; 1789 1790 if (he->unfolded || hmd == HMD_FORCE_CHILD) 1791 return true; 1792 1793 return false; 1794 } 1795 1796 struct rb_node *rb_hierarchy_last(struct rb_node *node) 1797 { 1798 struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node); 1799 1800 while (can_goto_child(he, HMD_NORMAL)) { 1801 node = rb_last(&he->hroot_out); 1802 he = rb_entry(node, struct hist_entry, rb_node); 1803 } 1804 return node; 1805 } 1806 1807 struct rb_node *__rb_hierarchy_next(struct rb_node *node, enum hierarchy_move_dir hmd) 1808 { 1809 struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node); 1810 1811 if (can_goto_child(he, hmd)) 1812 node = rb_first(&he->hroot_out); 1813 else 1814 node = rb_next(node); 1815 1816 while (node == NULL) { 1817 he = he->parent_he; 1818 if (he == NULL) 1819 break; 1820 1821 node = rb_next(&he->rb_node); 1822 } 1823 return node; 1824 } 1825 1826 struct rb_node *rb_hierarchy_prev(struct rb_node *node) 1827 { 1828 struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node); 1829 1830 node = rb_prev(node); 1831 if (node) 1832 return rb_hierarchy_last(node); 1833 1834 he = he->parent_he; 1835 if (he == NULL) 1836 return NULL; 1837 1838 return &he->rb_node; 1839 } 1840 1841 bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit) 1842 { 1843 struct rb_node *node; 1844 struct hist_entry *child; 1845 float percent; 1846 1847 if (he->leaf) 1848 return false; 1849 1850 node = rb_first(&he->hroot_out); 1851 child = rb_entry(node, struct hist_entry, rb_node); 1852 1853 while (node && child->filtered) { 1854 node = rb_next(node); 1855 child = rb_entry(node, struct hist_entry, rb_node); 1856 } 1857 1858 if (node) 1859 percent = hist_entry__get_percent_limit(child); 1860 else 1861 percent = 0; 1862 1863 return node && percent >= limit; 1864 } 1865 1866 static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, 1867 enum hist_filter filter) 1868 { 1869 h->filtered &= ~(1 << filter); 1870 1871 if (symbol_conf.report_hierarchy) { 1872 struct hist_entry *parent = h->parent_he; 1873 1874 while (parent) { 1875 he_stat__add_stat(&parent->stat, &h->stat); 1876 1877 parent->filtered &= ~(1 << filter); 1878 1879 if (parent->filtered) 1880 goto next; 1881 1882 /* force fold unfiltered entry for simplicity */ 1883 parent->unfolded = false; 1884 parent->has_no_entry = false; 1885 parent->row_offset = 0; 1886 parent->nr_rows = 0; 1887 next: 1888 parent = parent->parent_he; 1889 } 1890 } 1891 1892 if (h->filtered) 1893 return; 1894 1895 /* force fold unfiltered entry for simplicity */ 1896 h->unfolded = false; 1897 h->has_no_entry = false; 1898 h->row_offset = 0; 1899 h->nr_rows = 0; 1900 1901 hists->stats.nr_non_filtered_samples += h->stat.nr_events; 1902 1903 hists__inc_filter_stats(hists, h); 1904 hists__calc_col_len(hists, h); 1905 } 1906 1907 1908 static bool hists__filter_entry_by_dso(struct hists *hists, 1909 struct hist_entry *he) 1910 { 1911 if (hists->dso_filter != NULL && 1912 (he->ms.map == NULL || he->ms.map->dso != hists->dso_filter)) { 1913 he->filtered |= (1 << HIST_FILTER__DSO); 1914 return true; 1915 } 1916 1917 return false; 1918 } 1919 1920 static bool hists__filter_entry_by_thread(struct hists *hists, 1921 struct hist_entry *he) 1922 { 1923 if (hists->thread_filter != NULL && 1924 he->thread != hists->thread_filter) { 1925 he->filtered |= (1 << HIST_FILTER__THREAD); 1926 return true; 1927 } 1928 1929 return false; 1930 } 1931 1932 static bool hists__filter_entry_by_symbol(struct hists *hists, 1933 struct hist_entry *he) 1934 { 1935 if (hists->symbol_filter_str != NULL && 1936 (!he->ms.sym || strstr(he->ms.sym->name, 1937 hists->symbol_filter_str) == NULL)) { 1938 he->filtered |= (1 << HIST_FILTER__SYMBOL); 1939 return true; 1940 } 1941 1942 return false; 1943 } 1944 1945 static bool hists__filter_entry_by_socket(struct hists *hists, 1946 struct hist_entry *he) 1947 { 1948 if ((hists->socket_filter > -1) && 1949 (he->socket != hists->socket_filter)) { 1950 he->filtered |= (1 << HIST_FILTER__SOCKET); 1951 return true; 1952 } 1953 1954 return false; 1955 } 1956 1957 typedef bool (*filter_fn_t)(struct hists *hists, struct hist_entry *he); 1958 1959 static void hists__filter_by_type(struct hists *hists, int type, filter_fn_t filter) 1960 { 1961 struct rb_node *nd; 1962 1963 hists->stats.nr_non_filtered_samples = 0; 1964 1965 hists__reset_filter_stats(hists); 1966 hists__reset_col_len(hists); 1967 1968 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 1969 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 1970 1971 if (filter(hists, h)) 1972 continue; 1973 1974 hists__remove_entry_filter(hists, h, type); 1975 } 1976 } 1977 1978 static void resort_filtered_entry(struct rb_root *root, struct hist_entry *he) 1979 { 1980 struct rb_node **p = &root->rb_node; 1981 struct rb_node *parent = NULL; 1982 struct hist_entry *iter; 1983 struct rb_root new_root = RB_ROOT; 1984 struct rb_node *nd; 1985 1986 while (*p != NULL) { 1987 parent = *p; 1988 iter = rb_entry(parent, struct hist_entry, rb_node); 1989 1990 if (hist_entry__sort(he, iter) > 0) 1991 p = &(*p)->rb_left; 1992 else 1993 p = &(*p)->rb_right; 1994 } 1995 1996 rb_link_node(&he->rb_node, parent, p); 1997 rb_insert_color(&he->rb_node, root); 1998 1999 if (he->leaf || he->filtered) 2000 return; 2001 2002 nd = rb_first(&he->hroot_out); 2003 while (nd) { 2004 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 2005 2006 nd = rb_next(nd); 2007 rb_erase(&h->rb_node, &he->hroot_out); 2008 2009 resort_filtered_entry(&new_root, h); 2010 } 2011 2012 he->hroot_out = new_root; 2013 } 2014 2015 static void hists__filter_hierarchy(struct hists *hists, int type, const void *arg) 2016 { 2017 struct rb_node *nd; 2018 struct rb_root new_root = RB_ROOT; 2019 2020 hists->stats.nr_non_filtered_samples = 0; 2021 2022 hists__reset_filter_stats(hists); 2023 hists__reset_col_len(hists); 2024 2025 nd = rb_first(&hists->entries); 2026 while (nd) { 2027 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 2028 int ret; 2029 2030 ret = hist_entry__filter(h, type, arg); 2031 2032 /* 2033 * case 1. non-matching type 2034 * zero out the period, set filter marker and move to child 2035 */ 2036 if (ret < 0) { 2037 memset(&h->stat, 0, sizeof(h->stat)); 2038 h->filtered |= (1 << type); 2039 2040 nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_CHILD); 2041 } 2042 /* 2043 * case 2. matched type (filter out) 2044 * set filter marker and move to next 2045 */ 2046 else if (ret == 1) { 2047 h->filtered |= (1 << type); 2048 2049 nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_SIBLING); 2050 } 2051 /* 2052 * case 3. ok (not filtered) 2053 * add period to hists and parents, erase the filter marker 2054 * and move to next sibling 2055 */ 2056 else { 2057 hists__remove_entry_filter(hists, h, type); 2058 2059 nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_SIBLING); 2060 } 2061 } 2062 2063 hierarchy_recalc_total_periods(hists); 2064 2065 /* 2066 * resort output after applying a new filter since filter in a lower 2067 * hierarchy can change periods in a upper hierarchy. 2068 */ 2069 nd = rb_first(&hists->entries); 2070 while (nd) { 2071 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 2072 2073 nd = rb_next(nd); 2074 rb_erase(&h->rb_node, &hists->entries); 2075 2076 resort_filtered_entry(&new_root, h); 2077 } 2078 2079 hists->entries = new_root; 2080 } 2081 2082 void hists__filter_by_thread(struct hists *hists) 2083 { 2084 if (symbol_conf.report_hierarchy) 2085 hists__filter_hierarchy(hists, HIST_FILTER__THREAD, 2086 hists->thread_filter); 2087 else 2088 hists__filter_by_type(hists, HIST_FILTER__THREAD, 2089 hists__filter_entry_by_thread); 2090 } 2091 2092 void hists__filter_by_dso(struct hists *hists) 2093 { 2094 if (symbol_conf.report_hierarchy) 2095 hists__filter_hierarchy(hists, HIST_FILTER__DSO, 2096 hists->dso_filter); 2097 else 2098 hists__filter_by_type(hists, HIST_FILTER__DSO, 2099 hists__filter_entry_by_dso); 2100 } 2101 2102 void hists__filter_by_symbol(struct hists *hists) 2103 { 2104 if (symbol_conf.report_hierarchy) 2105 hists__filter_hierarchy(hists, HIST_FILTER__SYMBOL, 2106 hists->symbol_filter_str); 2107 else 2108 hists__filter_by_type(hists, HIST_FILTER__SYMBOL, 2109 hists__filter_entry_by_symbol); 2110 } 2111 2112 void hists__filter_by_socket(struct hists *hists) 2113 { 2114 if (symbol_conf.report_hierarchy) 2115 hists__filter_hierarchy(hists, HIST_FILTER__SOCKET, 2116 &hists->socket_filter); 2117 else 2118 hists__filter_by_type(hists, HIST_FILTER__SOCKET, 2119 hists__filter_entry_by_socket); 2120 } 2121 2122 void events_stats__inc(struct events_stats *stats, u32 type) 2123 { 2124 ++stats->nr_events[0]; 2125 ++stats->nr_events[type]; 2126 } 2127 2128 void hists__inc_nr_events(struct hists *hists, u32 type) 2129 { 2130 events_stats__inc(&hists->stats, type); 2131 } 2132 2133 void hists__inc_nr_samples(struct hists *hists, bool filtered) 2134 { 2135 events_stats__inc(&hists->stats, PERF_RECORD_SAMPLE); 2136 if (!filtered) 2137 hists->stats.nr_non_filtered_samples++; 2138 } 2139 2140 static struct hist_entry *hists__add_dummy_entry(struct hists *hists, 2141 struct hist_entry *pair) 2142 { 2143 struct rb_root *root; 2144 struct rb_node **p; 2145 struct rb_node *parent = NULL; 2146 struct hist_entry *he; 2147 int64_t cmp; 2148 2149 if (hists__has(hists, need_collapse)) 2150 root = &hists->entries_collapsed; 2151 else 2152 root = hists->entries_in; 2153 2154 p = &root->rb_node; 2155 2156 while (*p != NULL) { 2157 parent = *p; 2158 he = rb_entry(parent, struct hist_entry, rb_node_in); 2159 2160 cmp = hist_entry__collapse(he, pair); 2161 2162 if (!cmp) 2163 goto out; 2164 2165 if (cmp < 0) 2166 p = &(*p)->rb_left; 2167 else 2168 p = &(*p)->rb_right; 2169 } 2170 2171 he = hist_entry__new(pair, true); 2172 if (he) { 2173 memset(&he->stat, 0, sizeof(he->stat)); 2174 he->hists = hists; 2175 if (symbol_conf.cumulate_callchain) 2176 memset(he->stat_acc, 0, sizeof(he->stat)); 2177 rb_link_node(&he->rb_node_in, parent, p); 2178 rb_insert_color(&he->rb_node_in, root); 2179 hists__inc_stats(hists, he); 2180 he->dummy = true; 2181 } 2182 out: 2183 return he; 2184 } 2185 2186 static struct hist_entry *add_dummy_hierarchy_entry(struct hists *hists, 2187 struct rb_root *root, 2188 struct hist_entry *pair) 2189 { 2190 struct rb_node **p; 2191 struct rb_node *parent = NULL; 2192 struct hist_entry *he; 2193 struct perf_hpp_fmt *fmt; 2194 2195 p = &root->rb_node; 2196 while (*p != NULL) { 2197 int64_t cmp = 0; 2198 2199 parent = *p; 2200 he = rb_entry(parent, struct hist_entry, rb_node_in); 2201 2202 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) { 2203 cmp = fmt->collapse(fmt, he, pair); 2204 if (cmp) 2205 break; 2206 } 2207 if (!cmp) 2208 goto out; 2209 2210 if (cmp < 0) 2211 p = &parent->rb_left; 2212 else 2213 p = &parent->rb_right; 2214 } 2215 2216 he = hist_entry__new(pair, true); 2217 if (he) { 2218 rb_link_node(&he->rb_node_in, parent, p); 2219 rb_insert_color(&he->rb_node_in, root); 2220 2221 he->dummy = true; 2222 he->hists = hists; 2223 memset(&he->stat, 0, sizeof(he->stat)); 2224 hists__inc_stats(hists, he); 2225 } 2226 out: 2227 return he; 2228 } 2229 2230 static struct hist_entry *hists__find_entry(struct hists *hists, 2231 struct hist_entry *he) 2232 { 2233 struct rb_node *n; 2234 2235 if (hists__has(hists, need_collapse)) 2236 n = hists->entries_collapsed.rb_node; 2237 else 2238 n = hists->entries_in->rb_node; 2239 2240 while (n) { 2241 struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in); 2242 int64_t cmp = hist_entry__collapse(iter, he); 2243 2244 if (cmp < 0) 2245 n = n->rb_left; 2246 else if (cmp > 0) 2247 n = n->rb_right; 2248 else 2249 return iter; 2250 } 2251 2252 return NULL; 2253 } 2254 2255 static struct hist_entry *hists__find_hierarchy_entry(struct rb_root *root, 2256 struct hist_entry *he) 2257 { 2258 struct rb_node *n = root->rb_node; 2259 2260 while (n) { 2261 struct hist_entry *iter; 2262 struct perf_hpp_fmt *fmt; 2263 int64_t cmp = 0; 2264 2265 iter = rb_entry(n, struct hist_entry, rb_node_in); 2266 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) { 2267 cmp = fmt->collapse(fmt, iter, he); 2268 if (cmp) 2269 break; 2270 } 2271 2272 if (cmp < 0) 2273 n = n->rb_left; 2274 else if (cmp > 0) 2275 n = n->rb_right; 2276 else 2277 return iter; 2278 } 2279 2280 return NULL; 2281 } 2282 2283 static void hists__match_hierarchy(struct rb_root *leader_root, 2284 struct rb_root *other_root) 2285 { 2286 struct rb_node *nd; 2287 struct hist_entry *pos, *pair; 2288 2289 for (nd = rb_first(leader_root); nd; nd = rb_next(nd)) { 2290 pos = rb_entry(nd, struct hist_entry, rb_node_in); 2291 pair = hists__find_hierarchy_entry(other_root, pos); 2292 2293 if (pair) { 2294 hist_entry__add_pair(pair, pos); 2295 hists__match_hierarchy(&pos->hroot_in, &pair->hroot_in); 2296 } 2297 } 2298 } 2299 2300 /* 2301 * Look for pairs to link to the leader buckets (hist_entries): 2302 */ 2303 void hists__match(struct hists *leader, struct hists *other) 2304 { 2305 struct rb_root *root; 2306 struct rb_node *nd; 2307 struct hist_entry *pos, *pair; 2308 2309 if (symbol_conf.report_hierarchy) { 2310 /* hierarchy report always collapses entries */ 2311 return hists__match_hierarchy(&leader->entries_collapsed, 2312 &other->entries_collapsed); 2313 } 2314 2315 if (hists__has(leader, need_collapse)) 2316 root = &leader->entries_collapsed; 2317 else 2318 root = leader->entries_in; 2319 2320 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 2321 pos = rb_entry(nd, struct hist_entry, rb_node_in); 2322 pair = hists__find_entry(other, pos); 2323 2324 if (pair) 2325 hist_entry__add_pair(pair, pos); 2326 } 2327 } 2328 2329 static int hists__link_hierarchy(struct hists *leader_hists, 2330 struct hist_entry *parent, 2331 struct rb_root *leader_root, 2332 struct rb_root *other_root) 2333 { 2334 struct rb_node *nd; 2335 struct hist_entry *pos, *leader; 2336 2337 for (nd = rb_first(other_root); nd; nd = rb_next(nd)) { 2338 pos = rb_entry(nd, struct hist_entry, rb_node_in); 2339 2340 if (hist_entry__has_pairs(pos)) { 2341 bool found = false; 2342 2343 list_for_each_entry(leader, &pos->pairs.head, pairs.node) { 2344 if (leader->hists == leader_hists) { 2345 found = true; 2346 break; 2347 } 2348 } 2349 if (!found) 2350 return -1; 2351 } else { 2352 leader = add_dummy_hierarchy_entry(leader_hists, 2353 leader_root, pos); 2354 if (leader == NULL) 2355 return -1; 2356 2357 /* do not point parent in the pos */ 2358 leader->parent_he = parent; 2359 2360 hist_entry__add_pair(pos, leader); 2361 } 2362 2363 if (!pos->leaf) { 2364 if (hists__link_hierarchy(leader_hists, leader, 2365 &leader->hroot_in, 2366 &pos->hroot_in) < 0) 2367 return -1; 2368 } 2369 } 2370 return 0; 2371 } 2372 2373 /* 2374 * Look for entries in the other hists that are not present in the leader, if 2375 * we find them, just add a dummy entry on the leader hists, with period=0, 2376 * nr_events=0, to serve as the list header. 2377 */ 2378 int hists__link(struct hists *leader, struct hists *other) 2379 { 2380 struct rb_root *root; 2381 struct rb_node *nd; 2382 struct hist_entry *pos, *pair; 2383 2384 if (symbol_conf.report_hierarchy) { 2385 /* hierarchy report always collapses entries */ 2386 return hists__link_hierarchy(leader, NULL, 2387 &leader->entries_collapsed, 2388 &other->entries_collapsed); 2389 } 2390 2391 if (hists__has(other, need_collapse)) 2392 root = &other->entries_collapsed; 2393 else 2394 root = other->entries_in; 2395 2396 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 2397 pos = rb_entry(nd, struct hist_entry, rb_node_in); 2398 2399 if (!hist_entry__has_pairs(pos)) { 2400 pair = hists__add_dummy_entry(leader, pos); 2401 if (pair == NULL) 2402 return -1; 2403 hist_entry__add_pair(pos, pair); 2404 } 2405 } 2406 2407 return 0; 2408 } 2409 2410 void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, 2411 struct perf_sample *sample, bool nonany_branch_mode) 2412 { 2413 struct branch_info *bi; 2414 2415 /* If we have branch cycles always annotate them. */ 2416 if (bs && bs->nr && bs->entries[0].flags.cycles) { 2417 int i; 2418 2419 bi = sample__resolve_bstack(sample, al); 2420 if (bi) { 2421 struct addr_map_symbol *prev = NULL; 2422 2423 /* 2424 * Ignore errors, still want to process the 2425 * other entries. 2426 * 2427 * For non standard branch modes always 2428 * force no IPC (prev == NULL) 2429 * 2430 * Note that perf stores branches reversed from 2431 * program order! 2432 */ 2433 for (i = bs->nr - 1; i >= 0; i--) { 2434 addr_map_symbol__account_cycles(&bi[i].from, 2435 nonany_branch_mode ? NULL : prev, 2436 bi[i].flags.cycles); 2437 prev = &bi[i].to; 2438 } 2439 free(bi); 2440 } 2441 } 2442 } 2443 2444 size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp) 2445 { 2446 struct perf_evsel *pos; 2447 size_t ret = 0; 2448 2449 evlist__for_each_entry(evlist, pos) { 2450 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); 2451 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); 2452 } 2453 2454 return ret; 2455 } 2456 2457 2458 u64 hists__total_period(struct hists *hists) 2459 { 2460 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 2461 hists->stats.total_period; 2462 } 2463 2464 int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) 2465 { 2466 char unit; 2467 int printed; 2468 const struct dso *dso = hists->dso_filter; 2469 const struct thread *thread = hists->thread_filter; 2470 int socket_id = hists->socket_filter; 2471 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2472 u64 nr_events = hists->stats.total_period; 2473 struct perf_evsel *evsel = hists_to_evsel(hists); 2474 const char *ev_name = perf_evsel__name(evsel); 2475 char buf[512], sample_freq_str[64] = ""; 2476 size_t buflen = sizeof(buf); 2477 char ref[30] = " show reference callgraph, "; 2478 bool enable_ref = false; 2479 2480 if (symbol_conf.filter_relative) { 2481 nr_samples = hists->stats.nr_non_filtered_samples; 2482 nr_events = hists->stats.total_non_filtered_period; 2483 } 2484 2485 if (perf_evsel__is_group_event(evsel)) { 2486 struct perf_evsel *pos; 2487 2488 perf_evsel__group_desc(evsel, buf, buflen); 2489 ev_name = buf; 2490 2491 for_each_group_member(pos, evsel) { 2492 struct hists *pos_hists = evsel__hists(pos); 2493 2494 if (symbol_conf.filter_relative) { 2495 nr_samples += pos_hists->stats.nr_non_filtered_samples; 2496 nr_events += pos_hists->stats.total_non_filtered_period; 2497 } else { 2498 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2499 nr_events += pos_hists->stats.total_period; 2500 } 2501 } 2502 } 2503 2504 if (symbol_conf.show_ref_callgraph && 2505 strstr(ev_name, "call-graph=no")) 2506 enable_ref = true; 2507 2508 if (show_freq) 2509 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); 2510 2511 nr_samples = convert_unit(nr_samples, &unit); 2512 printed = scnprintf(bf, size, 2513 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, 2514 nr_samples, unit, evsel->nr_members > 1 ? "s" : "", 2515 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); 2516 2517 2518 if (hists->uid_filter_str) 2519 printed += snprintf(bf + printed, size - printed, 2520 ", UID: %s", hists->uid_filter_str); 2521 if (thread) { 2522 if (hists__has(hists, thread)) { 2523 printed += scnprintf(bf + printed, size - printed, 2524 ", Thread: %s(%d)", 2525 (thread->comm_set ? thread__comm_str(thread) : ""), 2526 thread->tid); 2527 } else { 2528 printed += scnprintf(bf + printed, size - printed, 2529 ", Thread: %s", 2530 (thread->comm_set ? thread__comm_str(thread) : "")); 2531 } 2532 } 2533 if (dso) 2534 printed += scnprintf(bf + printed, size - printed, 2535 ", DSO: %s", dso->short_name); 2536 if (socket_id > -1) 2537 printed += scnprintf(bf + printed, size - printed, 2538 ", Processor Socket: %d", socket_id); 2539 2540 return printed; 2541 } 2542 2543 int parse_filter_percentage(const struct option *opt __maybe_unused, 2544 const char *arg, int unset __maybe_unused) 2545 { 2546 if (!strcmp(arg, "relative")) 2547 symbol_conf.filter_relative = true; 2548 else if (!strcmp(arg, "absolute")) 2549 symbol_conf.filter_relative = false; 2550 else { 2551 pr_debug("Invalid percentage: %s\n", arg); 2552 return -1; 2553 } 2554 2555 return 0; 2556 } 2557 2558 int perf_hist_config(const char *var, const char *value) 2559 { 2560 if (!strcmp(var, "hist.percentage")) 2561 return parse_filter_percentage(NULL, value, 0); 2562 2563 return 0; 2564 } 2565 2566 int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list) 2567 { 2568 memset(hists, 0, sizeof(*hists)); 2569 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 2570 hists->entries_in = &hists->entries_in_array[0]; 2571 hists->entries_collapsed = RB_ROOT; 2572 hists->entries = RB_ROOT; 2573 pthread_mutex_init(&hists->lock, NULL); 2574 hists->socket_filter = -1; 2575 hists->hpp_list = hpp_list; 2576 INIT_LIST_HEAD(&hists->hpp_formats); 2577 return 0; 2578 } 2579 2580 static void hists__delete_remaining_entries(struct rb_root *root) 2581 { 2582 struct rb_node *node; 2583 struct hist_entry *he; 2584 2585 while (!RB_EMPTY_ROOT(root)) { 2586 node = rb_first(root); 2587 rb_erase(node, root); 2588 2589 he = rb_entry(node, struct hist_entry, rb_node_in); 2590 hist_entry__delete(he); 2591 } 2592 } 2593 2594 static void hists__delete_all_entries(struct hists *hists) 2595 { 2596 hists__delete_entries(hists); 2597 hists__delete_remaining_entries(&hists->entries_in_array[0]); 2598 hists__delete_remaining_entries(&hists->entries_in_array[1]); 2599 hists__delete_remaining_entries(&hists->entries_collapsed); 2600 } 2601 2602 static void hists_evsel__exit(struct perf_evsel *evsel) 2603 { 2604 struct hists *hists = evsel__hists(evsel); 2605 struct perf_hpp_fmt *fmt, *pos; 2606 struct perf_hpp_list_node *node, *tmp; 2607 2608 hists__delete_all_entries(hists); 2609 2610 list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) { 2611 perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) { 2612 list_del(&fmt->list); 2613 free(fmt); 2614 } 2615 list_del(&node->list); 2616 free(node); 2617 } 2618 } 2619 2620 static int hists_evsel__init(struct perf_evsel *evsel) 2621 { 2622 struct hists *hists = evsel__hists(evsel); 2623 2624 __hists__init(hists, &perf_hpp_list); 2625 return 0; 2626 } 2627 2628 /* 2629 * XXX We probably need a hists_evsel__exit() to free the hist_entries 2630 * stored in the rbtree... 2631 */ 2632 2633 int hists__init(void) 2634 { 2635 int err = perf_evsel__object_config(sizeof(struct hists_evsel), 2636 hists_evsel__init, 2637 hists_evsel__exit); 2638 if (err) 2639 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr); 2640 2641 return err; 2642 } 2643 2644 void perf_hpp_list__init(struct perf_hpp_list *list) 2645 { 2646 INIT_LIST_HEAD(&list->fields); 2647 INIT_LIST_HEAD(&list->sorts); 2648 } 2649