162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __PERF_SORT_H 362306a36Sopenharmony_ci#define __PERF_SORT_H 462306a36Sopenharmony_ci#include <regex.h> 562306a36Sopenharmony_ci#include <stdbool.h> 662306a36Sopenharmony_ci#include <linux/list.h> 762306a36Sopenharmony_ci#include <linux/rbtree.h> 862306a36Sopenharmony_ci#include "map_symbol.h" 962306a36Sopenharmony_ci#include "symbol_conf.h" 1062306a36Sopenharmony_ci#include "callchain.h" 1162306a36Sopenharmony_ci#include "values.h" 1262306a36Sopenharmony_ci#include "hist.h" 1362306a36Sopenharmony_ci#include "stat.h" 1462306a36Sopenharmony_ci#include "spark.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct option; 1762306a36Sopenharmony_cistruct thread; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciextern regex_t parent_regex; 2062306a36Sopenharmony_ciextern const char *sort_order; 2162306a36Sopenharmony_ciextern const char *field_order; 2262306a36Sopenharmony_ciextern const char default_parent_pattern[]; 2362306a36Sopenharmony_ciextern const char *parent_pattern; 2462306a36Sopenharmony_ciextern const char *default_sort_order; 2562306a36Sopenharmony_ciextern regex_t ignore_callees_regex; 2662306a36Sopenharmony_ciextern int have_ignore_callees; 2762306a36Sopenharmony_ciextern enum sort_mode sort__mode; 2862306a36Sopenharmony_ciextern struct sort_entry sort_comm; 2962306a36Sopenharmony_ciextern struct sort_entry sort_dso; 3062306a36Sopenharmony_ciextern struct sort_entry sort_sym; 3162306a36Sopenharmony_ciextern struct sort_entry sort_parent; 3262306a36Sopenharmony_ciextern struct sort_entry sort_dso_from; 3362306a36Sopenharmony_ciextern struct sort_entry sort_dso_to; 3462306a36Sopenharmony_ciextern struct sort_entry sort_sym_from; 3562306a36Sopenharmony_ciextern struct sort_entry sort_sym_to; 3662306a36Sopenharmony_ciextern struct sort_entry sort_srcline; 3762306a36Sopenharmony_ciextern const char default_mem_sort_order[]; 3862306a36Sopenharmony_ciextern bool chk_double_cl; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct res_sample { 4162306a36Sopenharmony_ci u64 time; 4262306a36Sopenharmony_ci int cpu; 4362306a36Sopenharmony_ci int tid; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct he_stat { 4762306a36Sopenharmony_ci u64 period; 4862306a36Sopenharmony_ci u64 period_sys; 4962306a36Sopenharmony_ci u64 period_us; 5062306a36Sopenharmony_ci u64 period_guest_sys; 5162306a36Sopenharmony_ci u64 period_guest_us; 5262306a36Sopenharmony_ci u32 nr_events; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistruct namespace_id { 5662306a36Sopenharmony_ci u64 dev; 5762306a36Sopenharmony_ci u64 ino; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct hist_entry_diff { 6162306a36Sopenharmony_ci bool computed; 6262306a36Sopenharmony_ci union { 6362306a36Sopenharmony_ci /* PERF_HPP__DELTA */ 6462306a36Sopenharmony_ci double period_ratio_delta; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* PERF_HPP__RATIO */ 6762306a36Sopenharmony_ci double period_ratio; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* HISTC_WEIGHTED_DIFF */ 7062306a36Sopenharmony_ci s64 wdiff; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* PERF_HPP_DIFF__CYCLES */ 7362306a36Sopenharmony_ci s64 cycles; 7462306a36Sopenharmony_ci }; 7562306a36Sopenharmony_ci struct stats stats; 7662306a36Sopenharmony_ci unsigned long svals[NUM_SPARKS]; 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistruct hist_entry_ops { 8062306a36Sopenharmony_ci void *(*new)(size_t size); 8162306a36Sopenharmony_ci void (*free)(void *ptr); 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/** 8562306a36Sopenharmony_ci * struct hist_entry - histogram entry 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * @row_offset - offset from the first callchain expanded to appear on screen 8862306a36Sopenharmony_ci * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_cistruct hist_entry { 9162306a36Sopenharmony_ci struct rb_node rb_node_in; 9262306a36Sopenharmony_ci struct rb_node rb_node; 9362306a36Sopenharmony_ci union { 9462306a36Sopenharmony_ci struct list_head node; 9562306a36Sopenharmony_ci struct list_head head; 9662306a36Sopenharmony_ci } pairs; 9762306a36Sopenharmony_ci struct he_stat stat; 9862306a36Sopenharmony_ci struct he_stat *stat_acc; 9962306a36Sopenharmony_ci struct map_symbol ms; 10062306a36Sopenharmony_ci struct thread *thread; 10162306a36Sopenharmony_ci struct comm *comm; 10262306a36Sopenharmony_ci struct namespace_id cgroup_id; 10362306a36Sopenharmony_ci u64 cgroup; 10462306a36Sopenharmony_ci u64 ip; 10562306a36Sopenharmony_ci u64 transaction; 10662306a36Sopenharmony_ci s32 socket; 10762306a36Sopenharmony_ci s32 cpu; 10862306a36Sopenharmony_ci u64 code_page_size; 10962306a36Sopenharmony_ci u64 weight; 11062306a36Sopenharmony_ci u64 ins_lat; 11162306a36Sopenharmony_ci u64 p_stage_cyc; 11262306a36Sopenharmony_ci u8 cpumode; 11362306a36Sopenharmony_ci u8 depth; 11462306a36Sopenharmony_ci struct simd_flags simd_flags; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* We are added by hists__add_dummy_entry. */ 11762306a36Sopenharmony_ci bool dummy; 11862306a36Sopenharmony_ci bool leaf; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci char level; 12162306a36Sopenharmony_ci u8 filtered; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci u16 callchain_size; 12462306a36Sopenharmony_ci union { 12562306a36Sopenharmony_ci /* 12662306a36Sopenharmony_ci * Since perf diff only supports the stdio output, TUI 12762306a36Sopenharmony_ci * fields are only accessed from perf report (or perf 12862306a36Sopenharmony_ci * top). So make it a union to reduce memory usage. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci struct hist_entry_diff diff; 13162306a36Sopenharmony_ci struct /* for TUI */ { 13262306a36Sopenharmony_ci u16 row_offset; 13362306a36Sopenharmony_ci u16 nr_rows; 13462306a36Sopenharmony_ci bool init_have_children; 13562306a36Sopenharmony_ci bool unfolded; 13662306a36Sopenharmony_ci bool has_children; 13762306a36Sopenharmony_ci bool has_no_entry; 13862306a36Sopenharmony_ci }; 13962306a36Sopenharmony_ci }; 14062306a36Sopenharmony_ci char *srcline; 14162306a36Sopenharmony_ci char *srcfile; 14262306a36Sopenharmony_ci struct symbol *parent; 14362306a36Sopenharmony_ci struct branch_info *branch_info; 14462306a36Sopenharmony_ci long time; 14562306a36Sopenharmony_ci struct hists *hists; 14662306a36Sopenharmony_ci struct mem_info *mem_info; 14762306a36Sopenharmony_ci struct block_info *block_info; 14862306a36Sopenharmony_ci struct kvm_info *kvm_info; 14962306a36Sopenharmony_ci void *raw_data; 15062306a36Sopenharmony_ci u32 raw_size; 15162306a36Sopenharmony_ci int num_res; 15262306a36Sopenharmony_ci struct res_sample *res_samples; 15362306a36Sopenharmony_ci void *trace_output; 15462306a36Sopenharmony_ci struct perf_hpp_list *hpp_list; 15562306a36Sopenharmony_ci struct hist_entry *parent_he; 15662306a36Sopenharmony_ci struct hist_entry_ops *ops; 15762306a36Sopenharmony_ci union { 15862306a36Sopenharmony_ci /* this is for hierarchical entry structure */ 15962306a36Sopenharmony_ci struct { 16062306a36Sopenharmony_ci struct rb_root_cached hroot_in; 16162306a36Sopenharmony_ci struct rb_root_cached hroot_out; 16262306a36Sopenharmony_ci }; /* non-leaf entries */ 16362306a36Sopenharmony_ci struct rb_root sorted_chain; /* leaf entry has callchains */ 16462306a36Sopenharmony_ci }; 16562306a36Sopenharmony_ci struct callchain_root callchain[0]; /* must be last member */ 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic __pure inline bool hist_entry__has_callchains(struct hist_entry *he) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci return he->callchain_size != 0; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciint hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic inline bool hist_entry__has_pairs(struct hist_entry *he) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci return !list_empty(&he->pairs.node); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci if (hist_entry__has_pairs(he)) 18362306a36Sopenharmony_ci return list_entry(he->pairs.node.next, struct hist_entry, pairs.node); 18462306a36Sopenharmony_ci return NULL; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic inline void hist_entry__add_pair(struct hist_entry *pair, 18862306a36Sopenharmony_ci struct hist_entry *he) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci list_add_tail(&pair->pairs.node, &he->pairs.head); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic inline float hist_entry__get_percent_limit(struct hist_entry *he) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci u64 period = he->stat.period; 19662306a36Sopenharmony_ci u64 total_period = hists__total_period(he->hists); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (unlikely(total_period == 0)) 19962306a36Sopenharmony_ci return 0; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (symbol_conf.cumulate_callchain) 20262306a36Sopenharmony_ci period = he->stat_acc->period; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return period * 100.0 / total_period; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cienum sort_mode { 20862306a36Sopenharmony_ci SORT_MODE__NORMAL, 20962306a36Sopenharmony_ci SORT_MODE__BRANCH, 21062306a36Sopenharmony_ci SORT_MODE__MEMORY, 21162306a36Sopenharmony_ci SORT_MODE__TOP, 21262306a36Sopenharmony_ci SORT_MODE__DIFF, 21362306a36Sopenharmony_ci SORT_MODE__TRACEPOINT, 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cienum sort_type { 21762306a36Sopenharmony_ci /* common sort keys */ 21862306a36Sopenharmony_ci SORT_PID, 21962306a36Sopenharmony_ci SORT_COMM, 22062306a36Sopenharmony_ci SORT_DSO, 22162306a36Sopenharmony_ci SORT_SYM, 22262306a36Sopenharmony_ci SORT_PARENT, 22362306a36Sopenharmony_ci SORT_CPU, 22462306a36Sopenharmony_ci SORT_SOCKET, 22562306a36Sopenharmony_ci SORT_SRCLINE, 22662306a36Sopenharmony_ci SORT_SRCFILE, 22762306a36Sopenharmony_ci SORT_LOCAL_WEIGHT, 22862306a36Sopenharmony_ci SORT_GLOBAL_WEIGHT, 22962306a36Sopenharmony_ci SORT_TRANSACTION, 23062306a36Sopenharmony_ci SORT_TRACE, 23162306a36Sopenharmony_ci SORT_SYM_SIZE, 23262306a36Sopenharmony_ci SORT_DSO_SIZE, 23362306a36Sopenharmony_ci SORT_CGROUP, 23462306a36Sopenharmony_ci SORT_CGROUP_ID, 23562306a36Sopenharmony_ci SORT_SYM_IPC_NULL, 23662306a36Sopenharmony_ci SORT_TIME, 23762306a36Sopenharmony_ci SORT_CODE_PAGE_SIZE, 23862306a36Sopenharmony_ci SORT_LOCAL_INS_LAT, 23962306a36Sopenharmony_ci SORT_GLOBAL_INS_LAT, 24062306a36Sopenharmony_ci SORT_LOCAL_PIPELINE_STAGE_CYC, 24162306a36Sopenharmony_ci SORT_GLOBAL_PIPELINE_STAGE_CYC, 24262306a36Sopenharmony_ci SORT_ADDR, 24362306a36Sopenharmony_ci SORT_LOCAL_RETIRE_LAT, 24462306a36Sopenharmony_ci SORT_GLOBAL_RETIRE_LAT, 24562306a36Sopenharmony_ci SORT_SIMD, 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* branch stack specific sort keys */ 24862306a36Sopenharmony_ci __SORT_BRANCH_STACK, 24962306a36Sopenharmony_ci SORT_DSO_FROM = __SORT_BRANCH_STACK, 25062306a36Sopenharmony_ci SORT_DSO_TO, 25162306a36Sopenharmony_ci SORT_SYM_FROM, 25262306a36Sopenharmony_ci SORT_SYM_TO, 25362306a36Sopenharmony_ci SORT_MISPREDICT, 25462306a36Sopenharmony_ci SORT_ABORT, 25562306a36Sopenharmony_ci SORT_IN_TX, 25662306a36Sopenharmony_ci SORT_CYCLES, 25762306a36Sopenharmony_ci SORT_SRCLINE_FROM, 25862306a36Sopenharmony_ci SORT_SRCLINE_TO, 25962306a36Sopenharmony_ci SORT_SYM_IPC, 26062306a36Sopenharmony_ci SORT_ADDR_FROM, 26162306a36Sopenharmony_ci SORT_ADDR_TO, 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* memory mode specific sort keys */ 26462306a36Sopenharmony_ci __SORT_MEMORY_MODE, 26562306a36Sopenharmony_ci SORT_MEM_DADDR_SYMBOL = __SORT_MEMORY_MODE, 26662306a36Sopenharmony_ci SORT_MEM_DADDR_DSO, 26762306a36Sopenharmony_ci SORT_MEM_LOCKED, 26862306a36Sopenharmony_ci SORT_MEM_TLB, 26962306a36Sopenharmony_ci SORT_MEM_LVL, 27062306a36Sopenharmony_ci SORT_MEM_SNOOP, 27162306a36Sopenharmony_ci SORT_MEM_DCACHELINE, 27262306a36Sopenharmony_ci SORT_MEM_IADDR_SYMBOL, 27362306a36Sopenharmony_ci SORT_MEM_PHYS_DADDR, 27462306a36Sopenharmony_ci SORT_MEM_DATA_PAGE_SIZE, 27562306a36Sopenharmony_ci SORT_MEM_BLOCKED, 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/* 27962306a36Sopenharmony_ci * configurable sorting bits 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistruct sort_entry { 28362306a36Sopenharmony_ci const char *se_header; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); 28662306a36Sopenharmony_ci int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *); 28762306a36Sopenharmony_ci int64_t (*se_sort)(struct hist_entry *, struct hist_entry *); 28862306a36Sopenharmony_ci int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size, 28962306a36Sopenharmony_ci unsigned int width); 29062306a36Sopenharmony_ci int (*se_filter)(struct hist_entry *he, int type, const void *arg); 29162306a36Sopenharmony_ci void (*se_init)(struct hist_entry *he); 29262306a36Sopenharmony_ci u8 se_width_idx; 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistruct block_hist { 29662306a36Sopenharmony_ci struct hists block_hists; 29762306a36Sopenharmony_ci struct perf_hpp_list block_list; 29862306a36Sopenharmony_ci struct perf_hpp_fmt block_fmt; 29962306a36Sopenharmony_ci int block_idx; 30062306a36Sopenharmony_ci bool valid; 30162306a36Sopenharmony_ci struct hist_entry he; 30262306a36Sopenharmony_ci}; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciextern struct sort_entry sort_thread; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistruct evlist; 30762306a36Sopenharmony_cistruct tep_handle; 30862306a36Sopenharmony_ciint setup_sorting(struct evlist *evlist); 30962306a36Sopenharmony_ciint setup_output_field(void); 31062306a36Sopenharmony_civoid reset_output_field(void); 31162306a36Sopenharmony_civoid sort__setup_elide(FILE *fp); 31262306a36Sopenharmony_civoid perf_hpp__set_elide(int idx, bool elide); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cichar *sort_help(const char *prefix); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ciint report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cibool is_strict_order(const char *order); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ciint hpp_dimension__add_output(unsigned col); 32162306a36Sopenharmony_civoid reset_dimensions(void); 32262306a36Sopenharmony_ciint sort_dimension__add(struct perf_hpp_list *list, const char *tok, 32362306a36Sopenharmony_ci struct evlist *evlist, 32462306a36Sopenharmony_ci int level); 32562306a36Sopenharmony_ciint output_field_add(struct perf_hpp_list *list, char *tok); 32662306a36Sopenharmony_ciint64_t 32762306a36Sopenharmony_cisort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right); 32862306a36Sopenharmony_ciint64_t 32962306a36Sopenharmony_cisort__daddr_cmp(struct hist_entry *left, struct hist_entry *right); 33062306a36Sopenharmony_ciint64_t 33162306a36Sopenharmony_cisort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right); 33262306a36Sopenharmony_ciint64_t 33362306a36Sopenharmony_ci_sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r); 33462306a36Sopenharmony_cichar *hist_entry__srcline(struct hist_entry *he); 33562306a36Sopenharmony_ci#endif /* __PERF_SORT_H */ 336