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