^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 <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "../util/callchain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "../util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "../util/hist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "../util/sort.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "../util/evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "../util/evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "../perf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* hist period print (hpp) functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define hpp__call_print_fn(hpp, fn, fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int __ret = fn(hpp, fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) advance_hpp(hpp, __ret); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) __ret; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) hpp_field_fn get_field, const char *fmt, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) hpp_snprint_fn print_fn, bool fmt_percent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct hists *hists = he->hists;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct evsel *evsel = hists_to_evsel(hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) char *buf = hpp->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) size_t size = hpp->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (fmt_percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) double percent = 0.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u64 total = hists__total_period(hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (total)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) percent = 100.0 * get_field(he) / total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (evsel__is_group_event(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int prev_idx, idx_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct hist_entry *pair;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int nr_members = evsel->core.nr_members;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) prev_idx = evsel__group_idx(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) list_for_each_entry(pair, &he->pairs.head, pairs.node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u64 period = get_field(pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u64 total = hists__total_period(pair->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!total)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) evsel = hists_to_evsel(pair->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) idx_delta = evsel__group_idx(evsel) - prev_idx - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) while (idx_delta--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * zero-fill group members in the middle which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * have no sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (fmt_percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret += hpp__call_print_fn(hpp, print_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) fmt, len, 0.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ret += hpp__call_print_fn(hpp, print_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) fmt, len, 0ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (fmt_percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ret += hpp__call_print_fn(hpp, print_fn, fmt, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 100.0 * period / total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ret += hpp__call_print_fn(hpp, print_fn, fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) len, period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) prev_idx = evsel__group_idx(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) idx_delta = nr_members - prev_idx - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) while (idx_delta--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * zero-fill group members at last which have no sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (fmt_percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ret += hpp__call_print_fn(hpp, print_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) fmt, len, 0.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ret += hpp__call_print_fn(hpp, print_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) fmt, len, 0ULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Restore original buf and size as it's where caller expects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * the result will be saved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) hpp->buf = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) hpp->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct hist_entry *he, hpp_field_fn get_field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int len = fmt->user_len ?: fmt->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (symbol_conf.field_sep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) print_fn, fmt_percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (fmt_percent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) len -= 2; /* 2 for a space and a % sign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) len -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct hist_entry *he, hpp_field_fn get_field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!symbol_conf.cumulate_callchain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int len = fmt->user_len ?: fmt->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int field_cmp(u64 field_a, u64 field_b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (field_a > field_b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (field_a < field_b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int hist_entry__new_pair(struct hist_entry *a, struct hist_entry *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) hpp_field_fn get_field, int nr_members,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u64 **fields_a, u64 **fields_b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u64 *fa = calloc(nr_members, sizeof(*fa)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *fb = calloc(nr_members, sizeof(*fb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct hist_entry *pair;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!fa || !fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) list_for_each_entry(pair, &a->pairs.head, pairs.node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct evsel *evsel = hists_to_evsel(pair->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) fa[evsel__group_idx(evsel)] = get_field(pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) list_for_each_entry(pair, &b->pairs.head, pairs.node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct evsel *evsel = hists_to_evsel(pair->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) fb[evsel__group_idx(evsel)] = get_field(pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *fields_a = fa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *fields_b = fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) free(fa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) free(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) *fields_a = *fields_b = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int __hpp__group_sort_idx(struct hist_entry *a, struct hist_entry *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) hpp_field_fn get_field, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct evsel *evsel = hists_to_evsel(a->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u64 *fields_a, *fields_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int cmp, nr_members, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) cmp = field_cmp(get_field(a), get_field(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!evsel__is_group_event(evsel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) nr_members = evsel->core.nr_members;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (idx < 1 || idx >= nr_members)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ret = field_cmp(fields_a[idx], fields_b[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) for (i = 1; i < nr_members; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (i != idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = field_cmp(fields_a[i], fields_b[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^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) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) free(fields_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) free(fields_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int __hpp__sort(struct hist_entry *a, struct hist_entry *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) hpp_field_fn get_field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) s64 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int i, nr_members;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u64 *fields_a, *fields_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (symbol_conf.group_sort_idx && symbol_conf.event_group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return __hpp__group_sort_idx(a, b, get_field,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) symbol_conf.group_sort_idx);
^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) ret = field_cmp(get_field(a), get_field(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (ret || !symbol_conf.event_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) evsel = hists_to_evsel(a->hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!evsel__is_group_event(evsel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) nr_members = evsel->core.nr_members;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) i = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for (i = 1; i < nr_members; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ret = field_cmp(fields_a[i], fields_b[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) free(fields_a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) free(fields_b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) hpp_field_fn get_field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) s64 ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (symbol_conf.cumulate_callchain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Put caller above callee when they have equal period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ret = field_cmp(get_field(a), get_field(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (a->thread != b->thread || !hist_entry__has_callchains(a) || !symbol_conf.use_callchain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret = b->callchain->max_depth - a->callchain->max_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (callchain_param.order == ORDER_CALLER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ret = -ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int hpp__width_fn(struct perf_hpp_fmt *fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct perf_hpp *hpp __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct hists *hists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int len = fmt->user_len ?: fmt->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct evsel *evsel = hists_to_evsel(hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (symbol_conf.event_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) len = max(len, evsel->core.nr_members * fmt->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (len < (int)strlen(fmt->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) len = strlen(fmt->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct hists *hists, int line __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int *span __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int len = hpp__width_fn(fmt, hpp, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
^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) int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ssize_t ssize = hpp->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) double percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int ret, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) len = va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) percent = va_arg(args, double);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return (ret >= ssize) ? (ssize - 1) : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static int hpp_entry_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ssize_t ssize = hpp->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ret = vsnprintf(hpp->buf, hpp->size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return (ret >= ssize) ? (ssize - 1) : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #define __HPP_COLOR_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static u64 he_get_##_field(struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return he->stat._field; \
^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) static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct perf_hpp *hpp, struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) hpp_color_scnprintf, true); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) #define __HPP_ENTRY_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct perf_hpp *hpp, struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) hpp_entry_scnprintf, true); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) #define __HPP_SORT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct hist_entry *a, struct hist_entry *b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return __hpp__sort(a, b, he_get_##_field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static u64 he_get_acc_##_field(struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return he->stat_acc->_field; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct perf_hpp *hpp, struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) hpp_color_scnprintf, true); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) #define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct perf_hpp *hpp, struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) hpp_entry_scnprintf, true); \
^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) #define __HPP_SORT_ACC_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct hist_entry *a, struct hist_entry *b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return __hpp__sort_acc(a, b, he_get_acc_##_field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) #define __HPP_ENTRY_RAW_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static u64 he_get_raw_##_field(struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return he->stat._field; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct perf_hpp *hpp, struct hist_entry *he) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) hpp_entry_scnprintf, false); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #define __HPP_SORT_RAW_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct hist_entry *a, struct hist_entry *b) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return __hpp__sort(a, b, he_get_raw_##_field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) #define HPP_PERCENT_FNS(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) __HPP_COLOR_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) __HPP_ENTRY_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) __HPP_SORT_FN(_type, _field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) #define HPP_PERCENT_ACC_FNS(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) __HPP_SORT_ACC_FN(_type, _field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) #define HPP_RAW_FNS(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) __HPP_ENTRY_RAW_FN(_type, _field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) __HPP_SORT_RAW_FN(_type, _field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) HPP_PERCENT_FNS(overhead, period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) HPP_PERCENT_FNS(overhead_sys, period_sys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) HPP_PERCENT_FNS(overhead_us, period_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) HPP_PERCENT_FNS(overhead_guest_us, period_guest_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) HPP_PERCENT_ACC_FNS(overhead_acc, period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) HPP_RAW_FNS(samples, nr_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) HPP_RAW_FNS(period, period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct hist_entry *a __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct hist_entry *b __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return a->header == hpp__header_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static bool hpp__equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!perf_hpp__is_hpp_entry(a) || !perf_hpp__is_hpp_entry(b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return a->idx == b->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) #define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .name = _name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .header = hpp__header_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .width = hpp__width_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .color = hpp__color_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .entry = hpp__entry_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .cmp = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .collapse = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .sort = hpp__sort_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .idx = PERF_HPP__ ## _idx, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .equal = hpp__equal, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) #define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .name = _name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .header = hpp__header_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .width = hpp__width_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .color = hpp__color_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .entry = hpp__entry_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) .cmp = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) .collapse = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) .sort = hpp__sort_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) .idx = PERF_HPP__ ## _idx, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .equal = hpp__equal, \
^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) #define HPP__PRINT_FNS(_name, _fn, _idx) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .name = _name, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .header = hpp__header_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .width = hpp__width_fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) .entry = hpp__entry_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .cmp = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .collapse = hpp__nop_cmp, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .sort = hpp__sort_ ## _fn, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .idx = PERF_HPP__ ## _idx, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .equal = hpp__equal, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct perf_hpp_fmt perf_hpp__format[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) HPP__PRINT_FNS("Samples", samples, SAMPLES),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) HPP__PRINT_FNS("Period", period, PERIOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct perf_hpp_list perf_hpp_list = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .fields = LIST_HEAD_INIT(perf_hpp_list.fields),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .nr_header_lines = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) #undef HPP__COLOR_PRINT_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) #undef HPP__COLOR_ACC_PRINT_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #undef HPP__PRINT_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) #undef HPP_PERCENT_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) #undef HPP_PERCENT_ACC_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) #undef HPP_RAW_FNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) #undef __HPP_HEADER_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) #undef __HPP_WIDTH_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #undef __HPP_COLOR_PERCENT_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) #undef __HPP_ENTRY_PERCENT_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #undef __HPP_COLOR_ACC_PERCENT_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #undef __HPP_ENTRY_ACC_PERCENT_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) #undef __HPP_ENTRY_RAW_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) #undef __HPP_SORT_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #undef __HPP_SORT_ACC_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) #undef __HPP_SORT_RAW_FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void fmt_free(struct perf_hpp_fmt *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * At this point fmt should be completely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * unhooked, if not it's a bug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) BUG_ON(!list_empty(&fmt->list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) BUG_ON(!list_empty(&fmt->sort_list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (fmt->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) fmt->free(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) void perf_hpp__init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct perf_hpp_fmt *fmt = &perf_hpp__format[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) INIT_LIST_HEAD(&fmt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* sort_list may be linked by setup_sorting() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (fmt->sort_list.next == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) INIT_LIST_HEAD(&fmt->sort_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * If user specified field order, no need to setup default fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (is_strict_order(field_order))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (symbol_conf.cumulate_callchain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) hpp_dimension__add_output(PERF_HPP__OVERHEAD_ACC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) hpp_dimension__add_output(PERF_HPP__OVERHEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (symbol_conf.show_cpu_utilization) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) hpp_dimension__add_output(PERF_HPP__OVERHEAD_SYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) hpp_dimension__add_output(PERF_HPP__OVERHEAD_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (perf_guest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_SYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (symbol_conf.show_nr_samples)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) hpp_dimension__add_output(PERF_HPP__SAMPLES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (symbol_conf.show_total_period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) hpp_dimension__add_output(PERF_HPP__PERIOD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) void perf_hpp_list__column_register(struct perf_hpp_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct perf_hpp_fmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) list_add_tail(&format->list, &list->fields);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct perf_hpp_fmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) list_add_tail(&format->sort_list, &list->sorts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct perf_hpp_fmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) list_add(&format->sort_list, &list->sorts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) list_del_init(&format->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) fmt_free(format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) void perf_hpp__cancel_cumulate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (is_strict_order(field_order))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ovh = &perf_hpp__format[PERF_HPP__OVERHEAD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (acc->equal(acc, fmt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) perf_hpp__column_unregister(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) continue;
^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 (ovh->equal(ovh, fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) fmt->name = "Overhead";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return a->equal && a->equal(a, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) void perf_hpp__setup_output_field(struct perf_hpp_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* append sort keys to output field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) perf_hpp_list__for_each_sort_list(list, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct perf_hpp_fmt *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* skip sort-only fields ("sort_compute" in perf diff) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (!fmt->entry && !fmt->color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) perf_hpp_list__for_each_format(list, pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (fmt_equal(fmt, pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) perf_hpp__column_register(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) void perf_hpp__append_sort_keys(struct perf_hpp_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* append output fields to sort keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) perf_hpp_list__for_each_format(list, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct perf_hpp_fmt *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) perf_hpp_list__for_each_sort_list(list, pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (fmt_equal(fmt, pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) perf_hpp__register_sort_field(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) void perf_hpp__reset_output_field(struct perf_hpp_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct perf_hpp_fmt *fmt, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* reset output fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) perf_hpp_list__for_each_format_safe(list, fmt, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) list_del_init(&fmt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) list_del_init(&fmt->sort_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) fmt_free(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* reset sort keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) list_del_init(&fmt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) list_del_init(&fmt->sort_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) fmt_free(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * See hists__fprintf to match the column widths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) unsigned int hists__sort_list_width(struct hists *hists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct perf_hpp dummy_hpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) hists__for_each_format(hists, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (perf_hpp__should_skip(fmt, hists))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ret += fmt->width(fmt, &dummy_hpp, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (verbose > 0 && hists__has(hists, sym)) /* Addr + origin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) ret += 3 + BITS_PER_LONG / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) unsigned int hists__overhead_width(struct hists *hists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) struct perf_hpp dummy_hpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) hists__for_each_format(hists, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (perf_hpp__is_sort_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ret += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ret += fmt->width(fmt, &dummy_hpp, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (perf_hpp__is_sort_entry(fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return perf_hpp__reset_sort_width(fmt, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (perf_hpp__is_dynamic_entry(fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) BUG_ON(fmt->idx >= PERF_HPP__MAX_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) switch (fmt->idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) case PERF_HPP__OVERHEAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) case PERF_HPP__OVERHEAD_SYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case PERF_HPP__OVERHEAD_US:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case PERF_HPP__OVERHEAD_ACC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) fmt->len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case PERF_HPP__OVERHEAD_GUEST_SYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case PERF_HPP__OVERHEAD_GUEST_US:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) fmt->len = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case PERF_HPP__SAMPLES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case PERF_HPP__PERIOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) fmt->len = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) void hists__reset_column_width(struct hists *hists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct perf_hpp_list_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) hists__for_each_format(hists, fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) perf_hpp__reset_width(fmt, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* hierarchy entries have their own hpp list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) list_for_each_entry(node, &hists->hpp_formats, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) perf_hpp_list__for_each_format(&node->hpp, fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) perf_hpp__reset_width(fmt, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) void perf_hpp__set_user_width(const char *width_list_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) const char *ptr = width_list_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int len = strtol(ptr, &p, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) fmt->user_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) if (*p == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) ptr = p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct perf_hpp_list_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct perf_hpp_fmt *fmt_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) bool skip = perf_hpp__should_skip(fmt, hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) list_for_each_entry(node, &hists->hpp_formats, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (node->level == fmt->level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) node = malloc(sizeof(*node));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (node == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) node->skip = skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) node->level = fmt->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) perf_hpp_list__init(&node->hpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) hists->nr_hpp_node++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) list_add_tail(&node->list, &hists->hpp_formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) fmt_copy = perf_hpp_fmt__dup(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (fmt_copy == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!skip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) node->skip = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) list_add_tail(&fmt_copy->list, &node->hpp.fields);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct evlist *evlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct perf_hpp_fmt *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct hists *hists;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (!symbol_conf.report_hierarchy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) hists = evsel__hists(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) perf_hpp_list__for_each_sort_list(list, fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (perf_hpp__is_dynamic_entry(fmt) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) !perf_hpp__defined_dynamic_entry(fmt, hists))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) ret = add_hierarchy_fmt(hists, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }