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