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