summaryrefslogtreecommitdiff
path: root/tools/perf/util/sort.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/sort.c')
-rw-r--r--tools/perf/util/sort.c418
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;
}