18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <errno.h> 38c2ecf20Sopenharmony_ci#include <inttypes.h> 48c2ecf20Sopenharmony_ci#include <regex.h> 58c2ecf20Sopenharmony_ci#include <stdlib.h> 68c2ecf20Sopenharmony_ci#include <linux/mman.h> 78c2ecf20Sopenharmony_ci#include <linux/time64.h> 88c2ecf20Sopenharmony_ci#include "debug.h" 98c2ecf20Sopenharmony_ci#include "dso.h" 108c2ecf20Sopenharmony_ci#include "sort.h" 118c2ecf20Sopenharmony_ci#include "hist.h" 128c2ecf20Sopenharmony_ci#include "cacheline.h" 138c2ecf20Sopenharmony_ci#include "comm.h" 148c2ecf20Sopenharmony_ci#include "map.h" 158c2ecf20Sopenharmony_ci#include "maps.h" 168c2ecf20Sopenharmony_ci#include "symbol.h" 178c2ecf20Sopenharmony_ci#include "map_symbol.h" 188c2ecf20Sopenharmony_ci#include "branch.h" 198c2ecf20Sopenharmony_ci#include "thread.h" 208c2ecf20Sopenharmony_ci#include "evsel.h" 218c2ecf20Sopenharmony_ci#include "evlist.h" 228c2ecf20Sopenharmony_ci#include "srcline.h" 238c2ecf20Sopenharmony_ci#include "strlist.h" 248c2ecf20Sopenharmony_ci#include "strbuf.h" 258c2ecf20Sopenharmony_ci#include <traceevent/event-parse.h> 268c2ecf20Sopenharmony_ci#include "mem-events.h" 278c2ecf20Sopenharmony_ci#include "annotate.h" 288c2ecf20Sopenharmony_ci#include "time-utils.h" 298c2ecf20Sopenharmony_ci#include "cgroup.h" 308c2ecf20Sopenharmony_ci#include "machine.h" 318c2ecf20Sopenharmony_ci#include <linux/kernel.h> 328c2ecf20Sopenharmony_ci#include <linux/string.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciregex_t parent_regex; 358c2ecf20Sopenharmony_ciconst char default_parent_pattern[] = "^sys_|^do_page_fault"; 368c2ecf20Sopenharmony_ciconst char *parent_pattern = default_parent_pattern; 378c2ecf20Sopenharmony_ciconst char *default_sort_order = "comm,dso,symbol"; 388c2ecf20Sopenharmony_ciconst char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; 398c2ecf20Sopenharmony_ciconst char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 408c2ecf20Sopenharmony_ciconst char default_top_sort_order[] = "dso,symbol"; 418c2ecf20Sopenharmony_ciconst char default_diff_sort_order[] = "dso,symbol"; 428c2ecf20Sopenharmony_ciconst char default_tracepoint_sort_order[] = "trace"; 438c2ecf20Sopenharmony_ciconst char *sort_order; 448c2ecf20Sopenharmony_ciconst char *field_order; 458c2ecf20Sopenharmony_ciregex_t ignore_callees_regex; 468c2ecf20Sopenharmony_ciint have_ignore_callees = 0; 478c2ecf20Sopenharmony_cienum sort_mode sort__mode = SORT_MODE__NORMAL; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci * Replaces all occurrences of a char used with the: 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * -t, --field-separator 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * option, that uses a special separator character and don't pad with spaces, 558c2ecf20Sopenharmony_ci * replacing all occurrences of this separator in symbol names (and other 568c2ecf20Sopenharmony_ci * output) with a '.' character, that thus it's the only non valid separator. 578c2ecf20Sopenharmony_ci*/ 588c2ecf20Sopenharmony_cistatic int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci int n; 618c2ecf20Sopenharmony_ci va_list ap; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci va_start(ap, fmt); 648c2ecf20Sopenharmony_ci n = vsnprintf(bf, size, fmt, ap); 658c2ecf20Sopenharmony_ci if (symbol_conf.field_sep && n > 0) { 668c2ecf20Sopenharmony_ci char *sep = bf; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci while (1) { 698c2ecf20Sopenharmony_ci sep = strchr(sep, *symbol_conf.field_sep); 708c2ecf20Sopenharmony_ci if (sep == NULL) 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci *sep = '.'; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci va_end(ap); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (n >= (int)size) 788c2ecf20Sopenharmony_ci return size - 1; 798c2ecf20Sopenharmony_ci return n; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic int64_t cmp_null(const void *l, const void *r) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci if (!l && !r) 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci else if (!l) 878c2ecf20Sopenharmony_ci return -1; 888c2ecf20Sopenharmony_ci else 898c2ecf20Sopenharmony_ci return 1; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* --sort pid */ 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic int64_t 958c2ecf20Sopenharmony_cisort__thread_cmp(struct hist_entry *left, struct hist_entry *right) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci return right->thread->tid - left->thread->tid; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int hist_entry__thread_snprintf(struct hist_entry *he, char *bf, 1018c2ecf20Sopenharmony_ci size_t size, unsigned int width) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci const char *comm = thread__comm_str(he->thread); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci width = max(7U, width) - 8; 1068c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%7d:%-*.*s", he->thread->tid, 1078c2ecf20Sopenharmony_ci width, width, comm ?: ""); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int hist_entry__thread_filter(struct hist_entry *he, int type, const void *arg) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci const struct thread *th = arg; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (type != HIST_FILTER__THREAD) 1158c2ecf20Sopenharmony_ci return -1; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return th && he->thread != th; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistruct sort_entry sort_thread = { 1218c2ecf20Sopenharmony_ci .se_header = " Pid:Command", 1228c2ecf20Sopenharmony_ci .se_cmp = sort__thread_cmp, 1238c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__thread_snprintf, 1248c2ecf20Sopenharmony_ci .se_filter = hist_entry__thread_filter, 1258c2ecf20Sopenharmony_ci .se_width_idx = HISTC_THREAD, 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* --sort comm */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * We can't use pointer comparison in functions below, 1328c2ecf20Sopenharmony_ci * because it gives different results based on pointer 1338c2ecf20Sopenharmony_ci * values, which could break some sorting assumptions. 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_cistatic int64_t 1368c2ecf20Sopenharmony_cisort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci return strcmp(comm__str(right->comm), comm__str(left->comm)); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic int64_t 1428c2ecf20Sopenharmony_cisort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return strcmp(comm__str(right->comm), comm__str(left->comm)); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic int64_t 1488c2ecf20Sopenharmony_cisort__comm_sort(struct hist_entry *left, struct hist_entry *right) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci return strcmp(comm__str(right->comm), comm__str(left->comm)); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 1548c2ecf20Sopenharmony_ci size_t size, unsigned int width) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm)); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistruct sort_entry sort_comm = { 1608c2ecf20Sopenharmony_ci .se_header = "Command", 1618c2ecf20Sopenharmony_ci .se_cmp = sort__comm_cmp, 1628c2ecf20Sopenharmony_ci .se_collapse = sort__comm_collapse, 1638c2ecf20Sopenharmony_ci .se_sort = sort__comm_sort, 1648c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__comm_snprintf, 1658c2ecf20Sopenharmony_ci .se_filter = hist_entry__thread_filter, 1668c2ecf20Sopenharmony_ci .se_width_idx = HISTC_COMM, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/* --sort dso */ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci struct dso *dso_l = map_l ? map_l->dso : NULL; 1748c2ecf20Sopenharmony_ci struct dso *dso_r = map_r ? map_r->dso : NULL; 1758c2ecf20Sopenharmony_ci const char *dso_name_l, *dso_name_r; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci if (!dso_l || !dso_r) 1788c2ecf20Sopenharmony_ci return cmp_null(dso_r, dso_l); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (verbose > 0) { 1818c2ecf20Sopenharmony_ci dso_name_l = dso_l->long_name; 1828c2ecf20Sopenharmony_ci dso_name_r = dso_r->long_name; 1838c2ecf20Sopenharmony_ci } else { 1848c2ecf20Sopenharmony_ci dso_name_l = dso_l->short_name; 1858c2ecf20Sopenharmony_ci dso_name_r = dso_r->short_name; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return strcmp(dso_name_l, dso_name_r); 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic int64_t 1928c2ecf20Sopenharmony_cisort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci return _sort__dso_cmp(right->ms.map, left->ms.map); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int _hist_entry__dso_snprintf(struct map *map, char *bf, 1988c2ecf20Sopenharmony_ci size_t size, unsigned int width) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci if (map && map->dso) { 2018c2ecf20Sopenharmony_ci const char *dso_name = verbose > 0 ? map->dso->long_name : 2028c2ecf20Sopenharmony_ci map->dso->short_name; 2038c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name); 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]"); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 2108c2ecf20Sopenharmony_ci size_t size, unsigned int width) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci return _hist_entry__dso_snprintf(he->ms.map, bf, size, width); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int hist_entry__dso_filter(struct hist_entry *he, int type, const void *arg) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci const struct dso *dso = arg; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (type != HIST_FILTER__DSO) 2208c2ecf20Sopenharmony_ci return -1; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return dso && (!he->ms.map || he->ms.map->dso != dso); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistruct sort_entry sort_dso = { 2268c2ecf20Sopenharmony_ci .se_header = "Shared Object", 2278c2ecf20Sopenharmony_ci .se_cmp = sort__dso_cmp, 2288c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dso_snprintf, 2298c2ecf20Sopenharmony_ci .se_filter = hist_entry__dso_filter, 2308c2ecf20Sopenharmony_ci .se_width_idx = HISTC_DSO, 2318c2ecf20Sopenharmony_ci}; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/* --sort symbol */ 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci return (int64_t)(right_ip - left_ip); 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciint64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci if (!sym_l || !sym_r) 2438c2ecf20Sopenharmony_ci return cmp_null(sym_l, sym_r); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (sym_l == sym_r) 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (sym_l->inlined || sym_r->inlined) { 2498c2ecf20Sopenharmony_ci int ret = strcmp(sym_l->name, sym_r->name); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (ret) 2528c2ecf20Sopenharmony_ci return ret; 2538c2ecf20Sopenharmony_ci if ((sym_l->start <= sym_r->end) && (sym_l->end >= sym_r->start)) 2548c2ecf20Sopenharmony_ci return 0; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (sym_l->start != sym_r->start) 2588c2ecf20Sopenharmony_ci return (int64_t)(sym_r->start - sym_l->start); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return (int64_t)(sym_r->end - sym_l->end); 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int64_t 2648c2ecf20Sopenharmony_cisort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci int64_t ret; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (!left->ms.sym && !right->ms.sym) 2698c2ecf20Sopenharmony_ci return _sort__addr_cmp(left->ip, right->ip); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* 2728c2ecf20Sopenharmony_ci * comparing symbol address alone is not enough since it's a 2738c2ecf20Sopenharmony_ci * relative address within a dso. 2748c2ecf20Sopenharmony_ci */ 2758c2ecf20Sopenharmony_ci if (!hists__has(left->hists, dso) || hists__has(right->hists, dso)) { 2768c2ecf20Sopenharmony_ci ret = sort__dso_cmp(left, right); 2778c2ecf20Sopenharmony_ci if (ret != 0) 2788c2ecf20Sopenharmony_ci return ret; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return _sort__sym_cmp(left->ms.sym, right->ms.sym); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic int64_t 2858c2ecf20Sopenharmony_cisort__sym_sort(struct hist_entry *left, struct hist_entry *right) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci if (!left->ms.sym || !right->ms.sym) 2888c2ecf20Sopenharmony_ci return cmp_null(left->ms.sym, right->ms.sym); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return strcmp(right->ms.sym->name, left->ms.sym->name); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic int _hist_entry__sym_snprintf(struct map_symbol *ms, 2948c2ecf20Sopenharmony_ci u64 ip, char level, char *bf, size_t size, 2958c2ecf20Sopenharmony_ci unsigned int width) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci struct symbol *sym = ms->sym; 2988c2ecf20Sopenharmony_ci struct map *map = ms->map; 2998c2ecf20Sopenharmony_ci size_t ret = 0; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (verbose > 0) { 3028c2ecf20Sopenharmony_ci char o = map ? dso__symtab_origin(map->dso) : '!'; 3038c2ecf20Sopenharmony_ci u64 rip = ip; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (map && map->dso && map->dso->kernel 3068c2ecf20Sopenharmony_ci && map->dso->adjust_symbols) 3078c2ecf20Sopenharmony_ci rip = map->unmap_ip(map, ip); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf, size, "%-#*llx %c ", 3108c2ecf20Sopenharmony_ci BITS_PER_LONG / 4 + 2, rip, o); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); 3148c2ecf20Sopenharmony_ci if (sym && map) { 3158c2ecf20Sopenharmony_ci if (sym->type == STT_OBJECT) { 3168c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); 3178c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", 3188c2ecf20Sopenharmony_ci ip - map->unmap_ip(map, sym->start)); 3198c2ecf20Sopenharmony_ci } else { 3208c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "%.*s", 3218c2ecf20Sopenharmony_ci width - ret, 3228c2ecf20Sopenharmony_ci sym->name); 3238c2ecf20Sopenharmony_ci if (sym->inlined) 3248c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, 3258c2ecf20Sopenharmony_ci " (inlined)"); 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci } else { 3288c2ecf20Sopenharmony_ci size_t len = BITS_PER_LONG / 4; 3298c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", 3308c2ecf20Sopenharmony_ci len, ip); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return ret; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ciint hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(&he->ms, he->ip, 3398c2ecf20Sopenharmony_ci he->level, bf, size, width); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic int hist_entry__sym_filter(struct hist_entry *he, int type, const void *arg) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci const char *sym = arg; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (type != HIST_FILTER__SYMBOL) 3478c2ecf20Sopenharmony_ci return -1; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return sym && (!he->ms.sym || !strstr(he->ms.sym->name, sym)); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistruct sort_entry sort_sym = { 3538c2ecf20Sopenharmony_ci .se_header = "Symbol", 3548c2ecf20Sopenharmony_ci .se_cmp = sort__sym_cmp, 3558c2ecf20Sopenharmony_ci .se_sort = sort__sym_sort, 3568c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_snprintf, 3578c2ecf20Sopenharmony_ci .se_filter = hist_entry__sym_filter, 3588c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYMBOL, 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* --sort srcline */ 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cichar *hist_entry__srcline(struct hist_entry *he) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci return map__srcline(he->ms.map, he->ip, he->ms.sym); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic int64_t 3698c2ecf20Sopenharmony_cisort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci if (!left->srcline) 3728c2ecf20Sopenharmony_ci left->srcline = hist_entry__srcline(left); 3738c2ecf20Sopenharmony_ci if (!right->srcline) 3748c2ecf20Sopenharmony_ci right->srcline = hist_entry__srcline(right); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return strcmp(right->srcline, left->srcline); 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 3808c2ecf20Sopenharmony_ci size_t size, unsigned int width) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci if (!he->srcline) 3838c2ecf20Sopenharmony_ci he->srcline = hist_entry__srcline(he); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-.*s", width, he->srcline); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistruct sort_entry sort_srcline = { 3898c2ecf20Sopenharmony_ci .se_header = "Source:Line", 3908c2ecf20Sopenharmony_ci .se_cmp = sort__srcline_cmp, 3918c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__srcline_snprintf, 3928c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SRCLINE, 3938c2ecf20Sopenharmony_ci}; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/* --sort srcline_from */ 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic char *addr_map_symbol__srcline(struct addr_map_symbol *ams) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci return map__srcline(ams->ms.map, ams->al_addr, ams->ms.sym); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic int64_t 4038c2ecf20Sopenharmony_cisort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci if (!left->branch_info->srcline_from) 4068c2ecf20Sopenharmony_ci left->branch_info->srcline_from = addr_map_symbol__srcline(&left->branch_info->from); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (!right->branch_info->srcline_from) 4098c2ecf20Sopenharmony_ci right->branch_info->srcline_from = addr_map_symbol__srcline(&right->branch_info->from); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from); 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf, 4158c2ecf20Sopenharmony_ci size_t size, unsigned int width) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistruct sort_entry sort_srcline_from = { 4218c2ecf20Sopenharmony_ci .se_header = "From Source:Line", 4228c2ecf20Sopenharmony_ci .se_cmp = sort__srcline_from_cmp, 4238c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__srcline_from_snprintf, 4248c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SRCLINE_FROM, 4258c2ecf20Sopenharmony_ci}; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* --sort srcline_to */ 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic int64_t 4308c2ecf20Sopenharmony_cisort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci if (!left->branch_info->srcline_to) 4338c2ecf20Sopenharmony_ci left->branch_info->srcline_to = addr_map_symbol__srcline(&left->branch_info->to); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if (!right->branch_info->srcline_to) 4368c2ecf20Sopenharmony_ci right->branch_info->srcline_to = addr_map_symbol__srcline(&right->branch_info->to); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf, 4428c2ecf20Sopenharmony_ci size_t size, unsigned int width) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to); 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistruct sort_entry sort_srcline_to = { 4488c2ecf20Sopenharmony_ci .se_header = "To Source:Line", 4498c2ecf20Sopenharmony_ci .se_cmp = sort__srcline_to_cmp, 4508c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__srcline_to_snprintf, 4518c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SRCLINE_TO, 4528c2ecf20Sopenharmony_ci}; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf, 4558c2ecf20Sopenharmony_ci size_t size, unsigned int width) 4568c2ecf20Sopenharmony_ci{ 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci struct symbol *sym = he->ms.sym; 4598c2ecf20Sopenharmony_ci struct annotation *notes; 4608c2ecf20Sopenharmony_ci double ipc = 0.0, coverage = 0.0; 4618c2ecf20Sopenharmony_ci char tmp[64]; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (!sym) 4648c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, "-"); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci notes = symbol__annotation(sym); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci if (notes->hit_cycles) 4698c2ecf20Sopenharmony_ci ipc = notes->hit_insn / ((double)notes->hit_cycles); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (notes->total_insn) { 4728c2ecf20Sopenharmony_ci coverage = notes->cover_insn * 100.0 / 4738c2ecf20Sopenharmony_ci ((double)notes->total_insn); 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci snprintf(tmp, sizeof(tmp), "%-5.2f [%5.1f%%]", ipc, coverage); 4778c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, tmp); 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistruct sort_entry sort_sym_ipc = { 4818c2ecf20Sopenharmony_ci .se_header = "IPC [IPC Coverage]", 4828c2ecf20Sopenharmony_ci .se_cmp = sort__sym_cmp, 4838c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_ipc_snprintf, 4848c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYMBOL_IPC, 4858c2ecf20Sopenharmony_ci}; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic int hist_entry__sym_ipc_null_snprintf(struct hist_entry *he 4888c2ecf20Sopenharmony_ci __maybe_unused, 4898c2ecf20Sopenharmony_ci char *bf, size_t size, 4908c2ecf20Sopenharmony_ci unsigned int width) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci char tmp[64]; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci snprintf(tmp, sizeof(tmp), "%-5s %2s", "-", "-"); 4958c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, tmp); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistruct sort_entry sort_sym_ipc_null = { 4998c2ecf20Sopenharmony_ci .se_header = "IPC [IPC Coverage]", 5008c2ecf20Sopenharmony_ci .se_cmp = sort__sym_cmp, 5018c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_ipc_null_snprintf, 5028c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYMBOL_IPC, 5038c2ecf20Sopenharmony_ci}; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/* --sort srcfile */ 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic char no_srcfile[1]; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic char *hist_entry__get_srcfile(struct hist_entry *e) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci char *sf, *p; 5128c2ecf20Sopenharmony_ci struct map *map = e->ms.map; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci if (!map) 5158c2ecf20Sopenharmony_ci return no_srcfile; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), 5188c2ecf20Sopenharmony_ci e->ms.sym, false, true, true, e->ip); 5198c2ecf20Sopenharmony_ci if (!strcmp(sf, SRCLINE_UNKNOWN)) 5208c2ecf20Sopenharmony_ci return no_srcfile; 5218c2ecf20Sopenharmony_ci p = strchr(sf, ':'); 5228c2ecf20Sopenharmony_ci if (p && *sf) { 5238c2ecf20Sopenharmony_ci *p = 0; 5248c2ecf20Sopenharmony_ci return sf; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci free(sf); 5278c2ecf20Sopenharmony_ci return no_srcfile; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic int64_t 5318c2ecf20Sopenharmony_cisort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci if (!left->srcfile) 5348c2ecf20Sopenharmony_ci left->srcfile = hist_entry__get_srcfile(left); 5358c2ecf20Sopenharmony_ci if (!right->srcfile) 5368c2ecf20Sopenharmony_ci right->srcfile = hist_entry__get_srcfile(right); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci return strcmp(right->srcfile, left->srcfile); 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf, 5428c2ecf20Sopenharmony_ci size_t size, unsigned int width) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci if (!he->srcfile) 5458c2ecf20Sopenharmony_ci he->srcfile = hist_entry__get_srcfile(he); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-.*s", width, he->srcfile); 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_cistruct sort_entry sort_srcfile = { 5518c2ecf20Sopenharmony_ci .se_header = "Source File", 5528c2ecf20Sopenharmony_ci .se_cmp = sort__srcfile_cmp, 5538c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__srcfile_snprintf, 5548c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SRCFILE, 5558c2ecf20Sopenharmony_ci}; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* --sort parent */ 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic int64_t 5608c2ecf20Sopenharmony_cisort__parent_cmp(struct hist_entry *left, struct hist_entry *right) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci struct symbol *sym_l = left->parent; 5638c2ecf20Sopenharmony_ci struct symbol *sym_r = right->parent; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (!sym_l || !sym_r) 5668c2ecf20Sopenharmony_ci return cmp_null(sym_l, sym_r); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci return strcmp(sym_r->name, sym_l->name); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 5728c2ecf20Sopenharmony_ci size_t size, unsigned int width) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, 5758c2ecf20Sopenharmony_ci he->parent ? he->parent->name : "[other]"); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistruct sort_entry sort_parent = { 5798c2ecf20Sopenharmony_ci .se_header = "Parent symbol", 5808c2ecf20Sopenharmony_ci .se_cmp = sort__parent_cmp, 5818c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__parent_snprintf, 5828c2ecf20Sopenharmony_ci .se_width_idx = HISTC_PARENT, 5838c2ecf20Sopenharmony_ci}; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci/* --sort cpu */ 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic int64_t 5888c2ecf20Sopenharmony_cisort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci return right->cpu - left->cpu; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 5948c2ecf20Sopenharmony_ci size_t size, unsigned int width) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistruct sort_entry sort_cpu = { 6008c2ecf20Sopenharmony_ci .se_header = "CPU", 6018c2ecf20Sopenharmony_ci .se_cmp = sort__cpu_cmp, 6028c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__cpu_snprintf, 6038c2ecf20Sopenharmony_ci .se_width_idx = HISTC_CPU, 6048c2ecf20Sopenharmony_ci}; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci/* --sort cgroup_id */ 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic int64_t _sort__cgroup_dev_cmp(u64 left_dev, u64 right_dev) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci return (int64_t)(right_dev - left_dev); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic int64_t _sort__cgroup_inode_cmp(u64 left_ino, u64 right_ino) 6148c2ecf20Sopenharmony_ci{ 6158c2ecf20Sopenharmony_ci return (int64_t)(right_ino - left_ino); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic int64_t 6198c2ecf20Sopenharmony_cisort__cgroup_id_cmp(struct hist_entry *left, struct hist_entry *right) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci int64_t ret; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci ret = _sort__cgroup_dev_cmp(right->cgroup_id.dev, left->cgroup_id.dev); 6248c2ecf20Sopenharmony_ci if (ret != 0) 6258c2ecf20Sopenharmony_ci return ret; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci return _sort__cgroup_inode_cmp(right->cgroup_id.ino, 6288c2ecf20Sopenharmony_ci left->cgroup_id.ino); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int hist_entry__cgroup_id_snprintf(struct hist_entry *he, 6328c2ecf20Sopenharmony_ci char *bf, size_t size, 6338c2ecf20Sopenharmony_ci unsigned int width __maybe_unused) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%lu/0x%lx", he->cgroup_id.dev, 6368c2ecf20Sopenharmony_ci he->cgroup_id.ino); 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistruct sort_entry sort_cgroup_id = { 6408c2ecf20Sopenharmony_ci .se_header = "cgroup id (dev/inode)", 6418c2ecf20Sopenharmony_ci .se_cmp = sort__cgroup_id_cmp, 6428c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__cgroup_id_snprintf, 6438c2ecf20Sopenharmony_ci .se_width_idx = HISTC_CGROUP_ID, 6448c2ecf20Sopenharmony_ci}; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci/* --sort cgroup */ 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic int64_t 6498c2ecf20Sopenharmony_cisort__cgroup_cmp(struct hist_entry *left, struct hist_entry *right) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci return right->cgroup - left->cgroup; 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic int hist_entry__cgroup_snprintf(struct hist_entry *he, 6558c2ecf20Sopenharmony_ci char *bf, size_t size, 6568c2ecf20Sopenharmony_ci unsigned int width __maybe_unused) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci const char *cgrp_name = "N/A"; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci if (he->cgroup) { 6618c2ecf20Sopenharmony_ci struct cgroup *cgrp = cgroup__find(he->ms.maps->machine->env, 6628c2ecf20Sopenharmony_ci he->cgroup); 6638c2ecf20Sopenharmony_ci if (cgrp != NULL) 6648c2ecf20Sopenharmony_ci cgrp_name = cgrp->name; 6658c2ecf20Sopenharmony_ci else 6668c2ecf20Sopenharmony_ci cgrp_name = "unknown"; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%s", cgrp_name); 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistruct sort_entry sort_cgroup = { 6738c2ecf20Sopenharmony_ci .se_header = "Cgroup", 6748c2ecf20Sopenharmony_ci .se_cmp = sort__cgroup_cmp, 6758c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__cgroup_snprintf, 6768c2ecf20Sopenharmony_ci .se_width_idx = HISTC_CGROUP, 6778c2ecf20Sopenharmony_ci}; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci/* --sort socket */ 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic int64_t 6828c2ecf20Sopenharmony_cisort__socket_cmp(struct hist_entry *left, struct hist_entry *right) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci return right->socket - left->socket; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cistatic int hist_entry__socket_snprintf(struct hist_entry *he, char *bf, 6888c2ecf20Sopenharmony_ci size_t size, unsigned int width) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket); 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic int hist_entry__socket_filter(struct hist_entry *he, int type, const void *arg) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci int sk = *(const int *)arg; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (type != HIST_FILTER__SOCKET) 6988c2ecf20Sopenharmony_ci return -1; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci return sk >= 0 && he->socket != sk; 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistruct sort_entry sort_socket = { 7048c2ecf20Sopenharmony_ci .se_header = "Socket", 7058c2ecf20Sopenharmony_ci .se_cmp = sort__socket_cmp, 7068c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__socket_snprintf, 7078c2ecf20Sopenharmony_ci .se_filter = hist_entry__socket_filter, 7088c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SOCKET, 7098c2ecf20Sopenharmony_ci}; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci/* --sort time */ 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int64_t 7148c2ecf20Sopenharmony_cisort__time_cmp(struct hist_entry *left, struct hist_entry *right) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci return right->time - left->time; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int hist_entry__time_snprintf(struct hist_entry *he, char *bf, 7208c2ecf20Sopenharmony_ci size_t size, unsigned int width) 7218c2ecf20Sopenharmony_ci{ 7228c2ecf20Sopenharmony_ci char he_time[32]; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci if (symbol_conf.nanosecs) 7258c2ecf20Sopenharmony_ci timestamp__scnprintf_nsec(he->time, he_time, 7268c2ecf20Sopenharmony_ci sizeof(he_time)); 7278c2ecf20Sopenharmony_ci else 7288c2ecf20Sopenharmony_ci timestamp__scnprintf_usec(he->time, he_time, 7298c2ecf20Sopenharmony_ci sizeof(he_time)); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-.*s", width, he_time); 7328c2ecf20Sopenharmony_ci} 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_cistruct sort_entry sort_time = { 7358c2ecf20Sopenharmony_ci .se_header = "Time", 7368c2ecf20Sopenharmony_ci .se_cmp = sort__time_cmp, 7378c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__time_snprintf, 7388c2ecf20Sopenharmony_ci .se_width_idx = HISTC_TIME, 7398c2ecf20Sopenharmony_ci}; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci/* --sort trace */ 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic char *get_trace_output(struct hist_entry *he) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct trace_seq seq; 7468c2ecf20Sopenharmony_ci struct evsel *evsel; 7478c2ecf20Sopenharmony_ci struct tep_record rec = { 7488c2ecf20Sopenharmony_ci .data = he->raw_data, 7498c2ecf20Sopenharmony_ci .size = he->raw_size, 7508c2ecf20Sopenharmony_ci }; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci evsel = hists_to_evsel(he->hists); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci trace_seq_init(&seq); 7558c2ecf20Sopenharmony_ci if (symbol_conf.raw_trace) { 7568c2ecf20Sopenharmony_ci tep_print_fields(&seq, he->raw_data, he->raw_size, 7578c2ecf20Sopenharmony_ci evsel->tp_format); 7588c2ecf20Sopenharmony_ci } else { 7598c2ecf20Sopenharmony_ci tep_print_event(evsel->tp_format->tep, 7608c2ecf20Sopenharmony_ci &seq, &rec, "%s", TEP_PRINT_INFO); 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci /* 7638c2ecf20Sopenharmony_ci * Trim the buffer, it starts at 4KB and we're not going to 7648c2ecf20Sopenharmony_ci * add anything more to this buffer. 7658c2ecf20Sopenharmony_ci */ 7668c2ecf20Sopenharmony_ci return realloc(seq.buffer, seq.len + 1); 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_cistatic int64_t 7708c2ecf20Sopenharmony_cisort__trace_cmp(struct hist_entry *left, struct hist_entry *right) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci struct evsel *evsel; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci evsel = hists_to_evsel(left->hists); 7758c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) 7768c2ecf20Sopenharmony_ci return 0; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci if (left->trace_output == NULL) 7798c2ecf20Sopenharmony_ci left->trace_output = get_trace_output(left); 7808c2ecf20Sopenharmony_ci if (right->trace_output == NULL) 7818c2ecf20Sopenharmony_ci right->trace_output = get_trace_output(right); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return strcmp(right->trace_output, left->trace_output); 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, 7878c2ecf20Sopenharmony_ci size_t size, unsigned int width) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct evsel *evsel; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci evsel = hists_to_evsel(he->hists); 7928c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) 7938c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%-.*s", width, "N/A"); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if (he->trace_output == NULL) 7968c2ecf20Sopenharmony_ci he->trace_output = get_trace_output(he); 7978c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-.*s", width, he->trace_output); 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_cistruct sort_entry sort_trace = { 8018c2ecf20Sopenharmony_ci .se_header = "Trace output", 8028c2ecf20Sopenharmony_ci .se_cmp = sort__trace_cmp, 8038c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__trace_snprintf, 8048c2ecf20Sopenharmony_ci .se_width_idx = HISTC_TRACE, 8058c2ecf20Sopenharmony_ci}; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci/* sort keys for branch stacks */ 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic int64_t 8108c2ecf20Sopenharmony_cisort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 8138c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci return _sort__dso_cmp(left->branch_info->from.ms.map, 8168c2ecf20Sopenharmony_ci right->branch_info->from.ms.map); 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, 8208c2ecf20Sopenharmony_ci size_t size, unsigned int width) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci if (he->branch_info) 8238c2ecf20Sopenharmony_ci return _hist_entry__dso_snprintf(he->branch_info->from.ms.map, 8248c2ecf20Sopenharmony_ci bf, size, width); 8258c2ecf20Sopenharmony_ci else 8268c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic int hist_entry__dso_from_filter(struct hist_entry *he, int type, 8308c2ecf20Sopenharmony_ci const void *arg) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci const struct dso *dso = arg; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci if (type != HIST_FILTER__DSO) 8358c2ecf20Sopenharmony_ci return -1; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci return dso && (!he->branch_info || !he->branch_info->from.ms.map || 8388c2ecf20Sopenharmony_ci he->branch_info->from.ms.map->dso != dso); 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_cistatic int64_t 8428c2ecf20Sopenharmony_cisort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 8458c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci return _sort__dso_cmp(left->branch_info->to.ms.map, 8488c2ecf20Sopenharmony_ci right->branch_info->to.ms.map); 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_cistatic int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, 8528c2ecf20Sopenharmony_ci size_t size, unsigned int width) 8538c2ecf20Sopenharmony_ci{ 8548c2ecf20Sopenharmony_ci if (he->branch_info) 8558c2ecf20Sopenharmony_ci return _hist_entry__dso_snprintf(he->branch_info->to.ms.map, 8568c2ecf20Sopenharmony_ci bf, size, width); 8578c2ecf20Sopenharmony_ci else 8588c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_cistatic int hist_entry__dso_to_filter(struct hist_entry *he, int type, 8628c2ecf20Sopenharmony_ci const void *arg) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci const struct dso *dso = arg; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci if (type != HIST_FILTER__DSO) 8678c2ecf20Sopenharmony_ci return -1; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci return dso && (!he->branch_info || !he->branch_info->to.ms.map || 8708c2ecf20Sopenharmony_ci he->branch_info->to.ms.map->dso != dso); 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic int64_t 8748c2ecf20Sopenharmony_cisort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci struct addr_map_symbol *from_l, *from_r; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 8798c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci from_l = &left->branch_info->from; 8828c2ecf20Sopenharmony_ci from_r = &right->branch_info->from; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (!from_l->ms.sym && !from_r->ms.sym) 8858c2ecf20Sopenharmony_ci return _sort__addr_cmp(from_l->addr, from_r->addr); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym); 8888c2ecf20Sopenharmony_ci} 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic int64_t 8918c2ecf20Sopenharmony_cisort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct addr_map_symbol *to_l, *to_r; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 8968c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci to_l = &left->branch_info->to; 8998c2ecf20Sopenharmony_ci to_r = &right->branch_info->to; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (!to_l->ms.sym && !to_r->ms.sym) 9028c2ecf20Sopenharmony_ci return _sort__addr_cmp(to_l->addr, to_r->addr); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci return _sort__sym_cmp(to_l->ms.sym, to_r->ms.sym); 9058c2ecf20Sopenharmony_ci} 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, 9088c2ecf20Sopenharmony_ci size_t size, unsigned int width) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci if (he->branch_info) { 9118c2ecf20Sopenharmony_ci struct addr_map_symbol *from = &he->branch_info->from; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(&from->ms, from->al_addr, 9148c2ecf20Sopenharmony_ci he->level, bf, size, width); 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, 9218c2ecf20Sopenharmony_ci size_t size, unsigned int width) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci if (he->branch_info) { 9248c2ecf20Sopenharmony_ci struct addr_map_symbol *to = &he->branch_info->to; 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(&to->ms, to->al_addr, 9278c2ecf20Sopenharmony_ci he->level, bf, size, width); 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A"); 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_cistatic int hist_entry__sym_from_filter(struct hist_entry *he, int type, 9348c2ecf20Sopenharmony_ci const void *arg) 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci const char *sym = arg; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (type != HIST_FILTER__SYMBOL) 9398c2ecf20Sopenharmony_ci return -1; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return sym && !(he->branch_info && he->branch_info->from.ms.sym && 9428c2ecf20Sopenharmony_ci strstr(he->branch_info->from.ms.sym->name, sym)); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic int hist_entry__sym_to_filter(struct hist_entry *he, int type, 9468c2ecf20Sopenharmony_ci const void *arg) 9478c2ecf20Sopenharmony_ci{ 9488c2ecf20Sopenharmony_ci const char *sym = arg; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci if (type != HIST_FILTER__SYMBOL) 9518c2ecf20Sopenharmony_ci return -1; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci return sym && !(he->branch_info && he->branch_info->to.ms.sym && 9548c2ecf20Sopenharmony_ci strstr(he->branch_info->to.ms.sym->name, sym)); 9558c2ecf20Sopenharmony_ci} 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_cistruct sort_entry sort_dso_from = { 9588c2ecf20Sopenharmony_ci .se_header = "Source Shared Object", 9598c2ecf20Sopenharmony_ci .se_cmp = sort__dso_from_cmp, 9608c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dso_from_snprintf, 9618c2ecf20Sopenharmony_ci .se_filter = hist_entry__dso_from_filter, 9628c2ecf20Sopenharmony_ci .se_width_idx = HISTC_DSO_FROM, 9638c2ecf20Sopenharmony_ci}; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_cistruct sort_entry sort_dso_to = { 9668c2ecf20Sopenharmony_ci .se_header = "Target Shared Object", 9678c2ecf20Sopenharmony_ci .se_cmp = sort__dso_to_cmp, 9688c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dso_to_snprintf, 9698c2ecf20Sopenharmony_ci .se_filter = hist_entry__dso_to_filter, 9708c2ecf20Sopenharmony_ci .se_width_idx = HISTC_DSO_TO, 9718c2ecf20Sopenharmony_ci}; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_cistruct sort_entry sort_sym_from = { 9748c2ecf20Sopenharmony_ci .se_header = "Source Symbol", 9758c2ecf20Sopenharmony_ci .se_cmp = sort__sym_from_cmp, 9768c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_from_snprintf, 9778c2ecf20Sopenharmony_ci .se_filter = hist_entry__sym_from_filter, 9788c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYMBOL_FROM, 9798c2ecf20Sopenharmony_ci}; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_cistruct sort_entry sort_sym_to = { 9828c2ecf20Sopenharmony_ci .se_header = "Target Symbol", 9838c2ecf20Sopenharmony_ci .se_cmp = sort__sym_to_cmp, 9848c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_to_snprintf, 9858c2ecf20Sopenharmony_ci .se_filter = hist_entry__sym_to_filter, 9868c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYMBOL_TO, 9878c2ecf20Sopenharmony_ci}; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_cistatic int64_t 9908c2ecf20Sopenharmony_cisort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) 9918c2ecf20Sopenharmony_ci{ 9928c2ecf20Sopenharmony_ci unsigned char mp, p; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 9958c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred; 9988c2ecf20Sopenharmony_ci p = left->branch_info->flags.predicted != right->branch_info->flags.predicted; 9998c2ecf20Sopenharmony_ci return mp || p; 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_cistatic int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf, 10038c2ecf20Sopenharmony_ci size_t size, unsigned int width){ 10048c2ecf20Sopenharmony_ci static const char *out = "N/A"; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (he->branch_info) { 10078c2ecf20Sopenharmony_ci if (he->branch_info->flags.predicted) 10088c2ecf20Sopenharmony_ci out = "N"; 10098c2ecf20Sopenharmony_ci else if (he->branch_info->flags.mispred) 10108c2ecf20Sopenharmony_ci out = "Y"; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*.*s", width, width, out); 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic int64_t 10178c2ecf20Sopenharmony_cisort__cycles_cmp(struct hist_entry *left, struct hist_entry *right) 10188c2ecf20Sopenharmony_ci{ 10198c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 10208c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci return left->branch_info->flags.cycles - 10238c2ecf20Sopenharmony_ci right->branch_info->flags.cycles; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf, 10278c2ecf20Sopenharmony_ci size_t size, unsigned int width) 10288c2ecf20Sopenharmony_ci{ 10298c2ecf20Sopenharmony_ci if (!he->branch_info) 10308c2ecf20Sopenharmony_ci return scnprintf(bf, size, "%-.*s", width, "N/A"); 10318c2ecf20Sopenharmony_ci if (he->branch_info->flags.cycles == 0) 10328c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, "-"); 10338c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*hd", width, 10348c2ecf20Sopenharmony_ci he->branch_info->flags.cycles); 10358c2ecf20Sopenharmony_ci} 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistruct sort_entry sort_cycles = { 10388c2ecf20Sopenharmony_ci .se_header = "Basic Block Cycles", 10398c2ecf20Sopenharmony_ci .se_cmp = sort__cycles_cmp, 10408c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__cycles_snprintf, 10418c2ecf20Sopenharmony_ci .se_width_idx = HISTC_CYCLES, 10428c2ecf20Sopenharmony_ci}; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci/* --sort daddr_sym */ 10458c2ecf20Sopenharmony_ciint64_t 10468c2ecf20Sopenharmony_cisort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci uint64_t l = 0, r = 0; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci if (left->mem_info) 10518c2ecf20Sopenharmony_ci l = left->mem_info->daddr.addr; 10528c2ecf20Sopenharmony_ci if (right->mem_info) 10538c2ecf20Sopenharmony_ci r = right->mem_info->daddr.addr; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci return (int64_t)(r - l); 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, 10598c2ecf20Sopenharmony_ci size_t size, unsigned int width) 10608c2ecf20Sopenharmony_ci{ 10618c2ecf20Sopenharmony_ci uint64_t addr = 0; 10628c2ecf20Sopenharmony_ci struct map_symbol *ms = NULL; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (he->mem_info) { 10658c2ecf20Sopenharmony_ci addr = he->mem_info->daddr.addr; 10668c2ecf20Sopenharmony_ci ms = &he->mem_info->daddr.ms; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ciint64_t 10728c2ecf20Sopenharmony_cisort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right) 10738c2ecf20Sopenharmony_ci{ 10748c2ecf20Sopenharmony_ci uint64_t l = 0, r = 0; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci if (left->mem_info) 10778c2ecf20Sopenharmony_ci l = left->mem_info->iaddr.addr; 10788c2ecf20Sopenharmony_ci if (right->mem_info) 10798c2ecf20Sopenharmony_ci r = right->mem_info->iaddr.addr; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci return (int64_t)(r - l); 10828c2ecf20Sopenharmony_ci} 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_cistatic int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf, 10858c2ecf20Sopenharmony_ci size_t size, unsigned int width) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci uint64_t addr = 0; 10888c2ecf20Sopenharmony_ci struct map_symbol *ms = NULL; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci if (he->mem_info) { 10918c2ecf20Sopenharmony_ci addr = he->mem_info->iaddr.addr; 10928c2ecf20Sopenharmony_ci ms = &he->mem_info->iaddr.ms; 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width); 10958c2ecf20Sopenharmony_ci} 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_cistatic int64_t 10988c2ecf20Sopenharmony_cisort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci struct map *map_l = NULL; 11018c2ecf20Sopenharmony_ci struct map *map_r = NULL; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci if (left->mem_info) 11048c2ecf20Sopenharmony_ci map_l = left->mem_info->daddr.ms.map; 11058c2ecf20Sopenharmony_ci if (right->mem_info) 11068c2ecf20Sopenharmony_ci map_r = right->mem_info->daddr.ms.map; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci return _sort__dso_cmp(map_l, map_r); 11098c2ecf20Sopenharmony_ci} 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_cistatic int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, 11128c2ecf20Sopenharmony_ci size_t size, unsigned int width) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci struct map *map = NULL; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci if (he->mem_info) 11178c2ecf20Sopenharmony_ci map = he->mem_info->daddr.ms.map; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci return _hist_entry__dso_snprintf(map, bf, size, width); 11208c2ecf20Sopenharmony_ci} 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_cistatic int64_t 11238c2ecf20Sopenharmony_cisort__locked_cmp(struct hist_entry *left, struct hist_entry *right) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_l; 11268c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_r; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci if (left->mem_info) 11298c2ecf20Sopenharmony_ci data_src_l = left->mem_info->data_src; 11308c2ecf20Sopenharmony_ci else 11318c2ecf20Sopenharmony_ci data_src_l.mem_lock = PERF_MEM_LOCK_NA; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci if (right->mem_info) 11348c2ecf20Sopenharmony_ci data_src_r = right->mem_info->data_src; 11358c2ecf20Sopenharmony_ci else 11368c2ecf20Sopenharmony_ci data_src_r.mem_lock = PERF_MEM_LOCK_NA; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock); 11398c2ecf20Sopenharmony_ci} 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_cistatic int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, 11428c2ecf20Sopenharmony_ci size_t size, unsigned int width) 11438c2ecf20Sopenharmony_ci{ 11448c2ecf20Sopenharmony_ci char out[10]; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci perf_mem__lck_scnprintf(out, sizeof(out), he->mem_info); 11478c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%.*s", width, out); 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic int64_t 11518c2ecf20Sopenharmony_cisort__tlb_cmp(struct hist_entry *left, struct hist_entry *right) 11528c2ecf20Sopenharmony_ci{ 11538c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_l; 11548c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_r; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci if (left->mem_info) 11578c2ecf20Sopenharmony_ci data_src_l = left->mem_info->data_src; 11588c2ecf20Sopenharmony_ci else 11598c2ecf20Sopenharmony_ci data_src_l.mem_dtlb = PERF_MEM_TLB_NA; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci if (right->mem_info) 11628c2ecf20Sopenharmony_ci data_src_r = right->mem_info->data_src; 11638c2ecf20Sopenharmony_ci else 11648c2ecf20Sopenharmony_ci data_src_r.mem_dtlb = PERF_MEM_TLB_NA; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb); 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, 11708c2ecf20Sopenharmony_ci size_t size, unsigned int width) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci char out[64]; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci perf_mem__tlb_scnprintf(out, sizeof(out), he->mem_info); 11758c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, out); 11768c2ecf20Sopenharmony_ci} 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_cistatic int64_t 11798c2ecf20Sopenharmony_cisort__lvl_cmp(struct hist_entry *left, struct hist_entry *right) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_l; 11828c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_r; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci if (left->mem_info) 11858c2ecf20Sopenharmony_ci data_src_l = left->mem_info->data_src; 11868c2ecf20Sopenharmony_ci else 11878c2ecf20Sopenharmony_ci data_src_l.mem_lvl = PERF_MEM_LVL_NA; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci if (right->mem_info) 11908c2ecf20Sopenharmony_ci data_src_r = right->mem_info->data_src; 11918c2ecf20Sopenharmony_ci else 11928c2ecf20Sopenharmony_ci data_src_r.mem_lvl = PERF_MEM_LVL_NA; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl); 11958c2ecf20Sopenharmony_ci} 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_cistatic int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, 11988c2ecf20Sopenharmony_ci size_t size, unsigned int width) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci char out[64]; 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci perf_mem__lvl_scnprintf(out, sizeof(out), he->mem_info); 12038c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, out); 12048c2ecf20Sopenharmony_ci} 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_cistatic int64_t 12078c2ecf20Sopenharmony_cisort__snoop_cmp(struct hist_entry *left, struct hist_entry *right) 12088c2ecf20Sopenharmony_ci{ 12098c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_l; 12108c2ecf20Sopenharmony_ci union perf_mem_data_src data_src_r; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (left->mem_info) 12138c2ecf20Sopenharmony_ci data_src_l = left->mem_info->data_src; 12148c2ecf20Sopenharmony_ci else 12158c2ecf20Sopenharmony_ci data_src_l.mem_snoop = PERF_MEM_SNOOP_NA; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci if (right->mem_info) 12188c2ecf20Sopenharmony_ci data_src_r = right->mem_info->data_src; 12198c2ecf20Sopenharmony_ci else 12208c2ecf20Sopenharmony_ci data_src_r.mem_snoop = PERF_MEM_SNOOP_NA; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop); 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, 12268c2ecf20Sopenharmony_ci size_t size, unsigned int width) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci char out[64]; 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci perf_mem__snp_scnprintf(out, sizeof(out), he->mem_info); 12318c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, out); 12328c2ecf20Sopenharmony_ci} 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ciint64_t 12358c2ecf20Sopenharmony_cisort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci u64 l, r; 12388c2ecf20Sopenharmony_ci struct map *l_map, *r_map; 12398c2ecf20Sopenharmony_ci int rc; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci if (!left->mem_info) return -1; 12428c2ecf20Sopenharmony_ci if (!right->mem_info) return 1; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci /* group event types together */ 12458c2ecf20Sopenharmony_ci if (left->cpumode > right->cpumode) return -1; 12468c2ecf20Sopenharmony_ci if (left->cpumode < right->cpumode) return 1; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci l_map = left->mem_info->daddr.ms.map; 12498c2ecf20Sopenharmony_ci r_map = right->mem_info->daddr.ms.map; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci /* if both are NULL, jump to sort on al_addr instead */ 12528c2ecf20Sopenharmony_ci if (!l_map && !r_map) 12538c2ecf20Sopenharmony_ci goto addr; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci if (!l_map) return -1; 12568c2ecf20Sopenharmony_ci if (!r_map) return 1; 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci rc = dso__cmp_id(l_map->dso, r_map->dso); 12598c2ecf20Sopenharmony_ci if (rc) 12608c2ecf20Sopenharmony_ci return rc; 12618c2ecf20Sopenharmony_ci /* 12628c2ecf20Sopenharmony_ci * Addresses with no major/minor numbers are assumed to be 12638c2ecf20Sopenharmony_ci * anonymous in userspace. Sort those on pid then address. 12648c2ecf20Sopenharmony_ci * 12658c2ecf20Sopenharmony_ci * The kernel and non-zero major/minor mapped areas are 12668c2ecf20Sopenharmony_ci * assumed to be unity mapped. Sort those on address. 12678c2ecf20Sopenharmony_ci */ 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci if ((left->cpumode != PERF_RECORD_MISC_KERNEL) && 12708c2ecf20Sopenharmony_ci (!(l_map->flags & MAP_SHARED)) && 12718c2ecf20Sopenharmony_ci !l_map->dso->id.maj && !l_map->dso->id.min && 12728c2ecf20Sopenharmony_ci !l_map->dso->id.ino && !l_map->dso->id.ino_generation) { 12738c2ecf20Sopenharmony_ci /* userspace anonymous */ 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci if (left->thread->pid_ > right->thread->pid_) return -1; 12768c2ecf20Sopenharmony_ci if (left->thread->pid_ < right->thread->pid_) return 1; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ciaddr: 12808c2ecf20Sopenharmony_ci /* al_addr does all the right addr - start + offset calculations */ 12818c2ecf20Sopenharmony_ci l = cl_address(left->mem_info->daddr.al_addr); 12828c2ecf20Sopenharmony_ci r = cl_address(right->mem_info->daddr.al_addr); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci if (l > r) return -1; 12858c2ecf20Sopenharmony_ci if (l < r) return 1; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci return 0; 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cistatic int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf, 12918c2ecf20Sopenharmony_ci size_t size, unsigned int width) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci uint64_t addr = 0; 12958c2ecf20Sopenharmony_ci struct map_symbol *ms = NULL; 12968c2ecf20Sopenharmony_ci char level = he->level; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci if (he->mem_info) { 12998c2ecf20Sopenharmony_ci struct map *map = he->mem_info->daddr.ms.map; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci addr = cl_address(he->mem_info->daddr.al_addr); 13028c2ecf20Sopenharmony_ci ms = &he->mem_info->daddr.ms; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci /* print [s] for shared data mmaps */ 13058c2ecf20Sopenharmony_ci if ((he->cpumode != PERF_RECORD_MISC_KERNEL) && 13068c2ecf20Sopenharmony_ci map && !(map->prot & PROT_EXEC) && 13078c2ecf20Sopenharmony_ci (map->flags & MAP_SHARED) && 13088c2ecf20Sopenharmony_ci (map->dso->id.maj || map->dso->id.min || 13098c2ecf20Sopenharmony_ci map->dso->id.ino || map->dso->id.ino_generation)) 13108c2ecf20Sopenharmony_ci level = 's'; 13118c2ecf20Sopenharmony_ci else if (!map) 13128c2ecf20Sopenharmony_ci level = 'X'; 13138c2ecf20Sopenharmony_ci } 13148c2ecf20Sopenharmony_ci return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width); 13158c2ecf20Sopenharmony_ci} 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_cistruct sort_entry sort_mispredict = { 13188c2ecf20Sopenharmony_ci .se_header = "Branch Mispredicted", 13198c2ecf20Sopenharmony_ci .se_cmp = sort__mispredict_cmp, 13208c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__mispredict_snprintf, 13218c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MISPREDICT, 13228c2ecf20Sopenharmony_ci}; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_cistatic u64 he_weight(struct hist_entry *he) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0; 13278c2ecf20Sopenharmony_ci} 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_cistatic int64_t 13308c2ecf20Sopenharmony_cisort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci return he_weight(left) - he_weight(right); 13338c2ecf20Sopenharmony_ci} 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_cistatic int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, 13368c2ecf20Sopenharmony_ci size_t size, unsigned int width) 13378c2ecf20Sopenharmony_ci{ 13388c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_cistruct sort_entry sort_local_weight = { 13428c2ecf20Sopenharmony_ci .se_header = "Local Weight", 13438c2ecf20Sopenharmony_ci .se_cmp = sort__local_weight_cmp, 13448c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__local_weight_snprintf, 13458c2ecf20Sopenharmony_ci .se_width_idx = HISTC_LOCAL_WEIGHT, 13468c2ecf20Sopenharmony_ci}; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_cistatic int64_t 13498c2ecf20Sopenharmony_cisort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) 13508c2ecf20Sopenharmony_ci{ 13518c2ecf20Sopenharmony_ci return left->stat.weight - right->stat.weight; 13528c2ecf20Sopenharmony_ci} 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_cistatic int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, 13558c2ecf20Sopenharmony_ci size_t size, unsigned int width) 13568c2ecf20Sopenharmony_ci{ 13578c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_cistruct sort_entry sort_global_weight = { 13618c2ecf20Sopenharmony_ci .se_header = "Weight", 13628c2ecf20Sopenharmony_ci .se_cmp = sort__global_weight_cmp, 13638c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__global_weight_snprintf, 13648c2ecf20Sopenharmony_ci .se_width_idx = HISTC_GLOBAL_WEIGHT, 13658c2ecf20Sopenharmony_ci}; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_cistruct sort_entry sort_mem_daddr_sym = { 13688c2ecf20Sopenharmony_ci .se_header = "Data Symbol", 13698c2ecf20Sopenharmony_ci .se_cmp = sort__daddr_cmp, 13708c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__daddr_snprintf, 13718c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_DADDR_SYMBOL, 13728c2ecf20Sopenharmony_ci}; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistruct sort_entry sort_mem_iaddr_sym = { 13758c2ecf20Sopenharmony_ci .se_header = "Code Symbol", 13768c2ecf20Sopenharmony_ci .se_cmp = sort__iaddr_cmp, 13778c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__iaddr_snprintf, 13788c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_IADDR_SYMBOL, 13798c2ecf20Sopenharmony_ci}; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistruct sort_entry sort_mem_daddr_dso = { 13828c2ecf20Sopenharmony_ci .se_header = "Data Object", 13838c2ecf20Sopenharmony_ci .se_cmp = sort__dso_daddr_cmp, 13848c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dso_daddr_snprintf, 13858c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_DADDR_DSO, 13868c2ecf20Sopenharmony_ci}; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_cistruct sort_entry sort_mem_locked = { 13898c2ecf20Sopenharmony_ci .se_header = "Locked", 13908c2ecf20Sopenharmony_ci .se_cmp = sort__locked_cmp, 13918c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__locked_snprintf, 13928c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_LOCKED, 13938c2ecf20Sopenharmony_ci}; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cistruct sort_entry sort_mem_tlb = { 13968c2ecf20Sopenharmony_ci .se_header = "TLB access", 13978c2ecf20Sopenharmony_ci .se_cmp = sort__tlb_cmp, 13988c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__tlb_snprintf, 13998c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_TLB, 14008c2ecf20Sopenharmony_ci}; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_cistruct sort_entry sort_mem_lvl = { 14038c2ecf20Sopenharmony_ci .se_header = "Memory access", 14048c2ecf20Sopenharmony_ci .se_cmp = sort__lvl_cmp, 14058c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__lvl_snprintf, 14068c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_LVL, 14078c2ecf20Sopenharmony_ci}; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_cistruct sort_entry sort_mem_snoop = { 14108c2ecf20Sopenharmony_ci .se_header = "Snoop", 14118c2ecf20Sopenharmony_ci .se_cmp = sort__snoop_cmp, 14128c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__snoop_snprintf, 14138c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_SNOOP, 14148c2ecf20Sopenharmony_ci}; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistruct sort_entry sort_mem_dcacheline = { 14178c2ecf20Sopenharmony_ci .se_header = "Data Cacheline", 14188c2ecf20Sopenharmony_ci .se_cmp = sort__dcacheline_cmp, 14198c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dcacheline_snprintf, 14208c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_DCACHELINE, 14218c2ecf20Sopenharmony_ci}; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_cistatic int64_t 14248c2ecf20Sopenharmony_cisort__phys_daddr_cmp(struct hist_entry *left, struct hist_entry *right) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci uint64_t l = 0, r = 0; 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci if (left->mem_info) 14298c2ecf20Sopenharmony_ci l = left->mem_info->daddr.phys_addr; 14308c2ecf20Sopenharmony_ci if (right->mem_info) 14318c2ecf20Sopenharmony_ci r = right->mem_info->daddr.phys_addr; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci return (int64_t)(r - l); 14348c2ecf20Sopenharmony_ci} 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_cistatic int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf, 14378c2ecf20Sopenharmony_ci size_t size, unsigned int width) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci uint64_t addr = 0; 14408c2ecf20Sopenharmony_ci size_t ret = 0; 14418c2ecf20Sopenharmony_ci size_t len = BITS_PER_LONG / 4; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci addr = he->mem_info->daddr.phys_addr; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", he->level); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, addr); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci ret += repsep_snprintf(bf + ret, size - ret, "%-*s", width - ret, ""); 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci if (ret > width) 14528c2ecf20Sopenharmony_ci bf[width] = '\0'; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci return width; 14558c2ecf20Sopenharmony_ci} 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_cistruct sort_entry sort_mem_phys_daddr = { 14588c2ecf20Sopenharmony_ci .se_header = "Data Physical Address", 14598c2ecf20Sopenharmony_ci .se_cmp = sort__phys_daddr_cmp, 14608c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__phys_daddr_snprintf, 14618c2ecf20Sopenharmony_ci .se_width_idx = HISTC_MEM_PHYS_DADDR, 14628c2ecf20Sopenharmony_ci}; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_cistatic int64_t 14658c2ecf20Sopenharmony_cisort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 14688c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci return left->branch_info->flags.abort != 14718c2ecf20Sopenharmony_ci right->branch_info->flags.abort; 14728c2ecf20Sopenharmony_ci} 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_cistatic int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, 14758c2ecf20Sopenharmony_ci size_t size, unsigned int width) 14768c2ecf20Sopenharmony_ci{ 14778c2ecf20Sopenharmony_ci static const char *out = "N/A"; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci if (he->branch_info) { 14808c2ecf20Sopenharmony_ci if (he->branch_info->flags.abort) 14818c2ecf20Sopenharmony_ci out = "A"; 14828c2ecf20Sopenharmony_ci else 14838c2ecf20Sopenharmony_ci out = "."; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, out); 14878c2ecf20Sopenharmony_ci} 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_cistruct sort_entry sort_abort = { 14908c2ecf20Sopenharmony_ci .se_header = "Transaction abort", 14918c2ecf20Sopenharmony_ci .se_cmp = sort__abort_cmp, 14928c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__abort_snprintf, 14938c2ecf20Sopenharmony_ci .se_width_idx = HISTC_ABORT, 14948c2ecf20Sopenharmony_ci}; 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_cistatic int64_t 14978c2ecf20Sopenharmony_cisort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) 14988c2ecf20Sopenharmony_ci{ 14998c2ecf20Sopenharmony_ci if (!left->branch_info || !right->branch_info) 15008c2ecf20Sopenharmony_ci return cmp_null(left->branch_info, right->branch_info); 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci return left->branch_info->flags.in_tx != 15038c2ecf20Sopenharmony_ci right->branch_info->flags.in_tx; 15048c2ecf20Sopenharmony_ci} 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_cistatic int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, 15078c2ecf20Sopenharmony_ci size_t size, unsigned int width) 15088c2ecf20Sopenharmony_ci{ 15098c2ecf20Sopenharmony_ci static const char *out = "N/A"; 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci if (he->branch_info) { 15128c2ecf20Sopenharmony_ci if (he->branch_info->flags.in_tx) 15138c2ecf20Sopenharmony_ci out = "T"; 15148c2ecf20Sopenharmony_ci else 15158c2ecf20Sopenharmony_ci out = "."; 15168c2ecf20Sopenharmony_ci } 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, out); 15198c2ecf20Sopenharmony_ci} 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistruct sort_entry sort_in_tx = { 15228c2ecf20Sopenharmony_ci .se_header = "Branch in transaction", 15238c2ecf20Sopenharmony_ci .se_cmp = sort__in_tx_cmp, 15248c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__in_tx_snprintf, 15258c2ecf20Sopenharmony_ci .se_width_idx = HISTC_IN_TX, 15268c2ecf20Sopenharmony_ci}; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_cistatic int64_t 15298c2ecf20Sopenharmony_cisort__transaction_cmp(struct hist_entry *left, struct hist_entry *right) 15308c2ecf20Sopenharmony_ci{ 15318c2ecf20Sopenharmony_ci return left->transaction - right->transaction; 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_cistatic inline char *add_str(char *p, const char *str) 15358c2ecf20Sopenharmony_ci{ 15368c2ecf20Sopenharmony_ci strcpy(p, str); 15378c2ecf20Sopenharmony_ci return p + strlen(str); 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_cistatic struct txbit { 15418c2ecf20Sopenharmony_ci unsigned flag; 15428c2ecf20Sopenharmony_ci const char *name; 15438c2ecf20Sopenharmony_ci int skip_for_len; 15448c2ecf20Sopenharmony_ci} txbits[] = { 15458c2ecf20Sopenharmony_ci { PERF_TXN_ELISION, "EL ", 0 }, 15468c2ecf20Sopenharmony_ci { PERF_TXN_TRANSACTION, "TX ", 1 }, 15478c2ecf20Sopenharmony_ci { PERF_TXN_SYNC, "SYNC ", 1 }, 15488c2ecf20Sopenharmony_ci { PERF_TXN_ASYNC, "ASYNC ", 0 }, 15498c2ecf20Sopenharmony_ci { PERF_TXN_RETRY, "RETRY ", 0 }, 15508c2ecf20Sopenharmony_ci { PERF_TXN_CONFLICT, "CON ", 0 }, 15518c2ecf20Sopenharmony_ci { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 }, 15528c2ecf20Sopenharmony_ci { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 }, 15538c2ecf20Sopenharmony_ci { 0, NULL, 0 } 15548c2ecf20Sopenharmony_ci}; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ciint hist_entry__transaction_len(void) 15578c2ecf20Sopenharmony_ci{ 15588c2ecf20Sopenharmony_ci int i; 15598c2ecf20Sopenharmony_ci int len = 0; 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci for (i = 0; txbits[i].name; i++) { 15628c2ecf20Sopenharmony_ci if (!txbits[i].skip_for_len) 15638c2ecf20Sopenharmony_ci len += strlen(txbits[i].name); 15648c2ecf20Sopenharmony_ci } 15658c2ecf20Sopenharmony_ci len += 4; /* :XX<space> */ 15668c2ecf20Sopenharmony_ci return len; 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_cistatic int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf, 15708c2ecf20Sopenharmony_ci size_t size, unsigned int width) 15718c2ecf20Sopenharmony_ci{ 15728c2ecf20Sopenharmony_ci u64 t = he->transaction; 15738c2ecf20Sopenharmony_ci char buf[128]; 15748c2ecf20Sopenharmony_ci char *p = buf; 15758c2ecf20Sopenharmony_ci int i; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci buf[0] = 0; 15788c2ecf20Sopenharmony_ci for (i = 0; txbits[i].name; i++) 15798c2ecf20Sopenharmony_ci if (txbits[i].flag & t) 15808c2ecf20Sopenharmony_ci p = add_str(p, txbits[i].name); 15818c2ecf20Sopenharmony_ci if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC))) 15828c2ecf20Sopenharmony_ci p = add_str(p, "NEITHER "); 15838c2ecf20Sopenharmony_ci if (t & PERF_TXN_ABORT_MASK) { 15848c2ecf20Sopenharmony_ci sprintf(p, ":%" PRIx64, 15858c2ecf20Sopenharmony_ci (t & PERF_TXN_ABORT_MASK) >> 15868c2ecf20Sopenharmony_ci PERF_TXN_ABORT_SHIFT); 15878c2ecf20Sopenharmony_ci p += strlen(p); 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci return repsep_snprintf(bf, size, "%-*s", width, buf); 15918c2ecf20Sopenharmony_ci} 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_cistruct sort_entry sort_transaction = { 15948c2ecf20Sopenharmony_ci .se_header = "Transaction ", 15958c2ecf20Sopenharmony_ci .se_cmp = sort__transaction_cmp, 15968c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__transaction_snprintf, 15978c2ecf20Sopenharmony_ci .se_width_idx = HISTC_TRANSACTION, 15988c2ecf20Sopenharmony_ci}; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci/* --sort symbol_size */ 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_cistatic int64_t _sort__sym_size_cmp(struct symbol *sym_l, struct symbol *sym_r) 16038c2ecf20Sopenharmony_ci{ 16048c2ecf20Sopenharmony_ci int64_t size_l = sym_l != NULL ? symbol__size(sym_l) : 0; 16058c2ecf20Sopenharmony_ci int64_t size_r = sym_r != NULL ? symbol__size(sym_r) : 0; 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci return size_l < size_r ? -1 : 16088c2ecf20Sopenharmony_ci size_l == size_r ? 0 : 1; 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_cistatic int64_t 16128c2ecf20Sopenharmony_cisort__sym_size_cmp(struct hist_entry *left, struct hist_entry *right) 16138c2ecf20Sopenharmony_ci{ 16148c2ecf20Sopenharmony_ci return _sort__sym_size_cmp(right->ms.sym, left->ms.sym); 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_cistatic int _hist_entry__sym_size_snprintf(struct symbol *sym, char *bf, 16188c2ecf20Sopenharmony_ci size_t bf_size, unsigned int width) 16198c2ecf20Sopenharmony_ci{ 16208c2ecf20Sopenharmony_ci if (sym) 16218c2ecf20Sopenharmony_ci return repsep_snprintf(bf, bf_size, "%*d", width, symbol__size(sym)); 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci return repsep_snprintf(bf, bf_size, "%*s", width, "unknown"); 16248c2ecf20Sopenharmony_ci} 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_cistatic int hist_entry__sym_size_snprintf(struct hist_entry *he, char *bf, 16278c2ecf20Sopenharmony_ci size_t size, unsigned int width) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci return _hist_entry__sym_size_snprintf(he->ms.sym, bf, size, width); 16308c2ecf20Sopenharmony_ci} 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_cistruct sort_entry sort_sym_size = { 16338c2ecf20Sopenharmony_ci .se_header = "Symbol size", 16348c2ecf20Sopenharmony_ci .se_cmp = sort__sym_size_cmp, 16358c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__sym_size_snprintf, 16368c2ecf20Sopenharmony_ci .se_width_idx = HISTC_SYM_SIZE, 16378c2ecf20Sopenharmony_ci}; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci/* --sort dso_size */ 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_cistatic int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci int64_t size_l = map_l != NULL ? map__size(map_l) : 0; 16448c2ecf20Sopenharmony_ci int64_t size_r = map_r != NULL ? map__size(map_r) : 0; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci return size_l < size_r ? -1 : 16478c2ecf20Sopenharmony_ci size_l == size_r ? 0 : 1; 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_cistatic int64_t 16518c2ecf20Sopenharmony_cisort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right) 16528c2ecf20Sopenharmony_ci{ 16538c2ecf20Sopenharmony_ci return _sort__dso_size_cmp(right->ms.map, left->ms.map); 16548c2ecf20Sopenharmony_ci} 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_cistatic int _hist_entry__dso_size_snprintf(struct map *map, char *bf, 16578c2ecf20Sopenharmony_ci size_t bf_size, unsigned int width) 16588c2ecf20Sopenharmony_ci{ 16598c2ecf20Sopenharmony_ci if (map && map->dso) 16608c2ecf20Sopenharmony_ci return repsep_snprintf(bf, bf_size, "%*d", width, 16618c2ecf20Sopenharmony_ci map__size(map)); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci return repsep_snprintf(bf, bf_size, "%*s", width, "unknown"); 16648c2ecf20Sopenharmony_ci} 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_cistatic int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf, 16678c2ecf20Sopenharmony_ci size_t size, unsigned int width) 16688c2ecf20Sopenharmony_ci{ 16698c2ecf20Sopenharmony_ci return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width); 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_cistruct sort_entry sort_dso_size = { 16738c2ecf20Sopenharmony_ci .se_header = "DSO size", 16748c2ecf20Sopenharmony_ci .se_cmp = sort__dso_size_cmp, 16758c2ecf20Sopenharmony_ci .se_snprintf = hist_entry__dso_size_snprintf, 16768c2ecf20Sopenharmony_ci .se_width_idx = HISTC_DSO_SIZE, 16778c2ecf20Sopenharmony_ci}; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_cistruct sort_dimension { 16818c2ecf20Sopenharmony_ci const char *name; 16828c2ecf20Sopenharmony_ci struct sort_entry *entry; 16838c2ecf20Sopenharmony_ci int taken; 16848c2ecf20Sopenharmony_ci}; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) } 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_cistatic struct sort_dimension common_sort_dimensions[] = { 16898c2ecf20Sopenharmony_ci DIM(SORT_PID, "pid", sort_thread), 16908c2ecf20Sopenharmony_ci DIM(SORT_COMM, "comm", sort_comm), 16918c2ecf20Sopenharmony_ci DIM(SORT_DSO, "dso", sort_dso), 16928c2ecf20Sopenharmony_ci DIM(SORT_SYM, "symbol", sort_sym), 16938c2ecf20Sopenharmony_ci DIM(SORT_PARENT, "parent", sort_parent), 16948c2ecf20Sopenharmony_ci DIM(SORT_CPU, "cpu", sort_cpu), 16958c2ecf20Sopenharmony_ci DIM(SORT_SOCKET, "socket", sort_socket), 16968c2ecf20Sopenharmony_ci DIM(SORT_SRCLINE, "srcline", sort_srcline), 16978c2ecf20Sopenharmony_ci DIM(SORT_SRCFILE, "srcfile", sort_srcfile), 16988c2ecf20Sopenharmony_ci DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 16998c2ecf20Sopenharmony_ci DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 17008c2ecf20Sopenharmony_ci DIM(SORT_TRANSACTION, "transaction", sort_transaction), 17018c2ecf20Sopenharmony_ci DIM(SORT_TRACE, "trace", sort_trace), 17028c2ecf20Sopenharmony_ci DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), 17038c2ecf20Sopenharmony_ci DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), 17048c2ecf20Sopenharmony_ci DIM(SORT_CGROUP, "cgroup", sort_cgroup), 17058c2ecf20Sopenharmony_ci DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 17068c2ecf20Sopenharmony_ci DIM(SORT_SYM_IPC_NULL, "ipc_null", sort_sym_ipc_null), 17078c2ecf20Sopenharmony_ci DIM(SORT_TIME, "time", sort_time), 17088c2ecf20Sopenharmony_ci}; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci#undef DIM 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_cistatic struct sort_dimension bstack_sort_dimensions[] = { 17158c2ecf20Sopenharmony_ci DIM(SORT_DSO_FROM, "dso_from", sort_dso_from), 17168c2ecf20Sopenharmony_ci DIM(SORT_DSO_TO, "dso_to", sort_dso_to), 17178c2ecf20Sopenharmony_ci DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), 17188c2ecf20Sopenharmony_ci DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), 17198c2ecf20Sopenharmony_ci DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 17208c2ecf20Sopenharmony_ci DIM(SORT_IN_TX, "in_tx", sort_in_tx), 17218c2ecf20Sopenharmony_ci DIM(SORT_ABORT, "abort", sort_abort), 17228c2ecf20Sopenharmony_ci DIM(SORT_CYCLES, "cycles", sort_cycles), 17238c2ecf20Sopenharmony_ci DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from), 17248c2ecf20Sopenharmony_ci DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to), 17258c2ecf20Sopenharmony_ci DIM(SORT_SYM_IPC, "ipc_lbr", sort_sym_ipc), 17268c2ecf20Sopenharmony_ci}; 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci#undef DIM 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) } 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_cistatic struct sort_dimension memory_sort_dimensions[] = { 17338c2ecf20Sopenharmony_ci DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), 17348c2ecf20Sopenharmony_ci DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym), 17358c2ecf20Sopenharmony_ci DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), 17368c2ecf20Sopenharmony_ci DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), 17378c2ecf20Sopenharmony_ci DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), 17388c2ecf20Sopenharmony_ci DIM(SORT_MEM_LVL, "mem", sort_mem_lvl), 17398c2ecf20Sopenharmony_ci DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop), 17408c2ecf20Sopenharmony_ci DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline), 17418c2ecf20Sopenharmony_ci DIM(SORT_MEM_PHYS_DADDR, "phys_daddr", sort_mem_phys_daddr), 17428c2ecf20Sopenharmony_ci}; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci#undef DIM 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_cistruct hpp_dimension { 17478c2ecf20Sopenharmony_ci const char *name; 17488c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 17498c2ecf20Sopenharmony_ci int taken; 17508c2ecf20Sopenharmony_ci}; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci#define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], } 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_cistatic struct hpp_dimension hpp_sort_dimensions[] = { 17558c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD, "overhead"), 17568c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"), 17578c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD_US, "overhead_us"), 17588c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"), 17598c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"), 17608c2ecf20Sopenharmony_ci DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"), 17618c2ecf20Sopenharmony_ci DIM(PERF_HPP__SAMPLES, "sample"), 17628c2ecf20Sopenharmony_ci DIM(PERF_HPP__PERIOD, "period"), 17638c2ecf20Sopenharmony_ci}; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci#undef DIM 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_cistruct hpp_sort_entry { 17688c2ecf20Sopenharmony_ci struct perf_hpp_fmt hpp; 17698c2ecf20Sopenharmony_ci struct sort_entry *se; 17708c2ecf20Sopenharmony_ci}; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_civoid perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists) 17738c2ecf20Sopenharmony_ci{ 17748c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 17778c2ecf20Sopenharmony_ci return; 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 17808c2ecf20Sopenharmony_ci hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name)); 17818c2ecf20Sopenharmony_ci} 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_cistatic int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 17848c2ecf20Sopenharmony_ci struct hists *hists, int line __maybe_unused, 17858c2ecf20Sopenharmony_ci int *span __maybe_unused) 17868c2ecf20Sopenharmony_ci{ 17878c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 17888c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci if (!len) 17938c2ecf20Sopenharmony_ci len = hists__col_len(hists, hse->se->se_width_idx); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); 17968c2ecf20Sopenharmony_ci} 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_cistatic int __sort__hpp_width(struct perf_hpp_fmt *fmt, 17998c2ecf20Sopenharmony_ci struct perf_hpp *hpp __maybe_unused, 18008c2ecf20Sopenharmony_ci struct hists *hists) 18018c2ecf20Sopenharmony_ci{ 18028c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 18038c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci if (!len) 18088c2ecf20Sopenharmony_ci len = hists__col_len(hists, hse->se->se_width_idx); 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci return len; 18118c2ecf20Sopenharmony_ci} 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_cistatic int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 18148c2ecf20Sopenharmony_ci struct hist_entry *he) 18158c2ecf20Sopenharmony_ci{ 18168c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 18178c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci if (!len) 18228c2ecf20Sopenharmony_ci len = hists__col_len(he->hists, hse->se->se_width_idx); 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 18258c2ecf20Sopenharmony_ci} 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_cistatic int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt, 18288c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 18298c2ecf20Sopenharmony_ci{ 18308c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 18338c2ecf20Sopenharmony_ci return hse->se->se_cmp(a, b); 18348c2ecf20Sopenharmony_ci} 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_cistatic int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt, 18378c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 18388c2ecf20Sopenharmony_ci{ 18398c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 18408c2ecf20Sopenharmony_ci int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *); 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 18438c2ecf20Sopenharmony_ci collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp; 18448c2ecf20Sopenharmony_ci return collapse_fn(a, b); 18458c2ecf20Sopenharmony_ci} 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_cistatic int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt, 18488c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 18498c2ecf20Sopenharmony_ci{ 18508c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 18518c2ecf20Sopenharmony_ci int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *); 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 18548c2ecf20Sopenharmony_ci sort_fn = hse->se->se_sort ?: hse->se->se_cmp; 18558c2ecf20Sopenharmony_ci return sort_fn(a, b); 18568c2ecf20Sopenharmony_ci} 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_cibool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) 18598c2ecf20Sopenharmony_ci{ 18608c2ecf20Sopenharmony_ci return format->header == __sort__hpp_header; 18618c2ecf20Sopenharmony_ci} 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci#define MK_SORT_ENTRY_CHK(key) \ 18648c2ecf20Sopenharmony_cibool perf_hpp__is_ ## key ## _entry(struct perf_hpp_fmt *fmt) \ 18658c2ecf20Sopenharmony_ci{ \ 18668c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; \ 18678c2ecf20Sopenharmony_ci \ 18688c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) \ 18698c2ecf20Sopenharmony_ci return false; \ 18708c2ecf20Sopenharmony_ci \ 18718c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); \ 18728c2ecf20Sopenharmony_ci return hse->se == &sort_ ## key ; \ 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(trace) 18768c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(srcline) 18778c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(srcfile) 18788c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(thread) 18798c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(comm) 18808c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(dso) 18818c2ecf20Sopenharmony_ciMK_SORT_ENTRY_CHK(sym) 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_cistatic bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 18858c2ecf20Sopenharmony_ci{ 18868c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse_a; 18878c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse_b; 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) 18908c2ecf20Sopenharmony_ci return false; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci hse_a = container_of(a, struct hpp_sort_entry, hpp); 18938c2ecf20Sopenharmony_ci hse_b = container_of(b, struct hpp_sort_entry, hpp); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci return hse_a->se == hse_b->se; 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic void hse_free(struct perf_hpp_fmt *fmt) 18998c2ecf20Sopenharmony_ci{ 19008c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 19038c2ecf20Sopenharmony_ci free(hse); 19048c2ecf20Sopenharmony_ci} 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_cistatic struct hpp_sort_entry * 19078c2ecf20Sopenharmony_ci__sort_dimension__alloc_hpp(struct sort_dimension *sd, int level) 19088c2ecf20Sopenharmony_ci{ 19098c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci hse = malloc(sizeof(*hse)); 19128c2ecf20Sopenharmony_ci if (hse == NULL) { 19138c2ecf20Sopenharmony_ci pr_err("Memory allocation failed\n"); 19148c2ecf20Sopenharmony_ci return NULL; 19158c2ecf20Sopenharmony_ci } 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci hse->se = sd->entry; 19188c2ecf20Sopenharmony_ci hse->hpp.name = sd->entry->se_header; 19198c2ecf20Sopenharmony_ci hse->hpp.header = __sort__hpp_header; 19208c2ecf20Sopenharmony_ci hse->hpp.width = __sort__hpp_width; 19218c2ecf20Sopenharmony_ci hse->hpp.entry = __sort__hpp_entry; 19228c2ecf20Sopenharmony_ci hse->hpp.color = NULL; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci hse->hpp.cmp = __sort__hpp_cmp; 19258c2ecf20Sopenharmony_ci hse->hpp.collapse = __sort__hpp_collapse; 19268c2ecf20Sopenharmony_ci hse->hpp.sort = __sort__hpp_sort; 19278c2ecf20Sopenharmony_ci hse->hpp.equal = __sort__hpp_equal; 19288c2ecf20Sopenharmony_ci hse->hpp.free = hse_free; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hse->hpp.list); 19318c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hse->hpp.sort_list); 19328c2ecf20Sopenharmony_ci hse->hpp.elide = false; 19338c2ecf20Sopenharmony_ci hse->hpp.len = 0; 19348c2ecf20Sopenharmony_ci hse->hpp.user_len = 0; 19358c2ecf20Sopenharmony_ci hse->hpp.level = level; 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci return hse; 19388c2ecf20Sopenharmony_ci} 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_cistatic void hpp_free(struct perf_hpp_fmt *fmt) 19418c2ecf20Sopenharmony_ci{ 19428c2ecf20Sopenharmony_ci free(fmt); 19438c2ecf20Sopenharmony_ci} 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_cistatic struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd, 19468c2ecf20Sopenharmony_ci int level) 19478c2ecf20Sopenharmony_ci{ 19488c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci fmt = memdup(hd->fmt, sizeof(*fmt)); 19518c2ecf20Sopenharmony_ci if (fmt) { 19528c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fmt->list); 19538c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fmt->sort_list); 19548c2ecf20Sopenharmony_ci fmt->free = hpp_free; 19558c2ecf20Sopenharmony_ci fmt->level = level; 19568c2ecf20Sopenharmony_ci } 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci return fmt; 19598c2ecf20Sopenharmony_ci} 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ciint hist_entry__filter(struct hist_entry *he, int type, const void *arg) 19628c2ecf20Sopenharmony_ci{ 19638c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 19648c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 19658c2ecf20Sopenharmony_ci int ret = -1; 19668c2ecf20Sopenharmony_ci int r; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci perf_hpp_list__for_each_format(he->hpp_list, fmt) { 19698c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 19708c2ecf20Sopenharmony_ci continue; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 19738c2ecf20Sopenharmony_ci if (hse->se->se_filter == NULL) 19748c2ecf20Sopenharmony_ci continue; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci /* 19778c2ecf20Sopenharmony_ci * hist entry is filtered if any of sort key in the hpp list 19788c2ecf20Sopenharmony_ci * is applied. But it should skip non-matched filter types. 19798c2ecf20Sopenharmony_ci */ 19808c2ecf20Sopenharmony_ci r = hse->se->se_filter(he, type, arg); 19818c2ecf20Sopenharmony_ci if (r >= 0) { 19828c2ecf20Sopenharmony_ci if (ret < 0) 19838c2ecf20Sopenharmony_ci ret = 0; 19848c2ecf20Sopenharmony_ci ret |= r; 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci } 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci return ret; 19898c2ecf20Sopenharmony_ci} 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_cistatic int __sort_dimension__add_hpp_sort(struct sort_dimension *sd, 19928c2ecf20Sopenharmony_ci struct perf_hpp_list *list, 19938c2ecf20Sopenharmony_ci int level) 19948c2ecf20Sopenharmony_ci{ 19958c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level); 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci if (hse == NULL) 19988c2ecf20Sopenharmony_ci return -1; 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci perf_hpp_list__register_sort_field(list, &hse->hpp); 20018c2ecf20Sopenharmony_ci return 0; 20028c2ecf20Sopenharmony_ci} 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_cistatic int __sort_dimension__add_hpp_output(struct sort_dimension *sd, 20058c2ecf20Sopenharmony_ci struct perf_hpp_list *list) 20068c2ecf20Sopenharmony_ci{ 20078c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, 0); 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci if (hse == NULL) 20108c2ecf20Sopenharmony_ci return -1; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci perf_hpp_list__column_register(list, &hse->hpp); 20138c2ecf20Sopenharmony_ci return 0; 20148c2ecf20Sopenharmony_ci} 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_cistruct hpp_dynamic_entry { 20178c2ecf20Sopenharmony_ci struct perf_hpp_fmt hpp; 20188c2ecf20Sopenharmony_ci struct evsel *evsel; 20198c2ecf20Sopenharmony_ci struct tep_format_field *field; 20208c2ecf20Sopenharmony_ci unsigned dynamic_len; 20218c2ecf20Sopenharmony_ci bool raw_trace; 20228c2ecf20Sopenharmony_ci}; 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_cistatic int hde_width(struct hpp_dynamic_entry *hde) 20258c2ecf20Sopenharmony_ci{ 20268c2ecf20Sopenharmony_ci if (!hde->hpp.len) { 20278c2ecf20Sopenharmony_ci int len = hde->dynamic_len; 20288c2ecf20Sopenharmony_ci int namelen = strlen(hde->field->name); 20298c2ecf20Sopenharmony_ci int fieldlen = hde->field->size; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci if (namelen > len) 20328c2ecf20Sopenharmony_ci len = namelen; 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci if (!(hde->field->flags & TEP_FIELD_IS_STRING)) { 20358c2ecf20Sopenharmony_ci /* length for print hex numbers */ 20368c2ecf20Sopenharmony_ci fieldlen = hde->field->size * 2 + 2; 20378c2ecf20Sopenharmony_ci } 20388c2ecf20Sopenharmony_ci if (fieldlen > len) 20398c2ecf20Sopenharmony_ci len = fieldlen; 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci hde->hpp.len = len; 20428c2ecf20Sopenharmony_ci } 20438c2ecf20Sopenharmony_ci return hde->hpp.len; 20448c2ecf20Sopenharmony_ci} 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_cistatic void update_dynamic_len(struct hpp_dynamic_entry *hde, 20478c2ecf20Sopenharmony_ci struct hist_entry *he) 20488c2ecf20Sopenharmony_ci{ 20498c2ecf20Sopenharmony_ci char *str, *pos; 20508c2ecf20Sopenharmony_ci struct tep_format_field *field = hde->field; 20518c2ecf20Sopenharmony_ci size_t namelen; 20528c2ecf20Sopenharmony_ci bool last = false; 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci if (hde->raw_trace) 20558c2ecf20Sopenharmony_ci return; 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci /* parse pretty print result and update max length */ 20588c2ecf20Sopenharmony_ci if (!he->trace_output) 20598c2ecf20Sopenharmony_ci he->trace_output = get_trace_output(he); 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci namelen = strlen(field->name); 20628c2ecf20Sopenharmony_ci str = he->trace_output; 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci while (str) { 20658c2ecf20Sopenharmony_ci pos = strchr(str, ' '); 20668c2ecf20Sopenharmony_ci if (pos == NULL) { 20678c2ecf20Sopenharmony_ci last = true; 20688c2ecf20Sopenharmony_ci pos = str + strlen(str); 20698c2ecf20Sopenharmony_ci } 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci if (!strncmp(str, field->name, namelen)) { 20728c2ecf20Sopenharmony_ci size_t len; 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci str += namelen + 1; 20758c2ecf20Sopenharmony_ci len = pos - str; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci if (len > hde->dynamic_len) 20788c2ecf20Sopenharmony_ci hde->dynamic_len = len; 20798c2ecf20Sopenharmony_ci break; 20808c2ecf20Sopenharmony_ci } 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci if (last) 20838c2ecf20Sopenharmony_ci str = NULL; 20848c2ecf20Sopenharmony_ci else 20858c2ecf20Sopenharmony_ci str = pos + 1; 20868c2ecf20Sopenharmony_ci } 20878c2ecf20Sopenharmony_ci} 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_cistatic int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 20908c2ecf20Sopenharmony_ci struct hists *hists __maybe_unused, 20918c2ecf20Sopenharmony_ci int line __maybe_unused, 20928c2ecf20Sopenharmony_ci int *span __maybe_unused) 20938c2ecf20Sopenharmony_ci{ 20948c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 20958c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci if (!len) 21008c2ecf20Sopenharmony_ci len = hde_width(hde); 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name); 21038c2ecf20Sopenharmony_ci} 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_cistatic int __sort__hde_width(struct perf_hpp_fmt *fmt, 21068c2ecf20Sopenharmony_ci struct perf_hpp *hpp __maybe_unused, 21078c2ecf20Sopenharmony_ci struct hists *hists __maybe_unused) 21088c2ecf20Sopenharmony_ci{ 21098c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 21108c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 21138c2ecf20Sopenharmony_ci 21148c2ecf20Sopenharmony_ci if (!len) 21158c2ecf20Sopenharmony_ci len = hde_width(hde); 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci return len; 21188c2ecf20Sopenharmony_ci} 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_cibool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists) 21218c2ecf20Sopenharmony_ci{ 21228c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci return hists_to_evsel(hists) == hde->evsel; 21278c2ecf20Sopenharmony_ci} 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_cistatic int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 21308c2ecf20Sopenharmony_ci struct hist_entry *he) 21318c2ecf20Sopenharmony_ci{ 21328c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 21338c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 21348c2ecf20Sopenharmony_ci char *str, *pos; 21358c2ecf20Sopenharmony_ci struct tep_format_field *field; 21368c2ecf20Sopenharmony_ci size_t namelen; 21378c2ecf20Sopenharmony_ci bool last = false; 21388c2ecf20Sopenharmony_ci int ret; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci if (!len) 21438c2ecf20Sopenharmony_ci len = hde_width(hde); 21448c2ecf20Sopenharmony_ci 21458c2ecf20Sopenharmony_ci if (hde->raw_trace) 21468c2ecf20Sopenharmony_ci goto raw_field; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci if (!he->trace_output) 21498c2ecf20Sopenharmony_ci he->trace_output = get_trace_output(he); 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci field = hde->field; 21528c2ecf20Sopenharmony_ci namelen = strlen(field->name); 21538c2ecf20Sopenharmony_ci str = he->trace_output; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci while (str) { 21568c2ecf20Sopenharmony_ci pos = strchr(str, ' '); 21578c2ecf20Sopenharmony_ci if (pos == NULL) { 21588c2ecf20Sopenharmony_ci last = true; 21598c2ecf20Sopenharmony_ci pos = str + strlen(str); 21608c2ecf20Sopenharmony_ci } 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci if (!strncmp(str, field->name, namelen)) { 21638c2ecf20Sopenharmony_ci str += namelen + 1; 21648c2ecf20Sopenharmony_ci str = strndup(str, pos - str); 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci if (str == NULL) 21678c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, 21688c2ecf20Sopenharmony_ci "%*.*s", len, len, "ERROR"); 21698c2ecf20Sopenharmony_ci break; 21708c2ecf20Sopenharmony_ci } 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci if (last) 21738c2ecf20Sopenharmony_ci str = NULL; 21748c2ecf20Sopenharmony_ci else 21758c2ecf20Sopenharmony_ci str = pos + 1; 21768c2ecf20Sopenharmony_ci } 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci if (str == NULL) { 21798c2ecf20Sopenharmony_ci struct trace_seq seq; 21808c2ecf20Sopenharmony_ciraw_field: 21818c2ecf20Sopenharmony_ci trace_seq_init(&seq); 21828c2ecf20Sopenharmony_ci tep_print_field(&seq, he->raw_data, hde->field); 21838c2ecf20Sopenharmony_ci str = seq.buffer; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str); 21878c2ecf20Sopenharmony_ci free(str); 21888c2ecf20Sopenharmony_ci return ret; 21898c2ecf20Sopenharmony_ci} 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_cistatic int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt, 21928c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 21938c2ecf20Sopenharmony_ci{ 21948c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 21958c2ecf20Sopenharmony_ci struct tep_format_field *field; 21968c2ecf20Sopenharmony_ci unsigned offset, size; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci if (b == NULL) { 22018c2ecf20Sopenharmony_ci update_dynamic_len(hde, a); 22028c2ecf20Sopenharmony_ci return 0; 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci field = hde->field; 22068c2ecf20Sopenharmony_ci if (field->flags & TEP_FIELD_IS_DYNAMIC) { 22078c2ecf20Sopenharmony_ci unsigned long long dyn; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci tep_read_number_field(field, a->raw_data, &dyn); 22108c2ecf20Sopenharmony_ci offset = dyn & 0xffff; 22118c2ecf20Sopenharmony_ci size = (dyn >> 16) & 0xffff; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci /* record max width for output */ 22148c2ecf20Sopenharmony_ci if (size > hde->dynamic_len) 22158c2ecf20Sopenharmony_ci hde->dynamic_len = size; 22168c2ecf20Sopenharmony_ci } else { 22178c2ecf20Sopenharmony_ci offset = field->offset; 22188c2ecf20Sopenharmony_ci size = field->size; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci return memcmp(a->raw_data + offset, b->raw_data + offset, size); 22228c2ecf20Sopenharmony_ci} 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_cibool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt) 22258c2ecf20Sopenharmony_ci{ 22268c2ecf20Sopenharmony_ci return fmt->cmp == __sort__hde_cmp; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_cistatic bool __sort__hde_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 22308c2ecf20Sopenharmony_ci{ 22318c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde_a; 22328c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde_b; 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci if (!perf_hpp__is_dynamic_entry(a) || !perf_hpp__is_dynamic_entry(b)) 22358c2ecf20Sopenharmony_ci return false; 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci hde_a = container_of(a, struct hpp_dynamic_entry, hpp); 22388c2ecf20Sopenharmony_ci hde_b = container_of(b, struct hpp_dynamic_entry, hpp); 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci return hde_a->field == hde_b->field; 22418c2ecf20Sopenharmony_ci} 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_cistatic void hde_free(struct perf_hpp_fmt *fmt) 22448c2ecf20Sopenharmony_ci{ 22458c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 22488c2ecf20Sopenharmony_ci free(hde); 22498c2ecf20Sopenharmony_ci} 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_cistatic struct hpp_dynamic_entry * 22528c2ecf20Sopenharmony_ci__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field, 22538c2ecf20Sopenharmony_ci int level) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci hde = malloc(sizeof(*hde)); 22588c2ecf20Sopenharmony_ci if (hde == NULL) { 22598c2ecf20Sopenharmony_ci pr_debug("Memory allocation failed\n"); 22608c2ecf20Sopenharmony_ci return NULL; 22618c2ecf20Sopenharmony_ci } 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci hde->evsel = evsel; 22648c2ecf20Sopenharmony_ci hde->field = field; 22658c2ecf20Sopenharmony_ci hde->dynamic_len = 0; 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci hde->hpp.name = field->name; 22688c2ecf20Sopenharmony_ci hde->hpp.header = __sort__hde_header; 22698c2ecf20Sopenharmony_ci hde->hpp.width = __sort__hde_width; 22708c2ecf20Sopenharmony_ci hde->hpp.entry = __sort__hde_entry; 22718c2ecf20Sopenharmony_ci hde->hpp.color = NULL; 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci hde->hpp.cmp = __sort__hde_cmp; 22748c2ecf20Sopenharmony_ci hde->hpp.collapse = __sort__hde_cmp; 22758c2ecf20Sopenharmony_ci hde->hpp.sort = __sort__hde_cmp; 22768c2ecf20Sopenharmony_ci hde->hpp.equal = __sort__hde_equal; 22778c2ecf20Sopenharmony_ci hde->hpp.free = hde_free; 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hde->hpp.list); 22808c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hde->hpp.sort_list); 22818c2ecf20Sopenharmony_ci hde->hpp.elide = false; 22828c2ecf20Sopenharmony_ci hde->hpp.len = 0; 22838c2ecf20Sopenharmony_ci hde->hpp.user_len = 0; 22848c2ecf20Sopenharmony_ci hde->hpp.level = level; 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci return hde; 22878c2ecf20Sopenharmony_ci} 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_cistruct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt) 22908c2ecf20Sopenharmony_ci{ 22918c2ecf20Sopenharmony_ci struct perf_hpp_fmt *new_fmt = NULL; 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci if (perf_hpp__is_sort_entry(fmt)) { 22948c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse, *new_hse; 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 22978c2ecf20Sopenharmony_ci new_hse = memdup(hse, sizeof(*hse)); 22988c2ecf20Sopenharmony_ci if (new_hse) 22998c2ecf20Sopenharmony_ci new_fmt = &new_hse->hpp; 23008c2ecf20Sopenharmony_ci } else if (perf_hpp__is_dynamic_entry(fmt)) { 23018c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde, *new_hde; 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 23048c2ecf20Sopenharmony_ci new_hde = memdup(hde, sizeof(*hde)); 23058c2ecf20Sopenharmony_ci if (new_hde) 23068c2ecf20Sopenharmony_ci new_fmt = &new_hde->hpp; 23078c2ecf20Sopenharmony_ci } else { 23088c2ecf20Sopenharmony_ci new_fmt = memdup(fmt, sizeof(*fmt)); 23098c2ecf20Sopenharmony_ci } 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&new_fmt->list); 23128c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&new_fmt->sort_list); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci return new_fmt; 23158c2ecf20Sopenharmony_ci} 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_cistatic int parse_field_name(char *str, char **event, char **field, char **opt) 23188c2ecf20Sopenharmony_ci{ 23198c2ecf20Sopenharmony_ci char *event_name, *field_name, *opt_name; 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci event_name = str; 23228c2ecf20Sopenharmony_ci field_name = strchr(str, '.'); 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci if (field_name) { 23258c2ecf20Sopenharmony_ci *field_name++ = '\0'; 23268c2ecf20Sopenharmony_ci } else { 23278c2ecf20Sopenharmony_ci event_name = NULL; 23288c2ecf20Sopenharmony_ci field_name = str; 23298c2ecf20Sopenharmony_ci } 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci opt_name = strchr(field_name, '/'); 23328c2ecf20Sopenharmony_ci if (opt_name) 23338c2ecf20Sopenharmony_ci *opt_name++ = '\0'; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci *event = event_name; 23368c2ecf20Sopenharmony_ci *field = field_name; 23378c2ecf20Sopenharmony_ci *opt = opt_name; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci return 0; 23408c2ecf20Sopenharmony_ci} 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci/* find match evsel using a given event name. The event name can be: 23438c2ecf20Sopenharmony_ci * 1. '%' + event index (e.g. '%1' for first event) 23448c2ecf20Sopenharmony_ci * 2. full event name (e.g. sched:sched_switch) 23458c2ecf20Sopenharmony_ci * 3. partial event name (should not contain ':') 23468c2ecf20Sopenharmony_ci */ 23478c2ecf20Sopenharmony_cistatic struct evsel *find_evsel(struct evlist *evlist, char *event_name) 23488c2ecf20Sopenharmony_ci{ 23498c2ecf20Sopenharmony_ci struct evsel *evsel = NULL; 23508c2ecf20Sopenharmony_ci struct evsel *pos; 23518c2ecf20Sopenharmony_ci bool full_name; 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci /* case 1 */ 23548c2ecf20Sopenharmony_ci if (event_name[0] == '%') { 23558c2ecf20Sopenharmony_ci int nr = strtol(event_name+1, NULL, 0); 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci if (nr > evlist->core.nr_entries) 23588c2ecf20Sopenharmony_ci return NULL; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci evsel = evlist__first(evlist); 23618c2ecf20Sopenharmony_ci while (--nr > 0) 23628c2ecf20Sopenharmony_ci evsel = evsel__next(evsel); 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci return evsel; 23658c2ecf20Sopenharmony_ci } 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci full_name = !!strchr(event_name, ':'); 23688c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, pos) { 23698c2ecf20Sopenharmony_ci /* case 2 */ 23708c2ecf20Sopenharmony_ci if (full_name && !strcmp(pos->name, event_name)) 23718c2ecf20Sopenharmony_ci return pos; 23728c2ecf20Sopenharmony_ci /* case 3 */ 23738c2ecf20Sopenharmony_ci if (!full_name && strstr(pos->name, event_name)) { 23748c2ecf20Sopenharmony_ci if (evsel) { 23758c2ecf20Sopenharmony_ci pr_debug("'%s' event is ambiguous: it can be %s or %s\n", 23768c2ecf20Sopenharmony_ci event_name, evsel->name, pos->name); 23778c2ecf20Sopenharmony_ci return NULL; 23788c2ecf20Sopenharmony_ci } 23798c2ecf20Sopenharmony_ci evsel = pos; 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci } 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci return evsel; 23848c2ecf20Sopenharmony_ci} 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_cistatic int __dynamic_dimension__add(struct evsel *evsel, 23878c2ecf20Sopenharmony_ci struct tep_format_field *field, 23888c2ecf20Sopenharmony_ci bool raw_trace, int level) 23898c2ecf20Sopenharmony_ci{ 23908c2ecf20Sopenharmony_ci struct hpp_dynamic_entry *hde; 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci hde = __alloc_dynamic_entry(evsel, field, level); 23938c2ecf20Sopenharmony_ci if (hde == NULL) 23948c2ecf20Sopenharmony_ci return -ENOMEM; 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci hde->raw_trace = raw_trace; 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci perf_hpp__register_sort_field(&hde->hpp); 23998c2ecf20Sopenharmony_ci return 0; 24008c2ecf20Sopenharmony_ci} 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_cistatic int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level) 24038c2ecf20Sopenharmony_ci{ 24048c2ecf20Sopenharmony_ci int ret; 24058c2ecf20Sopenharmony_ci struct tep_format_field *field; 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci field = evsel->tp_format->format.fields; 24088c2ecf20Sopenharmony_ci while (field) { 24098c2ecf20Sopenharmony_ci ret = __dynamic_dimension__add(evsel, field, raw_trace, level); 24108c2ecf20Sopenharmony_ci if (ret < 0) 24118c2ecf20Sopenharmony_ci return ret; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci field = field->next; 24148c2ecf20Sopenharmony_ci } 24158c2ecf20Sopenharmony_ci return 0; 24168c2ecf20Sopenharmony_ci} 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_cistatic int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace, 24198c2ecf20Sopenharmony_ci int level) 24208c2ecf20Sopenharmony_ci{ 24218c2ecf20Sopenharmony_ci int ret; 24228c2ecf20Sopenharmony_ci struct evsel *evsel; 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 24258c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) 24268c2ecf20Sopenharmony_ci continue; 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci ret = add_evsel_fields(evsel, raw_trace, level); 24298c2ecf20Sopenharmony_ci if (ret < 0) 24308c2ecf20Sopenharmony_ci return ret; 24318c2ecf20Sopenharmony_ci } 24328c2ecf20Sopenharmony_ci return 0; 24338c2ecf20Sopenharmony_ci} 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_cistatic int add_all_matching_fields(struct evlist *evlist, 24368c2ecf20Sopenharmony_ci char *field_name, bool raw_trace, int level) 24378c2ecf20Sopenharmony_ci{ 24388c2ecf20Sopenharmony_ci int ret = -ESRCH; 24398c2ecf20Sopenharmony_ci struct evsel *evsel; 24408c2ecf20Sopenharmony_ci struct tep_format_field *field; 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 24438c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) 24448c2ecf20Sopenharmony_ci continue; 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci field = tep_find_any_field(evsel->tp_format, field_name); 24478c2ecf20Sopenharmony_ci if (field == NULL) 24488c2ecf20Sopenharmony_ci continue; 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci ret = __dynamic_dimension__add(evsel, field, raw_trace, level); 24518c2ecf20Sopenharmony_ci if (ret < 0) 24528c2ecf20Sopenharmony_ci break; 24538c2ecf20Sopenharmony_ci } 24548c2ecf20Sopenharmony_ci return ret; 24558c2ecf20Sopenharmony_ci} 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_cistatic int add_dynamic_entry(struct evlist *evlist, const char *tok, 24588c2ecf20Sopenharmony_ci int level) 24598c2ecf20Sopenharmony_ci{ 24608c2ecf20Sopenharmony_ci char *str, *event_name, *field_name, *opt_name; 24618c2ecf20Sopenharmony_ci struct evsel *evsel; 24628c2ecf20Sopenharmony_ci struct tep_format_field *field; 24638c2ecf20Sopenharmony_ci bool raw_trace = symbol_conf.raw_trace; 24648c2ecf20Sopenharmony_ci int ret = 0; 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci if (evlist == NULL) 24678c2ecf20Sopenharmony_ci return -ENOENT; 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci str = strdup(tok); 24708c2ecf20Sopenharmony_ci if (str == NULL) 24718c2ecf20Sopenharmony_ci return -ENOMEM; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) { 24748c2ecf20Sopenharmony_ci ret = -EINVAL; 24758c2ecf20Sopenharmony_ci goto out; 24768c2ecf20Sopenharmony_ci } 24778c2ecf20Sopenharmony_ci 24788c2ecf20Sopenharmony_ci if (opt_name) { 24798c2ecf20Sopenharmony_ci if (strcmp(opt_name, "raw")) { 24808c2ecf20Sopenharmony_ci pr_debug("unsupported field option %s\n", opt_name); 24818c2ecf20Sopenharmony_ci ret = -EINVAL; 24828c2ecf20Sopenharmony_ci goto out; 24838c2ecf20Sopenharmony_ci } 24848c2ecf20Sopenharmony_ci raw_trace = true; 24858c2ecf20Sopenharmony_ci } 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci if (!strcmp(field_name, "trace_fields")) { 24888c2ecf20Sopenharmony_ci ret = add_all_dynamic_fields(evlist, raw_trace, level); 24898c2ecf20Sopenharmony_ci goto out; 24908c2ecf20Sopenharmony_ci } 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci if (event_name == NULL) { 24938c2ecf20Sopenharmony_ci ret = add_all_matching_fields(evlist, field_name, raw_trace, level); 24948c2ecf20Sopenharmony_ci goto out; 24958c2ecf20Sopenharmony_ci } 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci evsel = find_evsel(evlist, event_name); 24988c2ecf20Sopenharmony_ci if (evsel == NULL) { 24998c2ecf20Sopenharmony_ci pr_debug("Cannot find event: %s\n", event_name); 25008c2ecf20Sopenharmony_ci ret = -ENOENT; 25018c2ecf20Sopenharmony_ci goto out; 25028c2ecf20Sopenharmony_ci } 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 25058c2ecf20Sopenharmony_ci pr_debug("%s is not a tracepoint event\n", event_name); 25068c2ecf20Sopenharmony_ci ret = -EINVAL; 25078c2ecf20Sopenharmony_ci goto out; 25088c2ecf20Sopenharmony_ci } 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci if (!strcmp(field_name, "*")) { 25118c2ecf20Sopenharmony_ci ret = add_evsel_fields(evsel, raw_trace, level); 25128c2ecf20Sopenharmony_ci } else { 25138c2ecf20Sopenharmony_ci field = tep_find_any_field(evsel->tp_format, field_name); 25148c2ecf20Sopenharmony_ci if (field == NULL) { 25158c2ecf20Sopenharmony_ci pr_debug("Cannot find event field for %s.%s\n", 25168c2ecf20Sopenharmony_ci event_name, field_name); 25178c2ecf20Sopenharmony_ci return -ENOENT; 25188c2ecf20Sopenharmony_ci } 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_ci ret = __dynamic_dimension__add(evsel, field, raw_trace, level); 25218c2ecf20Sopenharmony_ci } 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ciout: 25248c2ecf20Sopenharmony_ci free(str); 25258c2ecf20Sopenharmony_ci return ret; 25268c2ecf20Sopenharmony_ci} 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_cistatic int __sort_dimension__add(struct sort_dimension *sd, 25298c2ecf20Sopenharmony_ci struct perf_hpp_list *list, 25308c2ecf20Sopenharmony_ci int level) 25318c2ecf20Sopenharmony_ci{ 25328c2ecf20Sopenharmony_ci if (sd->taken) 25338c2ecf20Sopenharmony_ci return 0; 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci if (__sort_dimension__add_hpp_sort(sd, list, level) < 0) 25368c2ecf20Sopenharmony_ci return -1; 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci if (sd->entry->se_collapse) 25398c2ecf20Sopenharmony_ci list->need_collapse = 1; 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci sd->taken = 1; 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci return 0; 25448c2ecf20Sopenharmony_ci} 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_cistatic int __hpp_dimension__add(struct hpp_dimension *hd, 25478c2ecf20Sopenharmony_ci struct perf_hpp_list *list, 25488c2ecf20Sopenharmony_ci int level) 25498c2ecf20Sopenharmony_ci{ 25508c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci if (hd->taken) 25538c2ecf20Sopenharmony_ci return 0; 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci fmt = __hpp_dimension__alloc_hpp(hd, level); 25568c2ecf20Sopenharmony_ci if (!fmt) 25578c2ecf20Sopenharmony_ci return -1; 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci hd->taken = 1; 25608c2ecf20Sopenharmony_ci perf_hpp_list__register_sort_field(list, fmt); 25618c2ecf20Sopenharmony_ci return 0; 25628c2ecf20Sopenharmony_ci} 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_cistatic int __sort_dimension__add_output(struct perf_hpp_list *list, 25658c2ecf20Sopenharmony_ci struct sort_dimension *sd) 25668c2ecf20Sopenharmony_ci{ 25678c2ecf20Sopenharmony_ci if (sd->taken) 25688c2ecf20Sopenharmony_ci return 0; 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_ci if (__sort_dimension__add_hpp_output(sd, list) < 0) 25718c2ecf20Sopenharmony_ci return -1; 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci sd->taken = 1; 25748c2ecf20Sopenharmony_ci return 0; 25758c2ecf20Sopenharmony_ci} 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_cistatic int __hpp_dimension__add_output(struct perf_hpp_list *list, 25788c2ecf20Sopenharmony_ci struct hpp_dimension *hd) 25798c2ecf20Sopenharmony_ci{ 25808c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci if (hd->taken) 25838c2ecf20Sopenharmony_ci return 0; 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci fmt = __hpp_dimension__alloc_hpp(hd, 0); 25868c2ecf20Sopenharmony_ci if (!fmt) 25878c2ecf20Sopenharmony_ci return -1; 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci hd->taken = 1; 25908c2ecf20Sopenharmony_ci perf_hpp_list__column_register(list, fmt); 25918c2ecf20Sopenharmony_ci return 0; 25928c2ecf20Sopenharmony_ci} 25938c2ecf20Sopenharmony_ci 25948c2ecf20Sopenharmony_ciint hpp_dimension__add_output(unsigned col) 25958c2ecf20Sopenharmony_ci{ 25968c2ecf20Sopenharmony_ci BUG_ON(col >= PERF_HPP__MAX_INDEX); 25978c2ecf20Sopenharmony_ci return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); 25988c2ecf20Sopenharmony_ci} 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ciint sort_dimension__add(struct perf_hpp_list *list, const char *tok, 26018c2ecf20Sopenharmony_ci struct evlist *evlist, 26028c2ecf20Sopenharmony_ci int level) 26038c2ecf20Sopenharmony_ci{ 26048c2ecf20Sopenharmony_ci unsigned int i; 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { 26078c2ecf20Sopenharmony_ci struct sort_dimension *sd = &common_sort_dimensions[i]; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 26108c2ecf20Sopenharmony_ci continue; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci if (sd->entry == &sort_parent) { 26138c2ecf20Sopenharmony_ci int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); 26148c2ecf20Sopenharmony_ci if (ret) { 26158c2ecf20Sopenharmony_ci char err[BUFSIZ]; 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci regerror(ret, &parent_regex, err, sizeof(err)); 26188c2ecf20Sopenharmony_ci pr_err("Invalid regex: %s\n%s", parent_pattern, err); 26198c2ecf20Sopenharmony_ci return -EINVAL; 26208c2ecf20Sopenharmony_ci } 26218c2ecf20Sopenharmony_ci list->parent = 1; 26228c2ecf20Sopenharmony_ci } else if (sd->entry == &sort_sym) { 26238c2ecf20Sopenharmony_ci list->sym = 1; 26248c2ecf20Sopenharmony_ci /* 26258c2ecf20Sopenharmony_ci * perf diff displays the performance difference amongst 26268c2ecf20Sopenharmony_ci * two or more perf.data files. Those files could come 26278c2ecf20Sopenharmony_ci * from different binaries. So we should not compare 26288c2ecf20Sopenharmony_ci * their ips, but the name of symbol. 26298c2ecf20Sopenharmony_ci */ 26308c2ecf20Sopenharmony_ci if (sort__mode == SORT_MODE__DIFF) 26318c2ecf20Sopenharmony_ci sd->entry->se_collapse = sort__sym_sort; 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci } else if (sd->entry == &sort_dso) { 26348c2ecf20Sopenharmony_ci list->dso = 1; 26358c2ecf20Sopenharmony_ci } else if (sd->entry == &sort_socket) { 26368c2ecf20Sopenharmony_ci list->socket = 1; 26378c2ecf20Sopenharmony_ci } else if (sd->entry == &sort_thread) { 26388c2ecf20Sopenharmony_ci list->thread = 1; 26398c2ecf20Sopenharmony_ci } else if (sd->entry == &sort_comm) { 26408c2ecf20Sopenharmony_ci list->comm = 1; 26418c2ecf20Sopenharmony_ci } 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci return __sort_dimension__add(sd, list, level); 26448c2ecf20Sopenharmony_ci } 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { 26478c2ecf20Sopenharmony_ci struct hpp_dimension *hd = &hpp_sort_dimensions[i]; 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci if (strncasecmp(tok, hd->name, strlen(tok))) 26508c2ecf20Sopenharmony_ci continue; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci return __hpp_dimension__add(hd, list, level); 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { 26568c2ecf20Sopenharmony_ci struct sort_dimension *sd = &bstack_sort_dimensions[i]; 26578c2ecf20Sopenharmony_ci 26588c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 26598c2ecf20Sopenharmony_ci continue; 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__BRANCH) 26628c2ecf20Sopenharmony_ci return -EINVAL; 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) 26658c2ecf20Sopenharmony_ci list->sym = 1; 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci __sort_dimension__add(sd, list, level); 26688c2ecf20Sopenharmony_ci return 0; 26698c2ecf20Sopenharmony_ci } 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { 26728c2ecf20Sopenharmony_ci struct sort_dimension *sd = &memory_sort_dimensions[i]; 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 26758c2ecf20Sopenharmony_ci continue; 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__MEMORY) 26788c2ecf20Sopenharmony_ci return -EINVAL; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci if (sd->entry == &sort_mem_dcacheline && cacheline_size() == 0) 26818c2ecf20Sopenharmony_ci return -EINVAL; 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci if (sd->entry == &sort_mem_daddr_sym) 26848c2ecf20Sopenharmony_ci list->sym = 1; 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ci __sort_dimension__add(sd, list, level); 26878c2ecf20Sopenharmony_ci return 0; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci if (!add_dynamic_entry(evlist, tok, level)) 26918c2ecf20Sopenharmony_ci return 0; 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_ci return -ESRCH; 26948c2ecf20Sopenharmony_ci} 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_cistatic int setup_sort_list(struct perf_hpp_list *list, char *str, 26978c2ecf20Sopenharmony_ci struct evlist *evlist) 26988c2ecf20Sopenharmony_ci{ 26998c2ecf20Sopenharmony_ci char *tmp, *tok; 27008c2ecf20Sopenharmony_ci int ret = 0; 27018c2ecf20Sopenharmony_ci int level = 0; 27028c2ecf20Sopenharmony_ci int next_level = 1; 27038c2ecf20Sopenharmony_ci bool in_group = false; 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci do { 27068c2ecf20Sopenharmony_ci tok = str; 27078c2ecf20Sopenharmony_ci tmp = strpbrk(str, "{}, "); 27088c2ecf20Sopenharmony_ci if (tmp) { 27098c2ecf20Sopenharmony_ci if (in_group) 27108c2ecf20Sopenharmony_ci next_level = level; 27118c2ecf20Sopenharmony_ci else 27128c2ecf20Sopenharmony_ci next_level = level + 1; 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci if (*tmp == '{') 27158c2ecf20Sopenharmony_ci in_group = true; 27168c2ecf20Sopenharmony_ci else if (*tmp == '}') 27178c2ecf20Sopenharmony_ci in_group = false; 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_ci *tmp = '\0'; 27208c2ecf20Sopenharmony_ci str = tmp + 1; 27218c2ecf20Sopenharmony_ci } 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci if (*tok) { 27248c2ecf20Sopenharmony_ci ret = sort_dimension__add(list, tok, evlist, level); 27258c2ecf20Sopenharmony_ci if (ret == -EINVAL) { 27268c2ecf20Sopenharmony_ci if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok))) 27278c2ecf20Sopenharmony_ci ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); 27288c2ecf20Sopenharmony_ci else 27298c2ecf20Sopenharmony_ci ui__error("Invalid --sort key: `%s'", tok); 27308c2ecf20Sopenharmony_ci break; 27318c2ecf20Sopenharmony_ci } else if (ret == -ESRCH) { 27328c2ecf20Sopenharmony_ci ui__error("Unknown --sort key: `%s'", tok); 27338c2ecf20Sopenharmony_ci break; 27348c2ecf20Sopenharmony_ci } 27358c2ecf20Sopenharmony_ci } 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci level = next_level; 27388c2ecf20Sopenharmony_ci } while (tmp); 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci return ret; 27418c2ecf20Sopenharmony_ci} 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_cistatic const char *get_default_sort_order(struct evlist *evlist) 27448c2ecf20Sopenharmony_ci{ 27458c2ecf20Sopenharmony_ci const char *default_sort_orders[] = { 27468c2ecf20Sopenharmony_ci default_sort_order, 27478c2ecf20Sopenharmony_ci default_branch_sort_order, 27488c2ecf20Sopenharmony_ci default_mem_sort_order, 27498c2ecf20Sopenharmony_ci default_top_sort_order, 27508c2ecf20Sopenharmony_ci default_diff_sort_order, 27518c2ecf20Sopenharmony_ci default_tracepoint_sort_order, 27528c2ecf20Sopenharmony_ci }; 27538c2ecf20Sopenharmony_ci bool use_trace = true; 27548c2ecf20Sopenharmony_ci struct evsel *evsel; 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci if (evlist == NULL || perf_evlist__empty(evlist)) 27598c2ecf20Sopenharmony_ci goto out_no_evlist; 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 27628c2ecf20Sopenharmony_ci if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 27638c2ecf20Sopenharmony_ci use_trace = false; 27648c2ecf20Sopenharmony_ci break; 27658c2ecf20Sopenharmony_ci } 27668c2ecf20Sopenharmony_ci } 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci if (use_trace) { 27698c2ecf20Sopenharmony_ci sort__mode = SORT_MODE__TRACEPOINT; 27708c2ecf20Sopenharmony_ci if (symbol_conf.raw_trace) 27718c2ecf20Sopenharmony_ci return "trace_fields"; 27728c2ecf20Sopenharmony_ci } 27738c2ecf20Sopenharmony_ciout_no_evlist: 27748c2ecf20Sopenharmony_ci return default_sort_orders[sort__mode]; 27758c2ecf20Sopenharmony_ci} 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_cistatic int setup_sort_order(struct evlist *evlist) 27788c2ecf20Sopenharmony_ci{ 27798c2ecf20Sopenharmony_ci char *new_sort_order; 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci /* 27828c2ecf20Sopenharmony_ci * Append '+'-prefixed sort order to the default sort 27838c2ecf20Sopenharmony_ci * order string. 27848c2ecf20Sopenharmony_ci */ 27858c2ecf20Sopenharmony_ci if (!sort_order || is_strict_order(sort_order)) 27868c2ecf20Sopenharmony_ci return 0; 27878c2ecf20Sopenharmony_ci 27888c2ecf20Sopenharmony_ci if (sort_order[1] == '\0') { 27898c2ecf20Sopenharmony_ci ui__error("Invalid --sort key: `+'"); 27908c2ecf20Sopenharmony_ci return -EINVAL; 27918c2ecf20Sopenharmony_ci } 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci /* 27948c2ecf20Sopenharmony_ci * We allocate new sort_order string, but we never free it, 27958c2ecf20Sopenharmony_ci * because it's checked over the rest of the code. 27968c2ecf20Sopenharmony_ci */ 27978c2ecf20Sopenharmony_ci if (asprintf(&new_sort_order, "%s,%s", 27988c2ecf20Sopenharmony_ci get_default_sort_order(evlist), sort_order + 1) < 0) { 27998c2ecf20Sopenharmony_ci pr_err("Not enough memory to set up --sort"); 28008c2ecf20Sopenharmony_ci return -ENOMEM; 28018c2ecf20Sopenharmony_ci } 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci sort_order = new_sort_order; 28048c2ecf20Sopenharmony_ci return 0; 28058c2ecf20Sopenharmony_ci} 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci/* 28088c2ecf20Sopenharmony_ci * Adds 'pre,' prefix into 'str' is 'pre' is 28098c2ecf20Sopenharmony_ci * not already part of 'str'. 28108c2ecf20Sopenharmony_ci */ 28118c2ecf20Sopenharmony_cistatic char *prefix_if_not_in(const char *pre, char *str) 28128c2ecf20Sopenharmony_ci{ 28138c2ecf20Sopenharmony_ci char *n; 28148c2ecf20Sopenharmony_ci 28158c2ecf20Sopenharmony_ci if (!str || strstr(str, pre)) 28168c2ecf20Sopenharmony_ci return str; 28178c2ecf20Sopenharmony_ci 28188c2ecf20Sopenharmony_ci if (asprintf(&n, "%s,%s", pre, str) < 0) 28198c2ecf20Sopenharmony_ci n = NULL; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci free(str); 28228c2ecf20Sopenharmony_ci return n; 28238c2ecf20Sopenharmony_ci} 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_cistatic char *setup_overhead(char *keys) 28268c2ecf20Sopenharmony_ci{ 28278c2ecf20Sopenharmony_ci if (sort__mode == SORT_MODE__DIFF) 28288c2ecf20Sopenharmony_ci return keys; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci keys = prefix_if_not_in("overhead", keys); 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci if (symbol_conf.cumulate_callchain) 28338c2ecf20Sopenharmony_ci keys = prefix_if_not_in("overhead_children", keys); 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci return keys; 28368c2ecf20Sopenharmony_ci} 28378c2ecf20Sopenharmony_ci 28388c2ecf20Sopenharmony_cistatic int __setup_sorting(struct evlist *evlist) 28398c2ecf20Sopenharmony_ci{ 28408c2ecf20Sopenharmony_ci char *str; 28418c2ecf20Sopenharmony_ci const char *sort_keys; 28428c2ecf20Sopenharmony_ci int ret = 0; 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci ret = setup_sort_order(evlist); 28458c2ecf20Sopenharmony_ci if (ret) 28468c2ecf20Sopenharmony_ci return ret; 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_ci sort_keys = sort_order; 28498c2ecf20Sopenharmony_ci if (sort_keys == NULL) { 28508c2ecf20Sopenharmony_ci if (is_strict_order(field_order)) { 28518c2ecf20Sopenharmony_ci /* 28528c2ecf20Sopenharmony_ci * If user specified field order but no sort order, 28538c2ecf20Sopenharmony_ci * we'll honor it and not add default sort orders. 28548c2ecf20Sopenharmony_ci */ 28558c2ecf20Sopenharmony_ci return 0; 28568c2ecf20Sopenharmony_ci } 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_ci sort_keys = get_default_sort_order(evlist); 28598c2ecf20Sopenharmony_ci } 28608c2ecf20Sopenharmony_ci 28618c2ecf20Sopenharmony_ci str = strdup(sort_keys); 28628c2ecf20Sopenharmony_ci if (str == NULL) { 28638c2ecf20Sopenharmony_ci pr_err("Not enough memory to setup sort keys"); 28648c2ecf20Sopenharmony_ci return -ENOMEM; 28658c2ecf20Sopenharmony_ci } 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci /* 28688c2ecf20Sopenharmony_ci * Prepend overhead fields for backward compatibility. 28698c2ecf20Sopenharmony_ci */ 28708c2ecf20Sopenharmony_ci if (!is_strict_order(field_order)) { 28718c2ecf20Sopenharmony_ci str = setup_overhead(str); 28728c2ecf20Sopenharmony_ci if (str == NULL) { 28738c2ecf20Sopenharmony_ci pr_err("Not enough memory to setup overhead keys"); 28748c2ecf20Sopenharmony_ci return -ENOMEM; 28758c2ecf20Sopenharmony_ci } 28768c2ecf20Sopenharmony_ci } 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_ci ret = setup_sort_list(&perf_hpp_list, str, evlist); 28798c2ecf20Sopenharmony_ci 28808c2ecf20Sopenharmony_ci free(str); 28818c2ecf20Sopenharmony_ci return ret; 28828c2ecf20Sopenharmony_ci} 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_civoid perf_hpp__set_elide(int idx, bool elide) 28858c2ecf20Sopenharmony_ci{ 28868c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 28878c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 28888c2ecf20Sopenharmony_ci 28898c2ecf20Sopenharmony_ci perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { 28908c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 28918c2ecf20Sopenharmony_ci continue; 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 28948c2ecf20Sopenharmony_ci if (hse->se->se_width_idx == idx) { 28958c2ecf20Sopenharmony_ci fmt->elide = elide; 28968c2ecf20Sopenharmony_ci break; 28978c2ecf20Sopenharmony_ci } 28988c2ecf20Sopenharmony_ci } 28998c2ecf20Sopenharmony_ci} 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_cistatic bool __get_elide(struct strlist *list, const char *list_name, FILE *fp) 29028c2ecf20Sopenharmony_ci{ 29038c2ecf20Sopenharmony_ci if (list && strlist__nr_entries(list) == 1) { 29048c2ecf20Sopenharmony_ci if (fp != NULL) 29058c2ecf20Sopenharmony_ci fprintf(fp, "# %s: %s\n", list_name, 29068c2ecf20Sopenharmony_ci strlist__entry(list, 0)->s); 29078c2ecf20Sopenharmony_ci return true; 29088c2ecf20Sopenharmony_ci } 29098c2ecf20Sopenharmony_ci return false; 29108c2ecf20Sopenharmony_ci} 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_cistatic bool get_elide(int idx, FILE *output) 29138c2ecf20Sopenharmony_ci{ 29148c2ecf20Sopenharmony_ci switch (idx) { 29158c2ecf20Sopenharmony_ci case HISTC_SYMBOL: 29168c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.sym_list, "symbol", output); 29178c2ecf20Sopenharmony_ci case HISTC_DSO: 29188c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.dso_list, "dso", output); 29198c2ecf20Sopenharmony_ci case HISTC_COMM: 29208c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.comm_list, "comm", output); 29218c2ecf20Sopenharmony_ci default: 29228c2ecf20Sopenharmony_ci break; 29238c2ecf20Sopenharmony_ci } 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__BRANCH) 29268c2ecf20Sopenharmony_ci return false; 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_ci switch (idx) { 29298c2ecf20Sopenharmony_ci case HISTC_SYMBOL_FROM: 29308c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.sym_from_list, "sym_from", output); 29318c2ecf20Sopenharmony_ci case HISTC_SYMBOL_TO: 29328c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.sym_to_list, "sym_to", output); 29338c2ecf20Sopenharmony_ci case HISTC_DSO_FROM: 29348c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.dso_from_list, "dso_from", output); 29358c2ecf20Sopenharmony_ci case HISTC_DSO_TO: 29368c2ecf20Sopenharmony_ci return __get_elide(symbol_conf.dso_to_list, "dso_to", output); 29378c2ecf20Sopenharmony_ci default: 29388c2ecf20Sopenharmony_ci break; 29398c2ecf20Sopenharmony_ci } 29408c2ecf20Sopenharmony_ci 29418c2ecf20Sopenharmony_ci return false; 29428c2ecf20Sopenharmony_ci} 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_civoid sort__setup_elide(FILE *output) 29458c2ecf20Sopenharmony_ci{ 29468c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 29478c2ecf20Sopenharmony_ci struct hpp_sort_entry *hse; 29488c2ecf20Sopenharmony_ci 29498c2ecf20Sopenharmony_ci perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { 29508c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 29518c2ecf20Sopenharmony_ci continue; 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci hse = container_of(fmt, struct hpp_sort_entry, hpp); 29548c2ecf20Sopenharmony_ci fmt->elide = get_elide(hse->se->se_width_idx, output); 29558c2ecf20Sopenharmony_ci } 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci /* 29588c2ecf20Sopenharmony_ci * It makes no sense to elide all of sort entries. 29598c2ecf20Sopenharmony_ci * Just revert them to show up again. 29608c2ecf20Sopenharmony_ci */ 29618c2ecf20Sopenharmony_ci perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { 29628c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 29638c2ecf20Sopenharmony_ci continue; 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci if (!fmt->elide) 29668c2ecf20Sopenharmony_ci return; 29678c2ecf20Sopenharmony_ci } 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { 29708c2ecf20Sopenharmony_ci if (!perf_hpp__is_sort_entry(fmt)) 29718c2ecf20Sopenharmony_ci continue; 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_ci fmt->elide = false; 29748c2ecf20Sopenharmony_ci } 29758c2ecf20Sopenharmony_ci} 29768c2ecf20Sopenharmony_ci 29778c2ecf20Sopenharmony_ciint output_field_add(struct perf_hpp_list *list, char *tok) 29788c2ecf20Sopenharmony_ci{ 29798c2ecf20Sopenharmony_ci unsigned int i; 29808c2ecf20Sopenharmony_ci 29818c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { 29828c2ecf20Sopenharmony_ci struct sort_dimension *sd = &common_sort_dimensions[i]; 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 29858c2ecf20Sopenharmony_ci continue; 29868c2ecf20Sopenharmony_ci 29878c2ecf20Sopenharmony_ci return __sort_dimension__add_output(list, sd); 29888c2ecf20Sopenharmony_ci } 29898c2ecf20Sopenharmony_ci 29908c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { 29918c2ecf20Sopenharmony_ci struct hpp_dimension *hd = &hpp_sort_dimensions[i]; 29928c2ecf20Sopenharmony_ci 29938c2ecf20Sopenharmony_ci if (strncasecmp(tok, hd->name, strlen(tok))) 29948c2ecf20Sopenharmony_ci continue; 29958c2ecf20Sopenharmony_ci 29968c2ecf20Sopenharmony_ci return __hpp_dimension__add_output(list, hd); 29978c2ecf20Sopenharmony_ci } 29988c2ecf20Sopenharmony_ci 29998c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { 30008c2ecf20Sopenharmony_ci struct sort_dimension *sd = &bstack_sort_dimensions[i]; 30018c2ecf20Sopenharmony_ci 30028c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 30038c2ecf20Sopenharmony_ci continue; 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__BRANCH) 30068c2ecf20Sopenharmony_ci return -EINVAL; 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_ci return __sort_dimension__add_output(list, sd); 30098c2ecf20Sopenharmony_ci } 30108c2ecf20Sopenharmony_ci 30118c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { 30128c2ecf20Sopenharmony_ci struct sort_dimension *sd = &memory_sort_dimensions[i]; 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci if (strncasecmp(tok, sd->name, strlen(tok))) 30158c2ecf20Sopenharmony_ci continue; 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__MEMORY) 30188c2ecf20Sopenharmony_ci return -EINVAL; 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_ci return __sort_dimension__add_output(list, sd); 30218c2ecf20Sopenharmony_ci } 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_ci return -ESRCH; 30248c2ecf20Sopenharmony_ci} 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_cistatic int setup_output_list(struct perf_hpp_list *list, char *str) 30278c2ecf20Sopenharmony_ci{ 30288c2ecf20Sopenharmony_ci char *tmp, *tok; 30298c2ecf20Sopenharmony_ci int ret = 0; 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci for (tok = strtok_r(str, ", ", &tmp); 30328c2ecf20Sopenharmony_ci tok; tok = strtok_r(NULL, ", ", &tmp)) { 30338c2ecf20Sopenharmony_ci ret = output_field_add(list, tok); 30348c2ecf20Sopenharmony_ci if (ret == -EINVAL) { 30358c2ecf20Sopenharmony_ci ui__error("Invalid --fields key: `%s'", tok); 30368c2ecf20Sopenharmony_ci break; 30378c2ecf20Sopenharmony_ci } else if (ret == -ESRCH) { 30388c2ecf20Sopenharmony_ci ui__error("Unknown --fields key: `%s'", tok); 30398c2ecf20Sopenharmony_ci break; 30408c2ecf20Sopenharmony_ci } 30418c2ecf20Sopenharmony_ci } 30428c2ecf20Sopenharmony_ci 30438c2ecf20Sopenharmony_ci return ret; 30448c2ecf20Sopenharmony_ci} 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_civoid reset_dimensions(void) 30478c2ecf20Sopenharmony_ci{ 30488c2ecf20Sopenharmony_ci unsigned int i; 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) 30518c2ecf20Sopenharmony_ci common_sort_dimensions[i].taken = 0; 30528c2ecf20Sopenharmony_ci 30538c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) 30548c2ecf20Sopenharmony_ci hpp_sort_dimensions[i].taken = 0; 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) 30578c2ecf20Sopenharmony_ci bstack_sort_dimensions[i].taken = 0; 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) 30608c2ecf20Sopenharmony_ci memory_sort_dimensions[i].taken = 0; 30618c2ecf20Sopenharmony_ci} 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_cibool is_strict_order(const char *order) 30648c2ecf20Sopenharmony_ci{ 30658c2ecf20Sopenharmony_ci return order && (*order != '+'); 30668c2ecf20Sopenharmony_ci} 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_cistatic int __setup_output_field(void) 30698c2ecf20Sopenharmony_ci{ 30708c2ecf20Sopenharmony_ci char *str, *strp; 30718c2ecf20Sopenharmony_ci int ret = -EINVAL; 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci if (field_order == NULL) 30748c2ecf20Sopenharmony_ci return 0; 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci strp = str = strdup(field_order); 30778c2ecf20Sopenharmony_ci if (str == NULL) { 30788c2ecf20Sopenharmony_ci pr_err("Not enough memory to setup output fields"); 30798c2ecf20Sopenharmony_ci return -ENOMEM; 30808c2ecf20Sopenharmony_ci } 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci if (!is_strict_order(field_order)) 30838c2ecf20Sopenharmony_ci strp++; 30848c2ecf20Sopenharmony_ci 30858c2ecf20Sopenharmony_ci if (!strlen(strp)) { 30868c2ecf20Sopenharmony_ci ui__error("Invalid --fields key: `+'"); 30878c2ecf20Sopenharmony_ci goto out; 30888c2ecf20Sopenharmony_ci } 30898c2ecf20Sopenharmony_ci 30908c2ecf20Sopenharmony_ci ret = setup_output_list(&perf_hpp_list, strp); 30918c2ecf20Sopenharmony_ci 30928c2ecf20Sopenharmony_ciout: 30938c2ecf20Sopenharmony_ci free(str); 30948c2ecf20Sopenharmony_ci return ret; 30958c2ecf20Sopenharmony_ci} 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ciint setup_sorting(struct evlist *evlist) 30988c2ecf20Sopenharmony_ci{ 30998c2ecf20Sopenharmony_ci int err; 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci err = __setup_sorting(evlist); 31028c2ecf20Sopenharmony_ci if (err < 0) 31038c2ecf20Sopenharmony_ci return err; 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci if (parent_pattern != default_parent_pattern) { 31068c2ecf20Sopenharmony_ci err = sort_dimension__add(&perf_hpp_list, "parent", evlist, -1); 31078c2ecf20Sopenharmony_ci if (err < 0) 31088c2ecf20Sopenharmony_ci return err; 31098c2ecf20Sopenharmony_ci } 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci reset_dimensions(); 31128c2ecf20Sopenharmony_ci 31138c2ecf20Sopenharmony_ci /* 31148c2ecf20Sopenharmony_ci * perf diff doesn't use default hpp output fields. 31158c2ecf20Sopenharmony_ci */ 31168c2ecf20Sopenharmony_ci if (sort__mode != SORT_MODE__DIFF) 31178c2ecf20Sopenharmony_ci perf_hpp__init(); 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_ci err = __setup_output_field(); 31208c2ecf20Sopenharmony_ci if (err < 0) 31218c2ecf20Sopenharmony_ci return err; 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci /* copy sort keys to output fields */ 31248c2ecf20Sopenharmony_ci perf_hpp__setup_output_field(&perf_hpp_list); 31258c2ecf20Sopenharmony_ci /* and then copy output fields to sort keys */ 31268c2ecf20Sopenharmony_ci perf_hpp__append_sort_keys(&perf_hpp_list); 31278c2ecf20Sopenharmony_ci 31288c2ecf20Sopenharmony_ci /* setup hists-specific output fields */ 31298c2ecf20Sopenharmony_ci if (perf_hpp__setup_hists_formats(&perf_hpp_list, evlist) < 0) 31308c2ecf20Sopenharmony_ci return -1; 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci return 0; 31338c2ecf20Sopenharmony_ci} 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_civoid reset_output_field(void) 31368c2ecf20Sopenharmony_ci{ 31378c2ecf20Sopenharmony_ci perf_hpp_list.need_collapse = 0; 31388c2ecf20Sopenharmony_ci perf_hpp_list.parent = 0; 31398c2ecf20Sopenharmony_ci perf_hpp_list.sym = 0; 31408c2ecf20Sopenharmony_ci perf_hpp_list.dso = 0; 31418c2ecf20Sopenharmony_ci 31428c2ecf20Sopenharmony_ci field_order = NULL; 31438c2ecf20Sopenharmony_ci sort_order = NULL; 31448c2ecf20Sopenharmony_ci 31458c2ecf20Sopenharmony_ci reset_dimensions(); 31468c2ecf20Sopenharmony_ci perf_hpp__reset_output_field(&perf_hpp_list); 31478c2ecf20Sopenharmony_ci} 31488c2ecf20Sopenharmony_ci 31498c2ecf20Sopenharmony_ci#define INDENT (3*8 + 1) 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_cistatic void add_key(struct strbuf *sb, const char *str, int *llen) 31528c2ecf20Sopenharmony_ci{ 31538c2ecf20Sopenharmony_ci if (*llen >= 75) { 31548c2ecf20Sopenharmony_ci strbuf_addstr(sb, "\n\t\t\t "); 31558c2ecf20Sopenharmony_ci *llen = INDENT; 31568c2ecf20Sopenharmony_ci } 31578c2ecf20Sopenharmony_ci strbuf_addf(sb, " %s", str); 31588c2ecf20Sopenharmony_ci *llen += strlen(str) + 1; 31598c2ecf20Sopenharmony_ci} 31608c2ecf20Sopenharmony_ci 31618c2ecf20Sopenharmony_cistatic void add_sort_string(struct strbuf *sb, struct sort_dimension *s, int n, 31628c2ecf20Sopenharmony_ci int *llen) 31638c2ecf20Sopenharmony_ci{ 31648c2ecf20Sopenharmony_ci int i; 31658c2ecf20Sopenharmony_ci 31668c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 31678c2ecf20Sopenharmony_ci add_key(sb, s[i].name, llen); 31688c2ecf20Sopenharmony_ci} 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_cistatic void add_hpp_sort_string(struct strbuf *sb, struct hpp_dimension *s, int n, 31718c2ecf20Sopenharmony_ci int *llen) 31728c2ecf20Sopenharmony_ci{ 31738c2ecf20Sopenharmony_ci int i; 31748c2ecf20Sopenharmony_ci 31758c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) 31768c2ecf20Sopenharmony_ci add_key(sb, s[i].name, llen); 31778c2ecf20Sopenharmony_ci} 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_cichar *sort_help(const char *prefix) 31808c2ecf20Sopenharmony_ci{ 31818c2ecf20Sopenharmony_ci struct strbuf sb; 31828c2ecf20Sopenharmony_ci char *s; 31838c2ecf20Sopenharmony_ci int len = strlen(prefix) + INDENT; 31848c2ecf20Sopenharmony_ci 31858c2ecf20Sopenharmony_ci strbuf_init(&sb, 300); 31868c2ecf20Sopenharmony_ci strbuf_addstr(&sb, prefix); 31878c2ecf20Sopenharmony_ci add_hpp_sort_string(&sb, hpp_sort_dimensions, 31888c2ecf20Sopenharmony_ci ARRAY_SIZE(hpp_sort_dimensions), &len); 31898c2ecf20Sopenharmony_ci add_sort_string(&sb, common_sort_dimensions, 31908c2ecf20Sopenharmony_ci ARRAY_SIZE(common_sort_dimensions), &len); 31918c2ecf20Sopenharmony_ci add_sort_string(&sb, bstack_sort_dimensions, 31928c2ecf20Sopenharmony_ci ARRAY_SIZE(bstack_sort_dimensions), &len); 31938c2ecf20Sopenharmony_ci add_sort_string(&sb, memory_sort_dimensions, 31948c2ecf20Sopenharmony_ci ARRAY_SIZE(memory_sort_dimensions), &len); 31958c2ecf20Sopenharmony_ci s = strbuf_detach(&sb, NULL); 31968c2ecf20Sopenharmony_ci strbuf_release(&sb); 31978c2ecf20Sopenharmony_ci return s; 31988c2ecf20Sopenharmony_ci} 3199