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