162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <inttypes.h> 362306a36Sopenharmony_ci#include <math.h> 462306a36Sopenharmony_ci#include <stdlib.h> 562306a36Sopenharmony_ci#include <string.h> 662306a36Sopenharmony_ci#include <linux/compiler.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "../util/callchain.h" 962306a36Sopenharmony_ci#include "../util/debug.h" 1062306a36Sopenharmony_ci#include "../util/hist.h" 1162306a36Sopenharmony_ci#include "../util/sort.h" 1262306a36Sopenharmony_ci#include "../util/evsel.h" 1362306a36Sopenharmony_ci#include "../util/evlist.h" 1462306a36Sopenharmony_ci#include "../util/thread.h" 1562306a36Sopenharmony_ci#include "../util/util.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* hist period print (hpp) functions */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define hpp__call_print_fn(hpp, fn, fmt, ...) \ 2062306a36Sopenharmony_ci({ \ 2162306a36Sopenharmony_ci int __ret = fn(hpp, fmt, ##__VA_ARGS__); \ 2262306a36Sopenharmony_ci advance_hpp(hpp, __ret); \ 2362306a36Sopenharmony_ci __ret; \ 2462306a36Sopenharmony_ci}) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 2762306a36Sopenharmony_ci hpp_field_fn get_field, const char *fmt, int len, 2862306a36Sopenharmony_ci hpp_snprint_fn print_fn, bool fmt_percent) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci int ret; 3162306a36Sopenharmony_ci struct hists *hists = he->hists; 3262306a36Sopenharmony_ci struct evsel *evsel = hists_to_evsel(hists); 3362306a36Sopenharmony_ci char *buf = hpp->buf; 3462306a36Sopenharmony_ci size_t size = hpp->size; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (fmt_percent) { 3762306a36Sopenharmony_ci double percent = 0.0; 3862306a36Sopenharmony_ci u64 total = hists__total_period(hists); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (total) 4162306a36Sopenharmony_ci percent = 100.0 * get_field(he) / total; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent); 4462306a36Sopenharmony_ci } else 4562306a36Sopenharmony_ci ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he)); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (evsel__is_group_event(evsel)) { 4862306a36Sopenharmony_ci int prev_idx, idx_delta; 4962306a36Sopenharmony_ci struct hist_entry *pair; 5062306a36Sopenharmony_ci int nr_members = evsel->core.nr_members; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci prev_idx = evsel__group_idx(evsel); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci list_for_each_entry(pair, &he->pairs.head, pairs.node) { 5562306a36Sopenharmony_ci u64 period = get_field(pair); 5662306a36Sopenharmony_ci u64 total = hists__total_period(pair->hists); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (!total) 5962306a36Sopenharmony_ci continue; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci evsel = hists_to_evsel(pair->hists); 6262306a36Sopenharmony_ci idx_delta = evsel__group_idx(evsel) - prev_idx - 1; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci while (idx_delta--) { 6562306a36Sopenharmony_ci /* 6662306a36Sopenharmony_ci * zero-fill group members in the middle which 6762306a36Sopenharmony_ci * have no sample 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci if (fmt_percent) { 7062306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, 7162306a36Sopenharmony_ci fmt, len, 0.0); 7262306a36Sopenharmony_ci } else { 7362306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, 7462306a36Sopenharmony_ci fmt, len, 0ULL); 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (fmt_percent) { 7962306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, fmt, len, 8062306a36Sopenharmony_ci 100.0 * period / total); 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, fmt, 8362306a36Sopenharmony_ci len, period); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci prev_idx = evsel__group_idx(evsel); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci idx_delta = nr_members - prev_idx - 1; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci while (idx_delta--) { 9262306a36Sopenharmony_ci /* 9362306a36Sopenharmony_ci * zero-fill group members at last which have no sample 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci if (fmt_percent) { 9662306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, 9762306a36Sopenharmony_ci fmt, len, 0.0); 9862306a36Sopenharmony_ci } else { 9962306a36Sopenharmony_ci ret += hpp__call_print_fn(hpp, print_fn, 10062306a36Sopenharmony_ci fmt, len, 0ULL); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* 10662306a36Sopenharmony_ci * Restore original buf and size as it's where caller expects 10762306a36Sopenharmony_ci * the result will be saved. 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ci hpp->buf = buf; 11062306a36Sopenharmony_ci hpp->size = size; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return ret; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 11662306a36Sopenharmony_ci struct hist_entry *he, hpp_field_fn get_field, 11762306a36Sopenharmony_ci const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci int len = fmt->user_len ?: fmt->len; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (symbol_conf.field_sep) { 12262306a36Sopenharmony_ci return __hpp__fmt(hpp, he, get_field, fmtstr, 1, 12362306a36Sopenharmony_ci print_fn, fmt_percent); 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (fmt_percent) 12762306a36Sopenharmony_ci len -= 2; /* 2 for a space and a % sign */ 12862306a36Sopenharmony_ci else 12962306a36Sopenharmony_ci len -= 1; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ciint hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 13562306a36Sopenharmony_ci struct hist_entry *he, hpp_field_fn get_field, 13662306a36Sopenharmony_ci const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci if (!symbol_conf.cumulate_callchain) { 13962306a36Sopenharmony_ci int len = fmt->user_len ?: fmt->len; 14062306a36Sopenharmony_ci return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A"); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int field_cmp(u64 field_a, u64 field_b) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if (field_a > field_b) 14962306a36Sopenharmony_ci return 1; 15062306a36Sopenharmony_ci if (field_a < field_b) 15162306a36Sopenharmony_ci return -1; 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int hist_entry__new_pair(struct hist_entry *a, struct hist_entry *b, 15662306a36Sopenharmony_ci hpp_field_fn get_field, int nr_members, 15762306a36Sopenharmony_ci u64 **fields_a, u64 **fields_b) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci u64 *fa = calloc(nr_members, sizeof(*fa)), 16062306a36Sopenharmony_ci *fb = calloc(nr_members, sizeof(*fb)); 16162306a36Sopenharmony_ci struct hist_entry *pair; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (!fa || !fb) 16462306a36Sopenharmony_ci goto out_free; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci list_for_each_entry(pair, &a->pairs.head, pairs.node) { 16762306a36Sopenharmony_ci struct evsel *evsel = hists_to_evsel(pair->hists); 16862306a36Sopenharmony_ci fa[evsel__group_idx(evsel)] = get_field(pair); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci list_for_each_entry(pair, &b->pairs.head, pairs.node) { 17262306a36Sopenharmony_ci struct evsel *evsel = hists_to_evsel(pair->hists); 17362306a36Sopenharmony_ci fb[evsel__group_idx(evsel)] = get_field(pair); 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci *fields_a = fa; 17762306a36Sopenharmony_ci *fields_b = fb; 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ciout_free: 18062306a36Sopenharmony_ci free(fa); 18162306a36Sopenharmony_ci free(fb); 18262306a36Sopenharmony_ci *fields_a = *fields_b = NULL; 18362306a36Sopenharmony_ci return -1; 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic int __hpp__group_sort_idx(struct hist_entry *a, struct hist_entry *b, 18762306a36Sopenharmony_ci hpp_field_fn get_field, int idx) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct evsel *evsel = hists_to_evsel(a->hists); 19062306a36Sopenharmony_ci u64 *fields_a, *fields_b; 19162306a36Sopenharmony_ci int cmp, nr_members, ret, i; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci cmp = field_cmp(get_field(a), get_field(b)); 19462306a36Sopenharmony_ci if (!evsel__is_group_event(evsel)) 19562306a36Sopenharmony_ci return cmp; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci nr_members = evsel->core.nr_members; 19862306a36Sopenharmony_ci if (idx < 1 || idx >= nr_members) 19962306a36Sopenharmony_ci return cmp; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ret = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b); 20262306a36Sopenharmony_ci if (ret) { 20362306a36Sopenharmony_ci ret = cmp; 20462306a36Sopenharmony_ci goto out; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ret = field_cmp(fields_a[idx], fields_b[idx]); 20862306a36Sopenharmony_ci if (ret) 20962306a36Sopenharmony_ci goto out; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci for (i = 1; i < nr_members; i++) { 21262306a36Sopenharmony_ci if (i != idx) { 21362306a36Sopenharmony_ci ret = field_cmp(fields_a[i], fields_b[i]); 21462306a36Sopenharmony_ci if (ret) 21562306a36Sopenharmony_ci goto out; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciout: 22062306a36Sopenharmony_ci free(fields_a); 22162306a36Sopenharmony_ci free(fields_b); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return ret; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int __hpp__sort(struct hist_entry *a, struct hist_entry *b, 22762306a36Sopenharmony_ci hpp_field_fn get_field) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci s64 ret; 23062306a36Sopenharmony_ci int i, nr_members; 23162306a36Sopenharmony_ci struct evsel *evsel; 23262306a36Sopenharmony_ci u64 *fields_a, *fields_b; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (symbol_conf.group_sort_idx && symbol_conf.event_group) { 23562306a36Sopenharmony_ci return __hpp__group_sort_idx(a, b, get_field, 23662306a36Sopenharmony_ci symbol_conf.group_sort_idx); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci ret = field_cmp(get_field(a), get_field(b)); 24062306a36Sopenharmony_ci if (ret || !symbol_conf.event_group) 24162306a36Sopenharmony_ci return ret; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci evsel = hists_to_evsel(a->hists); 24462306a36Sopenharmony_ci if (!evsel__is_group_event(evsel)) 24562306a36Sopenharmony_ci return ret; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci nr_members = evsel->core.nr_members; 24862306a36Sopenharmony_ci i = hist_entry__new_pair(a, b, get_field, nr_members, &fields_a, &fields_b); 24962306a36Sopenharmony_ci if (i) 25062306a36Sopenharmony_ci goto out; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci for (i = 1; i < nr_members; i++) { 25362306a36Sopenharmony_ci ret = field_cmp(fields_a[i], fields_b[i]); 25462306a36Sopenharmony_ci if (ret) 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ciout: 25962306a36Sopenharmony_ci free(fields_a); 26062306a36Sopenharmony_ci free(fields_b); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci return ret; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, 26662306a36Sopenharmony_ci hpp_field_fn get_field) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci s64 ret = 0; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (symbol_conf.cumulate_callchain) { 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * Put caller above callee when they have equal period. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_ci ret = field_cmp(get_field(a), get_field(b)); 27562306a36Sopenharmony_ci if (ret) 27662306a36Sopenharmony_ci return ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if ((a->thread == NULL ? NULL : RC_CHK_ACCESS(a->thread)) != 27962306a36Sopenharmony_ci (b->thread == NULL ? NULL : RC_CHK_ACCESS(b->thread)) || 28062306a36Sopenharmony_ci !hist_entry__has_callchains(a) || !symbol_conf.use_callchain) 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci ret = b->callchain->max_depth - a->callchain->max_depth; 28462306a36Sopenharmony_ci if (callchain_param.order == ORDER_CALLER) 28562306a36Sopenharmony_ci ret = -ret; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci return ret; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int hpp__width_fn(struct perf_hpp_fmt *fmt, 29162306a36Sopenharmony_ci struct perf_hpp *hpp __maybe_unused, 29262306a36Sopenharmony_ci struct hists *hists) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci int len = fmt->user_len ?: fmt->len; 29562306a36Sopenharmony_ci struct evsel *evsel = hists_to_evsel(hists); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (symbol_conf.event_group) 29862306a36Sopenharmony_ci len = max(len, evsel->core.nr_members * fmt->len); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (len < (int)strlen(fmt->name)) 30162306a36Sopenharmony_ci len = strlen(fmt->name); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return len; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 30762306a36Sopenharmony_ci struct hists *hists, int line __maybe_unused, 30862306a36Sopenharmony_ci int *span __maybe_unused) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci int len = hpp__width_fn(fmt, hpp, hists); 31162306a36Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciint hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci va_list args; 31762306a36Sopenharmony_ci ssize_t ssize = hpp->size; 31862306a36Sopenharmony_ci double percent; 31962306a36Sopenharmony_ci int ret, len; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci va_start(args, fmt); 32262306a36Sopenharmony_ci len = va_arg(args, int); 32362306a36Sopenharmony_ci percent = va_arg(args, double); 32462306a36Sopenharmony_ci ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent); 32562306a36Sopenharmony_ci va_end(args); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return (ret >= ssize) ? (ssize - 1) : ret; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int hpp_entry_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci va_list args; 33362306a36Sopenharmony_ci ssize_t ssize = hpp->size; 33462306a36Sopenharmony_ci int ret; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci va_start(args, fmt); 33762306a36Sopenharmony_ci ret = vsnprintf(hpp->buf, hpp->size, fmt, args); 33862306a36Sopenharmony_ci va_end(args); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci return (ret >= ssize) ? (ssize - 1) : ret; 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci#define __HPP_COLOR_PERCENT_FN(_type, _field) \ 34462306a36Sopenharmony_cistatic u64 he_get_##_field(struct hist_entry *he) \ 34562306a36Sopenharmony_ci{ \ 34662306a36Sopenharmony_ci return he->stat._field; \ 34762306a36Sopenharmony_ci} \ 34862306a36Sopenharmony_ci \ 34962306a36Sopenharmony_cistatic int hpp__color_##_type(struct perf_hpp_fmt *fmt, \ 35062306a36Sopenharmony_ci struct perf_hpp *hpp, struct hist_entry *he) \ 35162306a36Sopenharmony_ci{ \ 35262306a36Sopenharmony_ci return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \ 35362306a36Sopenharmony_ci hpp_color_scnprintf, true); \ 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 35762306a36Sopenharmony_cistatic int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ 35862306a36Sopenharmony_ci struct perf_hpp *hpp, struct hist_entry *he) \ 35962306a36Sopenharmony_ci{ \ 36062306a36Sopenharmony_ci return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \ 36162306a36Sopenharmony_ci hpp_entry_scnprintf, true); \ 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci#define __HPP_SORT_FN(_type, _field) \ 36562306a36Sopenharmony_cistatic int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 36662306a36Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) \ 36762306a36Sopenharmony_ci{ \ 36862306a36Sopenharmony_ci return __hpp__sort(a, b, he_get_##_field); \ 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 37262306a36Sopenharmony_cistatic u64 he_get_acc_##_field(struct hist_entry *he) \ 37362306a36Sopenharmony_ci{ \ 37462306a36Sopenharmony_ci return he->stat_acc->_field; \ 37562306a36Sopenharmony_ci} \ 37662306a36Sopenharmony_ci \ 37762306a36Sopenharmony_cistatic int hpp__color_##_type(struct perf_hpp_fmt *fmt, \ 37862306a36Sopenharmony_ci struct perf_hpp *hpp, struct hist_entry *he) \ 37962306a36Sopenharmony_ci{ \ 38062306a36Sopenharmony_ci return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \ 38162306a36Sopenharmony_ci hpp_color_scnprintf, true); \ 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 38562306a36Sopenharmony_cistatic int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ 38662306a36Sopenharmony_ci struct perf_hpp *hpp, struct hist_entry *he) \ 38762306a36Sopenharmony_ci{ \ 38862306a36Sopenharmony_ci return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \ 38962306a36Sopenharmony_ci hpp_entry_scnprintf, true); \ 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci#define __HPP_SORT_ACC_FN(_type, _field) \ 39362306a36Sopenharmony_cistatic int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 39462306a36Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) \ 39562306a36Sopenharmony_ci{ \ 39662306a36Sopenharmony_ci return __hpp__sort_acc(a, b, he_get_acc_##_field); \ 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci#define __HPP_ENTRY_RAW_FN(_type, _field) \ 40062306a36Sopenharmony_cistatic u64 he_get_raw_##_field(struct hist_entry *he) \ 40162306a36Sopenharmony_ci{ \ 40262306a36Sopenharmony_ci return he->stat._field; \ 40362306a36Sopenharmony_ci} \ 40462306a36Sopenharmony_ci \ 40562306a36Sopenharmony_cistatic int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ 40662306a36Sopenharmony_ci struct perf_hpp *hpp, struct hist_entry *he) \ 40762306a36Sopenharmony_ci{ \ 40862306a36Sopenharmony_ci return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \ 40962306a36Sopenharmony_ci hpp_entry_scnprintf, false); \ 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci#define __HPP_SORT_RAW_FN(_type, _field) \ 41362306a36Sopenharmony_cistatic int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 41462306a36Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) \ 41562306a36Sopenharmony_ci{ \ 41662306a36Sopenharmony_ci return __hpp__sort(a, b, he_get_raw_##_field); \ 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci#define HPP_PERCENT_FNS(_type, _field) \ 42162306a36Sopenharmony_ci__HPP_COLOR_PERCENT_FN(_type, _field) \ 42262306a36Sopenharmony_ci__HPP_ENTRY_PERCENT_FN(_type, _field) \ 42362306a36Sopenharmony_ci__HPP_SORT_FN(_type, _field) 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci#define HPP_PERCENT_ACC_FNS(_type, _field) \ 42662306a36Sopenharmony_ci__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 42762306a36Sopenharmony_ci__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 42862306a36Sopenharmony_ci__HPP_SORT_ACC_FN(_type, _field) 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci#define HPP_RAW_FNS(_type, _field) \ 43162306a36Sopenharmony_ci__HPP_ENTRY_RAW_FN(_type, _field) \ 43262306a36Sopenharmony_ci__HPP_SORT_RAW_FN(_type, _field) 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ciHPP_PERCENT_FNS(overhead, period) 43562306a36Sopenharmony_ciHPP_PERCENT_FNS(overhead_sys, period_sys) 43662306a36Sopenharmony_ciHPP_PERCENT_FNS(overhead_us, period_us) 43762306a36Sopenharmony_ciHPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys) 43862306a36Sopenharmony_ciHPP_PERCENT_FNS(overhead_guest_us, period_guest_us) 43962306a36Sopenharmony_ciHPP_PERCENT_ACC_FNS(overhead_acc, period) 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ciHPP_RAW_FNS(samples, nr_events) 44262306a36Sopenharmony_ciHPP_RAW_FNS(period, period) 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 44562306a36Sopenharmony_ci struct hist_entry *a __maybe_unused, 44662306a36Sopenharmony_ci struct hist_entry *b __maybe_unused) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci return a->header == hpp__header_fn; 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic bool hpp__equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci if (!perf_hpp__is_hpp_entry(a) || !perf_hpp__is_hpp_entry(b)) 45962306a36Sopenharmony_ci return false; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return a->idx == b->idx; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci#define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \ 46562306a36Sopenharmony_ci { \ 46662306a36Sopenharmony_ci .name = _name, \ 46762306a36Sopenharmony_ci .header = hpp__header_fn, \ 46862306a36Sopenharmony_ci .width = hpp__width_fn, \ 46962306a36Sopenharmony_ci .color = hpp__color_ ## _fn, \ 47062306a36Sopenharmony_ci .entry = hpp__entry_ ## _fn, \ 47162306a36Sopenharmony_ci .cmp = hpp__nop_cmp, \ 47262306a36Sopenharmony_ci .collapse = hpp__nop_cmp, \ 47362306a36Sopenharmony_ci .sort = hpp__sort_ ## _fn, \ 47462306a36Sopenharmony_ci .idx = PERF_HPP__ ## _idx, \ 47562306a36Sopenharmony_ci .equal = hpp__equal, \ 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \ 47962306a36Sopenharmony_ci { \ 48062306a36Sopenharmony_ci .name = _name, \ 48162306a36Sopenharmony_ci .header = hpp__header_fn, \ 48262306a36Sopenharmony_ci .width = hpp__width_fn, \ 48362306a36Sopenharmony_ci .color = hpp__color_ ## _fn, \ 48462306a36Sopenharmony_ci .entry = hpp__entry_ ## _fn, \ 48562306a36Sopenharmony_ci .cmp = hpp__nop_cmp, \ 48662306a36Sopenharmony_ci .collapse = hpp__nop_cmp, \ 48762306a36Sopenharmony_ci .sort = hpp__sort_ ## _fn, \ 48862306a36Sopenharmony_ci .idx = PERF_HPP__ ## _idx, \ 48962306a36Sopenharmony_ci .equal = hpp__equal, \ 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci#define HPP__PRINT_FNS(_name, _fn, _idx) \ 49362306a36Sopenharmony_ci { \ 49462306a36Sopenharmony_ci .name = _name, \ 49562306a36Sopenharmony_ci .header = hpp__header_fn, \ 49662306a36Sopenharmony_ci .width = hpp__width_fn, \ 49762306a36Sopenharmony_ci .entry = hpp__entry_ ## _fn, \ 49862306a36Sopenharmony_ci .cmp = hpp__nop_cmp, \ 49962306a36Sopenharmony_ci .collapse = hpp__nop_cmp, \ 50062306a36Sopenharmony_ci .sort = hpp__sort_ ## _fn, \ 50162306a36Sopenharmony_ci .idx = PERF_HPP__ ## _idx, \ 50262306a36Sopenharmony_ci .equal = hpp__equal, \ 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistruct perf_hpp_fmt perf_hpp__format[] = { 50662306a36Sopenharmony_ci HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD), 50762306a36Sopenharmony_ci HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS), 50862306a36Sopenharmony_ci HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US), 50962306a36Sopenharmony_ci HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS), 51062306a36Sopenharmony_ci HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US), 51162306a36Sopenharmony_ci HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC), 51262306a36Sopenharmony_ci HPP__PRINT_FNS("Samples", samples, SAMPLES), 51362306a36Sopenharmony_ci HPP__PRINT_FNS("Period", period, PERIOD) 51462306a36Sopenharmony_ci}; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistruct perf_hpp_list perf_hpp_list = { 51762306a36Sopenharmony_ci .fields = LIST_HEAD_INIT(perf_hpp_list.fields), 51862306a36Sopenharmony_ci .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), 51962306a36Sopenharmony_ci .nr_header_lines = 1, 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci#undef HPP__COLOR_PRINT_FNS 52362306a36Sopenharmony_ci#undef HPP__COLOR_ACC_PRINT_FNS 52462306a36Sopenharmony_ci#undef HPP__PRINT_FNS 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci#undef HPP_PERCENT_FNS 52762306a36Sopenharmony_ci#undef HPP_PERCENT_ACC_FNS 52862306a36Sopenharmony_ci#undef HPP_RAW_FNS 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci#undef __HPP_HEADER_FN 53162306a36Sopenharmony_ci#undef __HPP_WIDTH_FN 53262306a36Sopenharmony_ci#undef __HPP_COLOR_PERCENT_FN 53362306a36Sopenharmony_ci#undef __HPP_ENTRY_PERCENT_FN 53462306a36Sopenharmony_ci#undef __HPP_COLOR_ACC_PERCENT_FN 53562306a36Sopenharmony_ci#undef __HPP_ENTRY_ACC_PERCENT_FN 53662306a36Sopenharmony_ci#undef __HPP_ENTRY_RAW_FN 53762306a36Sopenharmony_ci#undef __HPP_SORT_FN 53862306a36Sopenharmony_ci#undef __HPP_SORT_ACC_FN 53962306a36Sopenharmony_ci#undef __HPP_SORT_RAW_FN 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic void fmt_free(struct perf_hpp_fmt *fmt) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci /* 54462306a36Sopenharmony_ci * At this point fmt should be completely 54562306a36Sopenharmony_ci * unhooked, if not it's a bug. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ci BUG_ON(!list_empty(&fmt->list)); 54862306a36Sopenharmony_ci BUG_ON(!list_empty(&fmt->sort_list)); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (fmt->free) 55162306a36Sopenharmony_ci fmt->free(fmt); 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_civoid perf_hpp__init(void) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci int i; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 55962306a36Sopenharmony_ci struct perf_hpp_fmt *fmt = &perf_hpp__format[i]; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci INIT_LIST_HEAD(&fmt->list); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* sort_list may be linked by setup_sorting() */ 56462306a36Sopenharmony_ci if (fmt->sort_list.next == NULL) 56562306a36Sopenharmony_ci INIT_LIST_HEAD(&fmt->sort_list); 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* 56962306a36Sopenharmony_ci * If user specified field order, no need to setup default fields. 57062306a36Sopenharmony_ci */ 57162306a36Sopenharmony_ci if (is_strict_order(field_order)) 57262306a36Sopenharmony_ci return; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (symbol_conf.cumulate_callchain) { 57562306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD_ACC); 57662306a36Sopenharmony_ci perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self"; 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (symbol_conf.show_cpu_utilization) { 58262306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD_SYS); 58362306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD_US); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (perf_guest) { 58662306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_SYS); 58762306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_US); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci } 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (symbol_conf.show_nr_samples) 59262306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__SAMPLES); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (symbol_conf.show_total_period) 59562306a36Sopenharmony_ci hpp_dimension__add_output(PERF_HPP__PERIOD); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_civoid perf_hpp_list__column_register(struct perf_hpp_list *list, 59962306a36Sopenharmony_ci struct perf_hpp_fmt *format) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci list_add_tail(&format->list, &list->fields); 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_civoid perf_hpp_list__register_sort_field(struct perf_hpp_list *list, 60562306a36Sopenharmony_ci struct perf_hpp_fmt *format) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci list_add_tail(&format->sort_list, &list->sorts); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_civoid perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, 61162306a36Sopenharmony_ci struct perf_hpp_fmt *format) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci list_add(&format->sort_list, &list->sorts); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic void perf_hpp__column_unregister(struct perf_hpp_fmt *format) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci list_del_init(&format->list); 61962306a36Sopenharmony_ci fmt_free(format); 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_civoid perf_hpp__cancel_cumulate(void) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (is_strict_order(field_order)) 62762306a36Sopenharmony_ci return; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; 63062306a36Sopenharmony_ci acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { 63362306a36Sopenharmony_ci if (acc->equal(acc, fmt)) { 63462306a36Sopenharmony_ci perf_hpp__column_unregister(fmt); 63562306a36Sopenharmony_ci continue; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci if (ovh->equal(ovh, fmt)) 63962306a36Sopenharmony_ci fmt->name = "Overhead"; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci return a->equal && a->equal(a, b); 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_civoid perf_hpp__setup_output_field(struct perf_hpp_list *list) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /* append sort keys to output field */ 65362306a36Sopenharmony_ci perf_hpp_list__for_each_sort_list(list, fmt) { 65462306a36Sopenharmony_ci struct perf_hpp_fmt *pos; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* skip sort-only fields ("sort_compute" in perf diff) */ 65762306a36Sopenharmony_ci if (!fmt->entry && !fmt->color) 65862306a36Sopenharmony_ci continue; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci perf_hpp_list__for_each_format(list, pos) { 66162306a36Sopenharmony_ci if (fmt_equal(fmt, pos)) 66262306a36Sopenharmony_ci goto next; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci perf_hpp__column_register(fmt); 66662306a36Sopenharmony_cinext: 66762306a36Sopenharmony_ci continue; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_civoid perf_hpp__append_sort_keys(struct perf_hpp_list *list) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* append output fields to sort keys */ 67662306a36Sopenharmony_ci perf_hpp_list__for_each_format(list, fmt) { 67762306a36Sopenharmony_ci struct perf_hpp_fmt *pos; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci perf_hpp_list__for_each_sort_list(list, pos) { 68062306a36Sopenharmony_ci if (fmt_equal(fmt, pos)) 68162306a36Sopenharmony_ci goto next; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci perf_hpp__register_sort_field(fmt); 68562306a36Sopenharmony_cinext: 68662306a36Sopenharmony_ci continue; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_civoid perf_hpp__reset_output_field(struct perf_hpp_list *list) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci struct perf_hpp_fmt *fmt, *tmp; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* reset output fields */ 69662306a36Sopenharmony_ci perf_hpp_list__for_each_format_safe(list, fmt, tmp) { 69762306a36Sopenharmony_ci list_del_init(&fmt->list); 69862306a36Sopenharmony_ci list_del_init(&fmt->sort_list); 69962306a36Sopenharmony_ci fmt_free(fmt); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci /* reset sort keys */ 70362306a36Sopenharmony_ci perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) { 70462306a36Sopenharmony_ci list_del_init(&fmt->list); 70562306a36Sopenharmony_ci list_del_init(&fmt->sort_list); 70662306a36Sopenharmony_ci fmt_free(fmt); 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci/* 71162306a36Sopenharmony_ci * See hists__fprintf to match the column widths 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_ciunsigned int hists__sort_list_width(struct hists *hists) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 71662306a36Sopenharmony_ci int ret = 0; 71762306a36Sopenharmony_ci bool first = true; 71862306a36Sopenharmony_ci struct perf_hpp dummy_hpp; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci hists__for_each_format(hists, fmt) { 72162306a36Sopenharmony_ci if (perf_hpp__should_skip(fmt, hists)) 72262306a36Sopenharmony_ci continue; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (first) 72562306a36Sopenharmony_ci first = false; 72662306a36Sopenharmony_ci else 72762306a36Sopenharmony_ci ret += 2; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci ret += fmt->width(fmt, &dummy_hpp, hists); 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (verbose > 0 && hists__has(hists, sym)) /* Addr + origin */ 73362306a36Sopenharmony_ci ret += 3 + BITS_PER_LONG / 4; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return ret; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciunsigned int hists__overhead_width(struct hists *hists) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 74162306a36Sopenharmony_ci int ret = 0; 74262306a36Sopenharmony_ci bool first = true; 74362306a36Sopenharmony_ci struct perf_hpp dummy_hpp; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci hists__for_each_format(hists, fmt) { 74662306a36Sopenharmony_ci if (perf_hpp__is_sort_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) 74762306a36Sopenharmony_ci break; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci if (first) 75062306a36Sopenharmony_ci first = false; 75162306a36Sopenharmony_ci else 75262306a36Sopenharmony_ci ret += 2; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci ret += fmt->width(fmt, &dummy_hpp, hists); 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci return ret; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_civoid perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci if (perf_hpp__is_sort_entry(fmt)) 76362306a36Sopenharmony_ci return perf_hpp__reset_sort_width(fmt, hists); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (perf_hpp__is_dynamic_entry(fmt)) 76662306a36Sopenharmony_ci return; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci BUG_ON(fmt->idx >= PERF_HPP__MAX_INDEX); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci switch (fmt->idx) { 77162306a36Sopenharmony_ci case PERF_HPP__OVERHEAD: 77262306a36Sopenharmony_ci case PERF_HPP__OVERHEAD_SYS: 77362306a36Sopenharmony_ci case PERF_HPP__OVERHEAD_US: 77462306a36Sopenharmony_ci case PERF_HPP__OVERHEAD_ACC: 77562306a36Sopenharmony_ci fmt->len = 8; 77662306a36Sopenharmony_ci break; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci case PERF_HPP__OVERHEAD_GUEST_SYS: 77962306a36Sopenharmony_ci case PERF_HPP__OVERHEAD_GUEST_US: 78062306a36Sopenharmony_ci fmt->len = 9; 78162306a36Sopenharmony_ci break; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci case PERF_HPP__SAMPLES: 78462306a36Sopenharmony_ci case PERF_HPP__PERIOD: 78562306a36Sopenharmony_ci fmt->len = 12; 78662306a36Sopenharmony_ci break; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci default: 78962306a36Sopenharmony_ci break; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci} 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_civoid hists__reset_column_width(struct hists *hists) 79462306a36Sopenharmony_ci{ 79562306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 79662306a36Sopenharmony_ci struct perf_hpp_list_node *node; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci hists__for_each_format(hists, fmt) 79962306a36Sopenharmony_ci perf_hpp__reset_width(fmt, hists); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* hierarchy entries have their own hpp list */ 80262306a36Sopenharmony_ci list_for_each_entry(node, &hists->hpp_formats, list) { 80362306a36Sopenharmony_ci perf_hpp_list__for_each_format(&node->hpp, fmt) 80462306a36Sopenharmony_ci perf_hpp__reset_width(fmt, hists); 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci} 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_civoid perf_hpp__set_user_width(const char *width_list_str) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 81162306a36Sopenharmony_ci const char *ptr = width_list_str; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { 81462306a36Sopenharmony_ci char *p; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci int len = strtol(ptr, &p, 10); 81762306a36Sopenharmony_ci fmt->user_len = len; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci if (*p == ',') 82062306a36Sopenharmony_ci ptr = p + 1; 82162306a36Sopenharmony_ci else 82262306a36Sopenharmony_ci break; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_cistatic int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt) 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci struct perf_hpp_list_node *node = NULL; 82962306a36Sopenharmony_ci struct perf_hpp_fmt *fmt_copy; 83062306a36Sopenharmony_ci bool found = false; 83162306a36Sopenharmony_ci bool skip = perf_hpp__should_skip(fmt, hists); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci list_for_each_entry(node, &hists->hpp_formats, list) { 83462306a36Sopenharmony_ci if (node->level == fmt->level) { 83562306a36Sopenharmony_ci found = true; 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci } 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci if (!found) { 84162306a36Sopenharmony_ci node = malloc(sizeof(*node)); 84262306a36Sopenharmony_ci if (node == NULL) 84362306a36Sopenharmony_ci return -1; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci node->skip = skip; 84662306a36Sopenharmony_ci node->level = fmt->level; 84762306a36Sopenharmony_ci perf_hpp_list__init(&node->hpp); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci hists->nr_hpp_node++; 85062306a36Sopenharmony_ci list_add_tail(&node->list, &hists->hpp_formats); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci fmt_copy = perf_hpp_fmt__dup(fmt); 85462306a36Sopenharmony_ci if (fmt_copy == NULL) 85562306a36Sopenharmony_ci return -1; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci if (!skip) 85862306a36Sopenharmony_ci node->skip = false; 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci list_add_tail(&fmt_copy->list, &node->hpp.fields); 86162306a36Sopenharmony_ci list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci return 0; 86462306a36Sopenharmony_ci} 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ciint perf_hpp__setup_hists_formats(struct perf_hpp_list *list, 86762306a36Sopenharmony_ci struct evlist *evlist) 86862306a36Sopenharmony_ci{ 86962306a36Sopenharmony_ci struct evsel *evsel; 87062306a36Sopenharmony_ci struct perf_hpp_fmt *fmt; 87162306a36Sopenharmony_ci struct hists *hists; 87262306a36Sopenharmony_ci int ret; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci if (!symbol_conf.report_hierarchy) 87562306a36Sopenharmony_ci return 0; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 87862306a36Sopenharmony_ci hists = evsel__hists(evsel); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci perf_hpp_list__for_each_sort_list(list, fmt) { 88162306a36Sopenharmony_ci if (perf_hpp__is_dynamic_entry(fmt) && 88262306a36Sopenharmony_ci !perf_hpp__defined_dynamic_entry(fmt, hists)) 88362306a36Sopenharmony_ci continue; 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci ret = add_hierarchy_fmt(hists, fmt); 88662306a36Sopenharmony_ci if (ret < 0) 88762306a36Sopenharmony_ci return ret; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return 0; 89262306a36Sopenharmony_ci} 893