diff options
Diffstat (limited to 'tools/perf/util/sort.c')
| -rw-r--r-- | tools/perf/util/sort.c | 418 |
1 files changed, 295 insertions, 123 deletions
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 42d5cd7ef4e2..58638ec9ae0e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,38 +1,45 @@ // SPDX-License-Identifier: GPL-2.0 +#include "sort.h" + +#include <ctype.h> #include <errno.h> #include <inttypes.h> -#include <regex.h> #include <stdlib.h> + +#include <elf.h> +#include <linux/kernel.h> #include <linux/mman.h> +#include <linux/string.h> #include <linux/time64.h> + +#include <regex.h> + +#include "annotate-data.h" +#include "annotate.h" +#include "branch.h" +#include "cacheline.h" +#include "cgroup.h" +#include "comm.h" #include "debug.h" #include "dso.h" -#include "sort.h" +#include "event.h" +#include "evlist.h" +#include "evsel.h" #include "hist.h" -#include "cacheline.h" -#include "comm.h" +#include "machine.h" #include "map.h" -#include "maps.h" -#include "symbol.h" #include "map_symbol.h" -#include "branch.h" -#include "thread.h" -#include "evsel.h" -#include "evlist.h" -#include "srcline.h" -#include "strlist.h" -#include "strbuf.h" +#include "maps.h" #include "mem-events.h" #include "mem-info.h" -#include "annotate.h" -#include "annotate-data.h" -#include "event.h" +#include "session.h" +#include "srcline.h" +#include "strbuf.h" +#include "strlist.h" +#include "symbol.h" +#include "thread.h" #include "time-utils.h" -#include "cgroup.h" -#include "machine.h" #include "trace-event.h" -#include <linux/kernel.h> -#include <linux/string.h> #ifdef HAVE_LIBTRACEEVENT #include <event-parse.h> @@ -42,11 +49,11 @@ regex_t parent_regex; const char default_parent_pattern[] = "^sys_|^do_page_fault"; const char *parent_pattern = default_parent_pattern; const char *default_sort_order = "comm,dso,symbol"; -const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; +static const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked,blocked,local_ins_lat,local_p_stage_cyc"; -const char default_top_sort_order[] = "dso,symbol"; -const char default_diff_sort_order[] = "dso,symbol"; -const char default_tracepoint_sort_order[] = "trace"; +static const char default_top_sort_order[] = "dso,symbol"; +static const char default_diff_sort_order[] = "dso,symbol"; +static const char default_tracepoint_sort_order[] = "trace"; const char *sort_order; const char *field_order; regex_t ignore_callees_regex; @@ -171,7 +178,7 @@ static int hist_entry__tgid_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%7d:%-*.*s", tgid, width, width, comm ?: ""); } -struct sort_entry sort_tgid = { +static struct sort_entry sort_tgid = { .se_header = " Tgid:Command", .se_cmp = sort__tgid_cmp, .se_snprintf = hist_entry__tgid_snprintf, @@ -193,8 +200,12 @@ static const char *hist_entry__get_simd_name(struct simd_flags *simd_flags) { u64 arch = simd_flags->arch; - if (arch & SIMD_OP_FLAGS_ARCH_SVE) + if (arch == SIMD_OP_FLAGS_ARCH_SVE) return "SVE"; + else if (arch == SIMD_OP_FLAGS_ARCH_SME) + return "SME"; + else if (arch == SIMD_OP_FLAGS_ARCH_ASE) + return "ASE"; else return "n/a"; } @@ -203,21 +214,26 @@ static int hist_entry__simd_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width __maybe_unused) { const char *name; + const char *pred_str = "."; if (!he->simd_flags.arch) return repsep_snprintf(bf, size, ""); name = hist_entry__get_simd_name(&he->simd_flags); - if (he->simd_flags.pred & SIMD_OP_FLAGS_PRED_EMPTY) - return repsep_snprintf(bf, size, "[e] %s", name); - else if (he->simd_flags.pred & SIMD_OP_FLAGS_PRED_PARTIAL) - return repsep_snprintf(bf, size, "[p] %s", name); + if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_EMPTY) + pred_str = "e"; + else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_PARTIAL) + pred_str = "p"; + else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_DISABLED) + pred_str = "d"; + else if (he->simd_flags.pred == SIMD_OP_FLAGS_PRED_FULL) + pred_str = "f"; - return repsep_snprintf(bf, size, "[.] %s", name); + return repsep_snprintf(bf, size, "[%s] %s", pred_str, name); } -struct sort_entry sort_simd = { +static struct sort_entry sort_simd = { .se_header = "Simd ", .se_cmp = sort__simd_cmp, .se_snprintf = hist_entry__simd_snprintf, @@ -265,6 +281,115 @@ struct sort_entry sort_comm = { .se_width_idx = HISTC_COMM, }; +/* --sort comm_nodigit */ + +size_t sort__comm_nodigit_len(struct hist_entry *entry) +{ + const char *comm = comm__str(entry->comm); + size_t index, len_nodigit = 0; + bool in_number = false; + + if (!comm) + return 0; + + for (index = 0; comm[index]; index++) { + if (!isdigit((unsigned char)comm[index])) { + in_number = false; + len_nodigit++; + } else if (!in_number) { + in_number = true; + len_nodigit += 3; /* <N> */ + } + } + + return len_nodigit; +} + +static int64_t strcmp_nodigit(const char *left, const char *right) +{ + for (;;) { + while (*left && isdigit((unsigned char)*left)) + left++; + while (*right && isdigit((unsigned char)*right)) + right++; + if (*left == *right && !*left) { + return 0; + } else if (*left == *right) { + left++; + right++; + } else { + return (int64_t)((unsigned char)*left - (unsigned char)*right); + } + } +} + +static int64_t +sort__comm_nodigit_cmp(struct hist_entry *left, struct hist_entry *right) +{ + return strcmp_nodigit(comm__str(right->comm), comm__str(left->comm)); +} + +static int64_t +sort__comm_nodigit_collapse(struct hist_entry *left, struct hist_entry *right) +{ + return strcmp_nodigit(comm__str(right->comm), comm__str(left->comm)); +} + +static int64_t +sort__comm_nodigit_sort(struct hist_entry *left, struct hist_entry *right) +{ + return strcmp_nodigit(comm__str(right->comm), comm__str(left->comm)); +} + +static int hist_entry__comm_nodigit_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) +{ + int ret = 0; + unsigned int print_len, printed = 0, start = 0, end = 0; + bool in_digit; + const char *comm = comm__str(he->comm), *print; + + while (printed < width && printed < size && comm[start]) { + in_digit = !!isdigit((unsigned char)comm[start]); + end = start + 1; + while (comm[end] && !!isdigit((unsigned char)comm[end]) == in_digit) + end++; + if (in_digit) { + print_len = 3; /* <N> */ + print = "<N>"; + } else { + print_len = end - start; + print = &comm[start]; + } + print_len = min(print_len, width - printed); + ret = repsep_snprintf(bf + printed, size - printed, "%-.*s", + print_len, print); + if (ret < 0) + return ret; + start = end; + printed += ret; + } + /* Pad to width if necessary */ + if (printed < width && printed < size) { + ret = repsep_snprintf(bf + printed, size - printed, "%-*.*s", + width - printed, width - printed, ""); + if (ret < 0) + return ret; + printed += ret; + } + return printed; +} + +struct sort_entry sort_comm_nodigit = { + .se_header = "CommandNoDigit", + .se_cmp = sort__comm_nodigit_cmp, + .se_collapse = sort__comm_nodigit_collapse, + .se_sort = sort__comm_nodigit_sort, + .se_snprintf = hist_entry__comm_nodigit_snprintf, + .se_filter = hist_entry__thread_filter, + .se_width_idx = HISTC_COMM_NODIGIT, +}; + /* --sort dso */ static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r) @@ -344,7 +469,7 @@ int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) if (sym_l == sym_r) return 0; - if (sym_l->inlined || sym_r->inlined) { + if (symbol__inlined(sym_l) || symbol__inlined(sym_r)) { int ret = strcmp(sym_l->name, sym_r->name); if (ret) @@ -411,7 +536,7 @@ static int _hist_entry__sym_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); if (sym && map) { - if (sym->type == STT_OBJECT) { + if (symbol__type(sym) == STT_OBJECT) { ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ip - map__unmap_ip(map, sym->start)); @@ -419,7 +544,7 @@ static int _hist_entry__sym_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "%.*s", width - ret, sym->name); - if (sym->inlined) + if (symbol__inlined(sym)) ret += repsep_snprintf(bf + ret, size - ret, " (inlined)"); } @@ -494,7 +619,7 @@ hist_entry__symoff_snprintf(struct hist_entry *he, char *bf, size_t size, unsign return repsep_snprintf(bf, size, "[%c] %s+0x%llx", he->level, sym->name, he->ip - sym->start); } -struct sort_entry sort_sym_offset = { +static struct sort_entry sort_sym_offset = { .se_header = "Symbol Offset", .se_cmp = sort__symoff_cmp, .se_sort = sort__symoff_sort, @@ -605,7 +730,7 @@ static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from); } -struct sort_entry sort_srcline_from = { +static struct sort_entry sort_srcline_from = { .se_header = "From Source:Line", .se_cmp = sort__srcline_from_cmp, .se_collapse = sort__srcline_from_collapse, @@ -653,7 +778,7 @@ static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to); } -struct sort_entry sort_srcline_to = { +static struct sort_entry sort_srcline_to = { .se_header = "To Source:Line", .se_cmp = sort__srcline_to_cmp, .se_collapse = sort__srcline_to_collapse, @@ -689,7 +814,7 @@ static int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*s", width, tmp); } -struct sort_entry sort_sym_ipc = { +static struct sort_entry sort_sym_ipc = { .se_header = "IPC [IPC Coverage]", .se_cmp = sort__sym_cmp, .se_snprintf = hist_entry__sym_ipc_snprintf, @@ -707,7 +832,7 @@ static int hist_entry__sym_ipc_null_snprintf(struct hist_entry *he return repsep_snprintf(bf, size, "%-*s", width, tmp); } -struct sort_entry sort_sym_ipc_null = { +static struct sort_entry sort_sym_ipc_null = { .se_header = "IPC [IPC Coverage]", .se_cmp = sort__sym_cmp, .se_snprintf = hist_entry__sym_ipc_null_snprintf, @@ -740,7 +865,7 @@ static int hist_entry__callchain_branch_predicted_snprintf( return repsep_snprintf(bf, size, "%-*.*s", width, width, str); } -struct sort_entry sort_callchain_branch_predicted = { +static struct sort_entry sort_callchain_branch_predicted = { .se_header = "Predicted", .se_cmp = sort__callchain_branch_predicted_cmp, .se_snprintf = hist_entry__callchain_branch_predicted_snprintf, @@ -770,7 +895,7 @@ static int hist_entry__callchain_branch_abort_snprintf(struct hist_entry *he, return repsep_snprintf(bf, size, "%-*.*s", width, width, str); } -struct sort_entry sort_callchain_branch_abort = { +static struct sort_entry sort_callchain_branch_abort = { .se_header = "Abort", .se_cmp = sort__callchain_branch_abort_cmp, .se_snprintf = hist_entry__callchain_branch_abort_snprintf, @@ -803,7 +928,7 @@ static int hist_entry__callchain_branch_cycles_snprintf(struct hist_entry *he, return repsep_snprintf(bf, size, "%-*.*s", width, width, str); } -struct sort_entry sort_callchain_branch_cycles = { +static struct sort_entry sort_callchain_branch_cycles = { .se_header = "Cycles", .se_cmp = sort__callchain_branch_cycles_cmp, .se_snprintf = hist_entry__callchain_branch_cycles_snprintf, @@ -870,7 +995,7 @@ static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-.*s", width, he->srcfile); } -struct sort_entry sort_srcfile = { +static struct sort_entry sort_srcfile = { .se_header = "Source File", .se_cmp = sort__srcfile_cmp, .se_collapse = sort__srcfile_collapse, @@ -922,7 +1047,7 @@ static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu); } -struct sort_entry sort_cpu = { +static struct sort_entry sort_cpu = { .se_header = "CPU", .se_cmp = sort__cpu_cmp, .se_snprintf = hist_entry__cpu_snprintf, @@ -953,7 +1078,7 @@ static int hist_entry__parallelism_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%*d", width, he->parallelism); } -struct sort_entry sort_parallelism = { +static struct sort_entry sort_parallelism = { .se_header = "Parallelism", .se_cmp = sort__parallelism_cmp, .se_filter = hist_entry__parallelism_filter, @@ -994,7 +1119,7 @@ static int hist_entry__cgroup_id_snprintf(struct hist_entry *he, he->cgroup_id.ino); } -struct sort_entry sort_cgroup_id = { +static struct sort_entry sort_cgroup_id = { .se_header = "cgroup id (dev/inode)", .se_cmp = sort__cgroup_id_cmp, .se_snprintf = hist_entry__cgroup_id_snprintf, @@ -1027,7 +1152,7 @@ static int hist_entry__cgroup_snprintf(struct hist_entry *he, return repsep_snprintf(bf, size, "%s", cgrp_name); } -struct sort_entry sort_cgroup = { +static struct sort_entry sort_cgroup = { .se_header = "Cgroup", .se_cmp = sort__cgroup_cmp, .se_snprintf = hist_entry__cgroup_snprintf, @@ -1058,7 +1183,7 @@ static int hist_entry__socket_filter(struct hist_entry *he, int type, const void return sk >= 0 && he->socket != sk; } -struct sort_entry sort_socket = { +static struct sort_entry sort_socket = { .se_header = "Socket", .se_cmp = sort__socket_cmp, .se_snprintf = hist_entry__socket_snprintf, @@ -1089,7 +1214,7 @@ static int hist_entry__time_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-.*s", width, he_time); } -struct sort_entry sort_time = { +static struct sort_entry sort_time = { .se_header = "Time", .se_cmp = sort__time_cmp, .se_snprintf = hist_entry__time_snprintf, @@ -1158,7 +1283,7 @@ static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-.*s", width, he->trace_output); } -struct sort_entry sort_trace = { +static struct sort_entry sort_trace = { .se_header = "Trace output", .se_cmp = sort__trace_cmp, .se_snprintf = hist_entry__trace_snprintf, @@ -1358,7 +1483,7 @@ static int _hist_entry__addr_snprintf(struct map_symbol *ms, ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); if (sym && map) { - if (sym->type == STT_OBJECT) { + if (symbol__type(sym) == STT_OBJECT) { ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ip - map__unmap_ip(map, sym->start)); @@ -1453,7 +1578,7 @@ sort__addr_to_cmp(struct hist_entry *left, struct hist_entry *right) return _sort__addr_cmp(to_l->addr, to_r->addr); } -struct sort_entry sort_addr_from = { +static struct sort_entry sort_addr_from = { .se_header = "Source Address", .se_cmp = sort__addr_from_cmp, .se_snprintf = hist_entry__addr_from_snprintf, @@ -1461,7 +1586,7 @@ struct sort_entry sort_addr_from = { .se_width_idx = HISTC_ADDR_FROM, }; -struct sort_entry sort_addr_to = { +static struct sort_entry sort_addr_to = { .se_header = "Target Address", .se_cmp = sort__addr_to_cmp, .se_snprintf = hist_entry__addr_to_snprintf, @@ -1518,7 +1643,7 @@ static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf, he->branch_info->flags.cycles); } -struct sort_entry sort_cycles = { +static struct sort_entry sort_cycles = { .se_header = "Basic Block Cycles", .se_cmp = sort__cycles_cmp, .se_snprintf = hist_entry__cycles_snprintf, @@ -1808,7 +1933,7 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf, return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width); } -struct sort_entry sort_mispredict = { +static struct sort_entry sort_mispredict = { .se_header = "Branch Mispredicted", .se_cmp = sort__mispredict_cmp, .se_snprintf = hist_entry__mispredict_snprintf, @@ -1827,7 +1952,7 @@ static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*llu", width, he->weight); } -struct sort_entry sort_local_weight = { +static struct sort_entry sort_local_weight = { .se_header = "Local Weight", .se_cmp = sort__weight_cmp, .se_snprintf = hist_entry__local_weight_snprintf, @@ -1841,7 +1966,7 @@ static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, he->weight * he->stat.nr_events); } -struct sort_entry sort_global_weight = { +static struct sort_entry sort_global_weight = { .se_header = "Weight", .se_cmp = sort__weight_cmp, .se_snprintf = hist_entry__global_weight_snprintf, @@ -1860,7 +1985,7 @@ static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat); } -struct sort_entry sort_local_ins_lat = { +static struct sort_entry sort_local_ins_lat = { .se_header = "Local INSTR Latency", .se_cmp = sort__ins_lat_cmp, .se_snprintf = hist_entry__local_ins_lat_snprintf, @@ -1874,7 +1999,7 @@ static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf, he->ins_lat * he->stat.nr_events); } -struct sort_entry sort_global_ins_lat = { +static struct sort_entry sort_global_ins_lat = { .se_header = "INSTR Latency", .se_cmp = sort__ins_lat_cmp, .se_snprintf = hist_entry__global_ins_lat_snprintf, @@ -1900,70 +2025,70 @@ static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*u", width, he->weight3); } -struct sort_entry sort_local_p_stage_cyc = { +static struct sort_entry sort_local_p_stage_cyc = { .se_header = "Local Pipeline Stage Cycle", .se_cmp = sort__p_stage_cyc_cmp, .se_snprintf = hist_entry__p_stage_cyc_snprintf, .se_width_idx = HISTC_LOCAL_P_STAGE_CYC, }; -struct sort_entry sort_global_p_stage_cyc = { +static struct sort_entry sort_global_p_stage_cyc = { .se_header = "Pipeline Stage Cycle", .se_cmp = sort__p_stage_cyc_cmp, .se_snprintf = hist_entry__global_p_stage_cyc_snprintf, .se_width_idx = HISTC_GLOBAL_P_STAGE_CYC, }; -struct sort_entry sort_mem_daddr_sym = { +static struct sort_entry sort_mem_daddr_sym = { .se_header = "Data Symbol", .se_cmp = sort__daddr_cmp, .se_snprintf = hist_entry__daddr_snprintf, .se_width_idx = HISTC_MEM_DADDR_SYMBOL, }; -struct sort_entry sort_mem_iaddr_sym = { +static struct sort_entry sort_mem_iaddr_sym = { .se_header = "Code Symbol", .se_cmp = sort__iaddr_cmp, .se_snprintf = hist_entry__iaddr_snprintf, .se_width_idx = HISTC_MEM_IADDR_SYMBOL, }; -struct sort_entry sort_mem_daddr_dso = { +static struct sort_entry sort_mem_daddr_dso = { .se_header = "Data Object", .se_cmp = sort__dso_daddr_cmp, .se_snprintf = hist_entry__dso_daddr_snprintf, .se_width_idx = HISTC_MEM_DADDR_DSO, }; -struct sort_entry sort_mem_locked = { +static struct sort_entry sort_mem_locked = { .se_header = "Locked", .se_cmp = sort__locked_cmp, .se_snprintf = hist_entry__locked_snprintf, .se_width_idx = HISTC_MEM_LOCKED, }; -struct sort_entry sort_mem_tlb = { +static struct sort_entry sort_mem_tlb = { .se_header = "TLB access", .se_cmp = sort__tlb_cmp, .se_snprintf = hist_entry__tlb_snprintf, .se_width_idx = HISTC_MEM_TLB, }; -struct sort_entry sort_mem_lvl = { +static struct sort_entry sort_mem_lvl = { .se_header = "Memory access", .se_cmp = sort__lvl_cmp, .se_snprintf = hist_entry__lvl_snprintf, .se_width_idx = HISTC_MEM_LVL, }; -struct sort_entry sort_mem_snoop = { +static struct sort_entry sort_mem_snoop = { .se_header = "Snoop", .se_cmp = sort__snoop_cmp, .se_snprintf = hist_entry__snoop_snprintf, .se_width_idx = HISTC_MEM_SNOOP, }; -struct sort_entry sort_mem_dcacheline = { +static struct sort_entry sort_mem_dcacheline = { .se_header = "Data Cacheline", .se_cmp = sort__dcacheline_cmp, .se_snprintf = hist_entry__dcacheline_snprintf, @@ -1998,7 +2123,7 @@ static int hist_entry__blocked_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%.*s", width, out); } -struct sort_entry sort_mem_blocked = { +static struct sort_entry sort_mem_blocked = { .se_header = "Blocked", .se_cmp = sort__blocked_cmp, .se_snprintf = hist_entry__blocked_snprintf, @@ -2039,7 +2164,7 @@ static int hist_entry__phys_daddr_snprintf(struct hist_entry *he, char *bf, return width; } -struct sort_entry sort_mem_phys_daddr = { +static struct sort_entry sort_mem_phys_daddr = { .se_header = "Data Physical Address", .se_cmp = sort__phys_daddr_cmp, .se_snprintf = hist_entry__phys_daddr_snprintf, @@ -2068,7 +2193,7 @@ static int hist_entry__data_page_size_snprintf(struct hist_entry *he, char *bf, get_page_size_name(mem_info__daddr(he->mem_info)->data_page_size, str)); } -struct sort_entry sort_mem_data_page_size = { +static struct sort_entry sort_mem_data_page_size = { .se_header = "Data Page Size", .se_cmp = sort__data_page_size_cmp, .se_snprintf = hist_entry__data_page_size_snprintf, @@ -2093,7 +2218,7 @@ static int hist_entry__code_page_size_snprintf(struct hist_entry *he, char *bf, get_page_size_name(he->code_page_size, str)); } -struct sort_entry sort_code_page_size = { +static struct sort_entry sort_code_page_size = { .se_header = "Code Page Size", .se_cmp = sort__code_page_size_cmp, .se_snprintf = hist_entry__code_page_size_snprintf, @@ -2125,7 +2250,7 @@ static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*s", width, out); } -struct sort_entry sort_abort = { +static struct sort_entry sort_abort = { .se_header = "Transaction abort", .se_cmp = sort__abort_cmp, .se_snprintf = hist_entry__abort_snprintf, @@ -2157,7 +2282,7 @@ static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*s", width, out); } -struct sort_entry sort_in_tx = { +static struct sort_entry sort_in_tx = { .se_header = "Branch in transaction", .se_cmp = sort__in_tx_cmp, .se_snprintf = hist_entry__in_tx_snprintf, @@ -2229,7 +2354,7 @@ static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-*s", width, buf); } -struct sort_entry sort_transaction = { +static struct sort_entry sort_transaction = { .se_header = "Transaction ", .se_cmp = sort__transaction_cmp, .se_snprintf = hist_entry__transaction_snprintf, @@ -2268,7 +2393,7 @@ static int hist_entry__sym_size_snprintf(struct hist_entry *he, char *bf, return _hist_entry__sym_size_snprintf(he->ms.sym, bf, size, width); } -struct sort_entry sort_sym_size = { +static struct sort_entry sort_sym_size = { .se_header = "Symbol size", .se_cmp = sort__sym_size_cmp, .se_snprintf = hist_entry__sym_size_snprintf, @@ -2307,7 +2432,7 @@ static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf, return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width); } -struct sort_entry sort_dso_size = { +static struct sort_entry sort_dso_size = { .se_header = "DSO size", .se_cmp = sort__dso_size_cmp, .se_snprintf = hist_entry__dso_size_snprintf, @@ -2344,7 +2469,7 @@ static int hist_entry__addr_snprintf(struct hist_entry *he, char *bf, return repsep_snprintf(bf, size, "%-#*llx", width, ip); } -struct sort_entry sort_addr = { +static struct sort_entry sort_addr = { .se_header = "Address", .se_cmp = sort__addr_cmp, .se_snprintf = hist_entry__addr_snprintf, @@ -2462,7 +2587,7 @@ static int hist_entry__typeoff_snprintf(struct hist_entry *he, char *bf, he->mem_type_off, buf); } -struct sort_entry sort_type_offset = { +static struct sort_entry sort_type_offset = { .se_header = "Data Type Offset", .se_cmp = sort__type_cmp, .se_collapse = sort__typeoff_sort, @@ -2474,7 +2599,26 @@ struct sort_entry sort_type_offset = { /* --sort typecln */ -#define DEFAULT_CACHELINE_SIZE 64 +static int +hist_entry__cln_size(struct hist_entry *he) +{ + int ret = 0; + + if (he && he->hists) { + struct evsel *evsel = hists_to_evsel(he->hists); + + if (evsel) { + struct perf_session *session = evsel__session(evsel); + + ret = session->header.env.cln_size; + } + } + + if (ret < 1) + ret = DEFAULT_CACHELINE_SIZE; // avoid div/0 later + + return ret; +} static int64_t sort__typecln_sort(struct hist_entry *left, struct hist_entry *right) @@ -2482,11 +2626,9 @@ sort__typecln_sort(struct hist_entry *left, struct hist_entry *right) struct annotated_data_type *left_type = left->mem_type; struct annotated_data_type *right_type = right->mem_type; int64_t left_cln, right_cln; + int64_t cln_size_left = hist_entry__cln_size(left); + int64_t cln_size_right = hist_entry__cln_size(right); int64_t ret; - int cln_size = cacheline_size(); - - if (cln_size == 0) - cln_size = DEFAULT_CACHELINE_SIZE; if (!left_type) { sort__type_init(left); @@ -2502,8 +2644,8 @@ sort__typecln_sort(struct hist_entry *left, struct hist_entry *right) if (ret) return ret; - left_cln = left->mem_type_off / cln_size; - right_cln = right->mem_type_off / cln_size; + left_cln = left->mem_type_off / cln_size_left; + right_cln = right->mem_type_off / cln_size_right; return left_cln - right_cln; } @@ -2511,16 +2653,13 @@ static int hist_entry__typecln_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width __maybe_unused) { struct annotated_data_type *he_type = he->mem_type; - int cln_size = cacheline_size(); - - if (cln_size == 0) - cln_size = DEFAULT_CACHELINE_SIZE; + int cln_size = hist_entry__cln_size(he); return repsep_snprintf(bf, size, "%s: cache-line %d", he_type->self.type_name, he->mem_type_off / cln_size); } -struct sort_entry sort_type_cacheline = { +static struct sort_entry sort_type_cacheline = { .se_header = "Data Type Cacheline", .se_cmp = sort__type_cmp, .se_collapse = sort__typecln_sort, @@ -2539,9 +2678,10 @@ struct sort_dimension { static int arch_support_sort_key(const char *sort_key, struct perf_env *env) { - const char *arch = perf_env__arch(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_eflags=*/NULL); - if (!strcmp("x86", arch) || !strcmp("powerpc", arch)) { + if (e_machine == EM_X86_64 || e_machine == EM_386 || e_machine == EM_PPC64 || + e_machine == EM_PPC) { if (!strcmp(sort_key, "p_stage_cyc")) return 1; if (!strcmp(sort_key, "local_p_stage_cyc")) @@ -2552,14 +2692,14 @@ static int arch_support_sort_key(const char *sort_key, struct perf_env *env) static const char *arch_perf_header_entry(const char *se_header, struct perf_env *env) { - const char *arch = perf_env__arch(env); + uint16_t e_machine = perf_env__e_machine(env, /*e_eflags=*/NULL); - if (!strcmp("x86", arch)) { + if (e_machine == EM_X86_64 || e_machine == EM_386) { if (!strcmp(se_header, "Local Pipeline Stage Cycle")) return "Local Retire Latency"; else if (!strcmp(se_header, "Pipeline Stage Cycle")) return "Retire Latency"; - } else if (!strcmp("powerpc", arch)) { + } else if (e_machine == EM_PPC64 || e_machine == EM_PPC) { if (!strcmp(se_header, "Local INSTR Latency")) return "Finish Cyc"; else if (!strcmp(se_header, "INSTR Latency")) @@ -2583,6 +2723,7 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_PID, "pid", sort_thread), DIM(SORT_TGID, "tgid", sort_tgid), DIM(SORT_COMM, "comm", sort_comm), + DIM(SORT_COMM_NODIGIT, "comm_nodigit", sort_comm_nodigit), DIM(SORT_DSO, "dso", sort_dso), DIM(SORT_SYM, "symbol", sort_sym), DIM(SORT_PARENT, "parent", sort_parent), @@ -2964,7 +3105,7 @@ static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd, struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level); if (hse == NULL) - return -1; + return -ENOMEM; perf_hpp_list__register_sort_field(list, &hse->hpp); return 0; @@ -2977,7 +3118,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd, struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level); if (hse == NULL) - return -1; + return -ENOMEM; perf_hpp_list__column_register(list, &hse->hpp); return 0; @@ -3346,7 +3487,7 @@ static struct evsel *find_evsel(struct evlist *evlist, char *event_name) if (event_name[0] == '%') { int nr = strtol(event_name+1, NULL, 0); - if (nr > evlist->core.nr_entries) + if (nr > evlist__nr_entries(evlist)) return NULL; evsel = evlist__first(evlist); @@ -3579,6 +3720,8 @@ static int __sort_dimension__update(struct sort_dimension *sd, list->thread = 1; } else if (sd->entry == &sort_comm) { list->comm = 1; + } else if (sd->entry == &sort_comm_nodigit) { + list->comm_nodigit = list->comm = 1; } else if (sd->entry == &sort_type_offset) { symbol_conf.annotate_data_member = true; } else if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) { @@ -3599,14 +3742,18 @@ static int __sort_dimension__add(struct sort_dimension *sd, struct perf_hpp_list *list, int level) { + int ret; + if (sd->taken) return 0; - if (__sort_dimension__add_hpp_sort(sd, list, level) < 0) - return -1; + ret = __sort_dimension__add_hpp_sort(sd, list, level); + if (ret < 0) + return ret; - if (__sort_dimension__update(sd, list) < 0) - return -1; + ret = __sort_dimension__update(sd, list); + if (ret < 0) + return ret; sd->taken = 1; @@ -3624,7 +3771,7 @@ static int __hpp_dimension__add(struct hpp_dimension *hd, fmt = __hpp_dimension__alloc_hpp(hd, level); if (!fmt) - return -1; + return -ENOMEM; hd->taken = 1; hd->was_taken = 1; @@ -3636,14 +3783,18 @@ static int __sort_dimension__add_output(struct perf_hpp_list *list, struct sort_dimension *sd, int level) { + int ret; + if (sd->taken) return 0; - if (__sort_dimension__add_hpp_output(sd, list, level) < 0) - return -1; + ret = __sort_dimension__add_hpp_output(sd, list, level); + if (ret < 0) + return ret; - if (__sort_dimension__update(sd, list) < 0) - return -1; + ret = __sort_dimension__update(sd, list); + if (ret < 0) + return ret; sd->taken = 1; return 0; @@ -3660,7 +3811,7 @@ static int __hpp_dimension__add_output(struct perf_hpp_list *list, fmt = __hpp_dimension__alloc_hpp(hd, level); if (!fmt) - return -1; + return -ENOMEM; hd->taken = 1; perf_hpp_list__column_register(list, fmt); @@ -3726,8 +3877,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok, strlen(tok))) return -EINVAL; - __sort_dimension__add(sd, list, level); - return 0; + return __sort_dimension__add(sd, list, level); } for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { @@ -3739,8 +3889,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok, if (sort__mode != SORT_MODE__MEMORY) return -EINVAL; - __sort_dimension__add(sd, list, level); - return 0; + return __sort_dimension__add(sd, list, level); } for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { @@ -3830,15 +3979,25 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, } ret = sort_dimension__add(list, tok, evlist, env, level); - if (ret == -EINVAL) { + switch (ret) { + case 0: + break; + case -EINVAL: if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok))) ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); else ui__error("Invalid --sort key: `%s'", tok); - break; - } else if (ret == -ESRCH) { + goto out; + case -ESRCH: ui__error("Unknown --sort key: `%s'", tok); - break; + goto out; + default: { + char buf[STRERR_BUFSIZE]; + + ui__error("%s for --sort key: `%s'", + str_error_r(-ret, buf, sizeof(buf)), tok); + goto out; + } } prev_level = level; } @@ -3846,6 +4005,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, level = next_level; } while (tmp); +out: return ret; } @@ -4040,6 +4200,7 @@ static bool get_elide(int idx, FILE *output) case HISTC_DSO: return __get_elide(symbol_conf.dso_list, "dso", output); case HISTC_COMM: + case HISTC_COMM_NODIGIT: return __get_elide(symbol_conf.comm_list, "comm", output); default: break; @@ -4171,15 +4332,26 @@ static int setup_output_list(struct perf_hpp_list *list, char *str) for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { ret = output_field_add(list, tok, &level); - if (ret == -EINVAL) { - ui__error("Invalid --fields key: `%s'", tok); + switch (ret) { + case 0: break; - } else if (ret == -ESRCH) { + case -EINVAL: + ui__error("Invalid --fields key: `%s'", tok); + goto out; + case -ESRCH: ui__error("Unknown --fields key: `%s'", tok); - break; + goto out; + default: { + char buf[STRERR_BUFSIZE]; + + ui__error("%s for --fields key: `%s'", + str_error_r(-ret, buf, sizeof(buf)), tok); + goto out; + } } } +out: return ret; } |
