summaryrefslogtreecommitdiffstats
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.c196
1 files changed, 92 insertions, 104 deletions
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5d2518e89fc4..345b5ccc90f6 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2,16 +2,23 @@
#include <errno.h>
#include <inttypes.h>
#include <regex.h>
+#include <stdlib.h>
#include <linux/mman.h>
#include <linux/time64.h>
+#include "debug.h"
+#include "dso.h"
#include "sort.h"
#include "hist.h"
+#include "cacheline.h"
#include "comm.h"
#include "map.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 <traceevent/event-parse.h>
@@ -19,6 +26,7 @@
#include "annotate.h"
#include "time-utils.h"
#include <linux/kernel.h>
+#include <linux/string.h>
regex_t parent_regex;
const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -279,10 +287,12 @@ sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
return strcmp(right->ms.sym->name, left->ms.sym->name);
}
-static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
+static int _hist_entry__sym_snprintf(struct map_symbol *ms,
u64 ip, char level, char *bf, size_t size,
unsigned int width)
{
+ struct symbol *sym = ms->sym;
+ struct map *map = ms->map;
size_t ret = 0;
if (verbose > 0) {
@@ -317,7 +327,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
- return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
+ return _hist_entry__sym_snprintf(&he->ms, he->ip,
he->level, bf, size, width);
}
@@ -378,7 +388,7 @@ struct sort_entry sort_srcline = {
static char *addr_map_symbol__srcline(struct addr_map_symbol *ams)
{
- return map__srcline(ams->map, ams->al_addr, ams->sym);
+ return map__srcline(ams->ms.map, ams->al_addr, ams->ms.sym);
}
static int64_t
@@ -668,17 +678,11 @@ sort__time_cmp(struct hist_entry *left, struct hist_entry *right)
static int hist_entry__time_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
- unsigned long secs;
- unsigned long long nsecs;
char he_time[32];
- nsecs = he->time;
- secs = nsecs / NSEC_PER_SEC;
- nsecs -= secs * NSEC_PER_SEC;
-
if (symbol_conf.nanosecs)
- snprintf(he_time, sizeof he_time, "%5lu.%09llu: ",
- secs, nsecs);
+ timestamp__scnprintf_nsec(he->time, he_time,
+ sizeof(he_time));
else
timestamp__scnprintf_usec(he->time, he_time,
sizeof(he_time));
@@ -698,7 +702,7 @@ struct sort_entry sort_time = {
static char *get_trace_output(struct hist_entry *he)
{
struct trace_seq seq;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_record rec = {
.data = he->raw_data,
.size = he->raw_size,
@@ -711,7 +715,8 @@ static char *get_trace_output(struct hist_entry *he)
tep_print_fields(&seq, he->raw_data, he->raw_size,
evsel->tp_format);
} else {
- tep_event_info(&seq, evsel->tp_format, &rec);
+ tep_print_event(evsel->tp_format->tep,
+ &seq, &rec, "%s", TEP_PRINT_INFO);
}
/*
* Trim the buffer, it starts at 4KB and we're not going to
@@ -723,10 +728,10 @@ static char *get_trace_output(struct hist_entry *he)
static int64_t
sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = hists_to_evsel(left->hists);
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
return 0;
if (left->trace_output == NULL)
@@ -740,10 +745,10 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evsel = hists_to_evsel(he->hists);
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
return scnprintf(bf, size, "%-.*s", width, "N/A");
if (he->trace_output == NULL)
@@ -766,15 +771,15 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
if (!left->branch_info || !right->branch_info)
return cmp_null(left->branch_info, right->branch_info);
- return _sort__dso_cmp(left->branch_info->from.map,
- right->branch_info->from.map);
+ return _sort__dso_cmp(left->branch_info->from.ms.map,
+ right->branch_info->from.ms.map);
}
static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
if (he->branch_info)
- return _hist_entry__dso_snprintf(he->branch_info->from.map,
+ return _hist_entry__dso_snprintf(he->branch_info->from.ms.map,
bf, size, width);
else
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
@@ -788,8 +793,8 @@ static int hist_entry__dso_from_filter(struct hist_entry *he, int type,
if (type != HIST_FILTER__DSO)
return -1;
- return dso && (!he->branch_info || !he->branch_info->from.map ||
- he->branch_info->from.map->dso != dso);
+ return dso && (!he->branch_info || !he->branch_info->from.ms.map ||
+ he->branch_info->from.ms.map->dso != dso);
}
static int64_t
@@ -798,15 +803,15 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
if (!left->branch_info || !right->branch_info)
return cmp_null(left->branch_info, right->branch_info);
- return _sort__dso_cmp(left->branch_info->to.map,
- right->branch_info->to.map);
+ return _sort__dso_cmp(left->branch_info->to.ms.map,
+ right->branch_info->to.ms.map);
}
static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
if (he->branch_info)
- return _hist_entry__dso_snprintf(he->branch_info->to.map,
+ return _hist_entry__dso_snprintf(he->branch_info->to.ms.map,
bf, size, width);
else
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
@@ -820,8 +825,8 @@ static int hist_entry__dso_to_filter(struct hist_entry *he, int type,
if (type != HIST_FILTER__DSO)
return -1;
- return dso && (!he->branch_info || !he->branch_info->to.map ||
- he->branch_info->to.map->dso != dso);
+ return dso && (!he->branch_info || !he->branch_info->to.ms.map ||
+ he->branch_info->to.ms.map->dso != dso);
}
static int64_t
@@ -836,10 +841,10 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
from_l = &left->branch_info->from;
from_r = &right->branch_info->from;
- if (!from_l->sym && !from_r->sym)
+ if (!from_l->ms.sym && !from_r->ms.sym)
return _sort__addr_cmp(from_l->addr, from_r->addr);
- return _sort__sym_cmp(from_l->sym, from_r->sym);
+ return _sort__sym_cmp(from_l->ms.sym, from_r->ms.sym);
}
static int64_t
@@ -853,10 +858,10 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
to_l = &left->branch_info->to;
to_r = &right->branch_info->to;
- if (!to_l->sym && !to_r->sym)
+ if (!to_l->ms.sym && !to_r->ms.sym)
return _sort__addr_cmp(to_l->addr, to_r->addr);
- return _sort__sym_cmp(to_l->sym, to_r->sym);
+ return _sort__sym_cmp(to_l->ms.sym, to_r->ms.sym);
}
static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
@@ -865,8 +870,7 @@ static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
if (he->branch_info) {
struct addr_map_symbol *from = &he->branch_info->from;
- return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
- he->level, bf, size, width);
+ return _hist_entry__sym_snprintf(&from->ms, from->addr, he->level, bf, size, width);
}
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
@@ -878,8 +882,7 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
if (he->branch_info) {
struct addr_map_symbol *to = &he->branch_info->to;
- return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
- he->level, bf, size, width);
+ return _hist_entry__sym_snprintf(&to->ms, to->addr, he->level, bf, size, width);
}
return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
@@ -893,8 +896,8 @@ static int hist_entry__sym_from_filter(struct hist_entry *he, int type,
if (type != HIST_FILTER__SYMBOL)
return -1;
- return sym && !(he->branch_info && he->branch_info->from.sym &&
- strstr(he->branch_info->from.sym->name, sym));
+ return sym && !(he->branch_info && he->branch_info->from.ms.sym &&
+ strstr(he->branch_info->from.ms.sym->name, sym));
}
static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
@@ -905,8 +908,8 @@ static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
if (type != HIST_FILTER__SYMBOL)
return -1;
- return sym && !(he->branch_info && he->branch_info->to.sym &&
- strstr(he->branch_info->to.sym->name, sym));
+ return sym && !(he->branch_info && he->branch_info->to.ms.sym &&
+ strstr(he->branch_info->to.ms.sym->name, sym));
}
struct sort_entry sort_dso_from = {
@@ -1014,16 +1017,13 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
uint64_t addr = 0;
- struct map *map = NULL;
- struct symbol *sym = NULL;
+ struct map_symbol *ms = NULL;
if (he->mem_info) {
addr = he->mem_info->daddr.addr;
- map = he->mem_info->daddr.map;
- sym = he->mem_info->daddr.sym;
+ ms = &he->mem_info->daddr.ms;
}
- return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
- width);
+ return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width);
}
int64_t
@@ -1043,16 +1043,13 @@ static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
uint64_t addr = 0;
- struct map *map = NULL;
- struct symbol *sym = NULL;
+ struct map_symbol *ms = NULL;
if (he->mem_info) {
addr = he->mem_info->iaddr.addr;
- map = he->mem_info->iaddr.map;
- sym = he->mem_info->iaddr.sym;
+ ms = &he->mem_info->iaddr.ms;
}
- return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
- width);
+ return _hist_entry__sym_snprintf(ms, addr, he->level, bf, size, width);
}
static int64_t
@@ -1062,9 +1059,9 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
struct map *map_r = NULL;
if (left->mem_info)
- map_l = left->mem_info->daddr.map;
+ map_l = left->mem_info->daddr.ms.map;
if (right->mem_info)
- map_r = right->mem_info->daddr.map;
+ map_r = right->mem_info->daddr.ms.map;
return _sort__dso_cmp(map_l, map_r);
}
@@ -1075,7 +1072,7 @@ static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
struct map *map = NULL;
if (he->mem_info)
- map = he->mem_info->daddr.map;
+ map = he->mem_info->daddr.ms.map;
return _hist_entry__dso_snprintf(map, bf, size, width);
}
@@ -1197,6 +1194,7 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
{
u64 l, r;
struct map *l_map, *r_map;
+ int rc;
if (!left->mem_info) return -1;
if (!right->mem_info) return 1;
@@ -1205,8 +1203,8 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
if (left->cpumode > right->cpumode) return -1;
if (left->cpumode < right->cpumode) return 1;
- l_map = left->mem_info->daddr.map;
- r_map = right->mem_info->daddr.map;
+ l_map = left->mem_info->daddr.ms.map;
+ r_map = right->mem_info->daddr.ms.map;
/* if both are NULL, jump to sort on al_addr instead */
if (!l_map && !r_map)
@@ -1215,18 +1213,9 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
if (!l_map) return -1;
if (!r_map) return 1;
- if (l_map->maj > r_map->maj) return -1;
- if (l_map->maj < r_map->maj) return 1;
-
- if (l_map->min > r_map->min) return -1;
- if (l_map->min < r_map->min) return 1;
-
- if (l_map->ino > r_map->ino) return -1;
- if (l_map->ino < r_map->ino) return 1;
-
- if (l_map->ino_generation > r_map->ino_generation) return -1;
- if (l_map->ino_generation < r_map->ino_generation) return 1;
-
+ rc = dso__cmp_id(l_map->dso, r_map->dso);
+ if (rc)
+ return rc;
/*
* Addresses with no major/minor numbers are assumed to be
* anonymous in userspace. Sort those on pid then address.
@@ -1237,8 +1226,8 @@ sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
(!(l_map->flags & MAP_SHARED)) &&
- !l_map->maj && !l_map->min && !l_map->ino &&
- !l_map->ino_generation) {
+ !l_map->dso->id.maj && !l_map->dso->id.min &&
+ !l_map->dso->id.ino && !l_map->dso->id.ino_generation) {
/* userspace anonymous */
if (left->thread->pid_ > right->thread->pid_) return -1;
@@ -1261,27 +1250,26 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
{
uint64_t addr = 0;
- struct map *map = NULL;
- struct symbol *sym = NULL;
+ struct map_symbol *ms = NULL;
char level = he->level;
if (he->mem_info) {
+ struct map *map = he->mem_info->daddr.ms.map;
+
addr = cl_address(he->mem_info->daddr.al_addr);
- map = he->mem_info->daddr.map;
- sym = he->mem_info->daddr.sym;
+ ms = &he->mem_info->daddr.ms;
/* print [s] for shared data mmaps */
if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
map && !(map->prot & PROT_EXEC) &&
(map->flags & MAP_SHARED) &&
- (map->maj || map->min || map->ino ||
- map->ino_generation))
+ (map->dso->id.maj || map->dso->id.min ||
+ map->dso->id.ino || map->dso->id.ino_generation))
level = 's';
else if (!map)
level = 'X';
}
- return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
- width);
+ return _hist_entry__sym_snprintf(ms, addr, level, bf, size, width);
}
struct sort_entry sort_mispredict = {
@@ -1984,7 +1972,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
struct hpp_dynamic_entry {
struct perf_hpp_fmt hpp;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
unsigned dynamic_len;
bool raw_trace;
@@ -2218,7 +2206,7 @@ static void hde_free(struct perf_hpp_fmt *fmt)
}
static struct hpp_dynamic_entry *
-__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field,
+__alloc_dynamic_entry(struct evsel *evsel, struct tep_format_field *field,
int level)
{
struct hpp_dynamic_entry *hde;
@@ -2313,20 +2301,20 @@ static int parse_field_name(char *str, char **event, char **field, char **opt)
* 2. full event name (e.g. sched:sched_switch)
* 3. partial event name (should not contain ':')
*/
-static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
+static struct evsel *find_evsel(struct evlist *evlist, char *event_name)
{
- struct perf_evsel *evsel = NULL;
- struct perf_evsel *pos;
+ struct evsel *evsel = NULL;
+ struct evsel *pos;
bool full_name;
/* case 1 */
if (event_name[0] == '%') {
int nr = strtol(event_name+1, NULL, 0);
- if (nr > evlist->nr_entries)
+ if (nr > evlist->core.nr_entries)
return NULL;
- evsel = perf_evlist__first(evlist);
+ evsel = evlist__first(evlist);
while (--nr > 0)
evsel = perf_evsel__next(evsel);
@@ -2352,7 +2340,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
return evsel;
}
-static int __dynamic_dimension__add(struct perf_evsel *evsel,
+static int __dynamic_dimension__add(struct evsel *evsel,
struct tep_format_field *field,
bool raw_trace, int level)
{
@@ -2368,7 +2356,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
return 0;
}
-static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
+static int add_evsel_fields(struct evsel *evsel, bool raw_trace, int level)
{
int ret;
struct tep_format_field *field;
@@ -2384,14 +2372,14 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
return 0;
}
-static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
+static int add_all_dynamic_fields(struct evlist *evlist, bool raw_trace,
int level)
{
int ret;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
ret = add_evsel_fields(evsel, raw_trace, level);
@@ -2401,15 +2389,15 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
return 0;
}
-static int add_all_matching_fields(struct perf_evlist *evlist,
+static int add_all_matching_fields(struct evlist *evlist,
char *field_name, bool raw_trace, int level)
{
int ret = -ESRCH;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT)
continue;
field = tep_find_any_field(evsel->tp_format, field_name);
@@ -2423,11 +2411,11 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
return ret;
}
-static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
+static int add_dynamic_entry(struct evlist *evlist, const char *tok,
int level)
{
char *str, *event_name, *field_name, *opt_name;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
struct tep_format_field *field;
bool raw_trace = symbol_conf.raw_trace;
int ret = 0;
@@ -2470,7 +2458,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
goto out;
}
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
pr_debug("%s is not a tracepoint event\n", event_name);
ret = -EINVAL;
goto out;
@@ -2567,7 +2555,7 @@ int hpp_dimension__add_output(unsigned col)
}
int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
- struct perf_evlist *evlist,
+ struct evlist *evlist,
int level)
{
unsigned int i;
@@ -2663,7 +2651,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
}
static int setup_sort_list(struct perf_hpp_list *list, char *str,
- struct perf_evlist *evlist)
+ struct evlist *evlist)
{
char *tmp, *tok;
int ret = 0;
@@ -2709,7 +2697,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
return ret;
}
-static const char *get_default_sort_order(struct perf_evlist *evlist)
+static const char *get_default_sort_order(struct evlist *evlist)
{
const char *default_sort_orders[] = {
default_sort_order,
@@ -2720,7 +2708,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
default_tracepoint_sort_order,
};
bool use_trace = true;
- struct perf_evsel *evsel;
+ struct evsel *evsel;
BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
@@ -2728,7 +2716,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
goto out_no_evlist;
evlist__for_each_entry(evlist, evsel) {
- if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
+ if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
use_trace = false;
break;
}
@@ -2743,7 +2731,7 @@ out_no_evlist:
return default_sort_orders[sort__mode];
}
-static int setup_sort_order(struct perf_evlist *evlist)
+static int setup_sort_order(struct evlist *evlist)
{
char *new_sort_order;
@@ -2804,7 +2792,7 @@ static char *setup_overhead(char *keys)
return keys;
}
-static int __setup_sorting(struct perf_evlist *evlist)
+static int __setup_sorting(struct evlist *evlist)
{
char *str;
const char *sort_keys;
@@ -3057,7 +3045,7 @@ out:
return ret;
}
-int setup_sorting(struct perf_evlist *evlist)
+int setup_sorting(struct evlist *evlist)
{
int err;
OpenPOWER on IntegriCloud