aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt8
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-probe.c1
-rw-r--r--tools/perf/builtin-record.c37
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/util/build-id.c18
-rw-r--r--tools/perf/util/event.c42
-rw-r--r--tools/perf/util/hist.c160
-rw-r--r--tools/perf/util/hist.h30
-rw-r--r--tools/perf/util/map.c81
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/newt.c991
-rw-r--r--tools/perf/util/probe-event.c135
-rw-r--r--tools/perf/util/probe-event.h27
-rw-r--r--tools/perf/util/probe-finder.c34
-rw-r--r--tools/perf/util/probe-finder.h10
-rw-r--r--tools/perf/util/session.c48
-rw-r--r--tools/perf/util/sort.c17
-rw-r--r--tools/perf/util/sort.h18
-rw-r--r--tools/perf/util/symbol.c219
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/thread.c7
-rw-r--r--tools/perf/util/thread.h2
24 files changed, 1253 insertions, 654 deletions
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 5d1a9500277..c1057701a7d 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -12,9 +12,9 @@ SYNOPSIS
DESCRIPTION
-----------
-This command manages the build-id cache. It can add and remove files to the
-cache. In the future it should as well purge older entries, set upper limits
-for the space used by the cache, etc.
+This command manages the build-id cache. It can add and remove files to/from
+the cache. In the future it should as well purge older entries, set upper
+limits for the space used by the cache, etc.
OPTIONS
-------
@@ -23,7 +23,7 @@ OPTIONS
Add specified file to the cache.
-r::
--remove=::
- Remove specified file to the cache.
+ Remove specified file from the cache.
-v::
--verbose::
Be more verbose.
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 99890728409..44a47e13bd6 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -43,10 +43,8 @@ static int __cmd_buildid_list(void)
if (session == NULL)
return -1;
- if (with_hits) {
- symbol_conf.full_paths = true;
+ if (with_hits)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);
- }
perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 39e6627ebb9..fca1d440291 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -180,8 +180,6 @@ static const struct option options[] = {
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
"load module symbols - WARNING: use only with -k and LIVE kernel"),
- OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths,
- "Don't shorten the pathnames taking into account the cwd"),
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
"only consider symbols in these dsos"),
OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 54551867e7e..199d5e19554 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -267,4 +267,3 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
}
return 0;
}
-
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b93879677cc..ff77b805de7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -439,6 +439,8 @@ static void atexit_header(void)
process_buildids();
perf_header__write(&session->header, output, true);
+ perf_session__delete(session);
+ symbol__exit();
}
}
@@ -558,12 +560,15 @@ static int __cmd_record(int argc, const char **argv)
if (!file_new) {
err = perf_header__read(session, output);
if (err < 0)
- return err;
+ goto out_delete_session;
}
if (have_tracepoints(attrs, nr_counters))
perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
+ /*
+ * perf_session__delete(session) will be called at atexit_header()
+ */
atexit(atexit_header);
if (forks) {
@@ -768,6 +773,10 @@ static int __cmd_record(int argc, const char **argv)
bytes_written / 24);
return 0;
+
+out_delete_session:
+ perf_session__delete(session);
+ return err;
}
static const char * const record_usage[] = {
@@ -824,7 +833,7 @@ static const struct option options[] = {
int cmd_record(int argc, const char **argv, const char *prefix __used)
{
- int i,j;
+ int i, j, err = -ENOMEM;
argc = parse_options(argc, argv, options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
@@ -863,7 +872,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
} else {
all_tids=malloc(sizeof(pid_t));
if (!all_tids)
- return -ENOMEM;
+ goto out_symbol_exit;
all_tids[0] = target_tid;
thread_num = 1;
@@ -873,13 +882,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
for (j = 0; j < MAX_COUNTERS; j++) {
fd[i][j] = malloc(sizeof(int)*thread_num);
if (!fd[i][j])
- return -ENOMEM;
+ goto out_free_fd;
}
}
event_array = malloc(
sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
if (!event_array)
- return -ENOMEM;
+ goto out_free_fd;
if (user_interval != ULLONG_MAX)
default_interval = user_interval;
@@ -895,8 +904,22 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
default_interval = freq;
} else {
fprintf(stderr, "frequency and count are zero, aborting\n");
- exit(EXIT_FAILURE);
+ err = -EINVAL;
+ goto out_free_event_array;
}
- return __cmd_record(argc, argv);
+ err = __cmd_record(argc, argv);
+
+out_free_event_array:
+ free(event_array);
+out_free_fd:
+ for (i = 0; i < MAX_NR_CPUS; i++) {
+ for (j = 0; j < MAX_COUNTERS; j++)
+ free(fd[i][j]);
+ }
+ free(all_tids);
+ all_tids = NULL;
+out_symbol_exit:
+ symbol__exit();
+ return err;
}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ce42bbaa252..2f4b92925b2 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -441,8 +441,6 @@ static const struct option options[] = {
"pretty printing style key: normal raw"),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
"sort by key(s): pid, comm, dso, symbol, parent"),
- OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths,
- "Don't shorten the pathnames taking into account the cwd"),
OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
"Show sample percentage for different cpu modes"),
OPT_STRING('p', "parent", &parent_pattern, "regex",
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5c26e2d314a..e437edb7241 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -12,6 +12,7 @@
#include "event.h"
#include "symbol.h"
#include <linux/kernel.h>
+#include "debug.h"
static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
{
@@ -34,10 +35,27 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
return 0;
}
+static int event__exit_del_thread(event_t *self, struct perf_session *session)
+{
+ struct thread *thread = perf_session__findnew(session, self->fork.tid);
+
+ dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
+ self->fork.ppid, self->fork.ptid);
+
+ if (thread) {
+ rb_erase(&thread->rb_node, &session->threads);
+ session->last_match = NULL;
+ thread__delete(thread);
+ }
+
+ return 0;
+}
+
struct perf_event_ops build_id__mark_dso_hit_ops = {
.sample = build_id__mark_dso_hit,
.mmap = event__process_mmap,
.fork = event__process_task,
+ .exit = event__exit_del_thread,
};
char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index d7f21d71eb6..6b0db557792 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -340,30 +340,29 @@ int event__synthesize_kernel_mmap(event__handler_t process,
return process(&ev, session);
}
-static void thread__comm_adjust(struct thread *self)
+static void thread__comm_adjust(struct thread *self, struct hists *hists)
{
char *comm = self->comm;
if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
(!symbol_conf.comm_list ||
strlist__has_entry(symbol_conf.comm_list, comm))) {
- unsigned int slen = strlen(comm);
+ u16 slen = strlen(comm);
- if (slen > comms__col_width) {
- comms__col_width = slen;
- threads__col_width = slen + 6;
- }
+ if (hists__new_col_len(hists, HISTC_COMM, slen))
+ hists__set_col_len(hists, HISTC_THREAD, slen + 6);
}
}
-static int thread__set_comm_adjust(struct thread *self, const char *comm)
+static int thread__set_comm_adjust(struct thread *self, const char *comm,
+ struct hists *hists)
{
int ret = thread__set_comm(self, comm);
if (ret)
return ret;
- thread__comm_adjust(self);
+ thread__comm_adjust(self, hists);
return 0;
}
@@ -374,7 +373,8 @@ int event__process_comm(event_t *self, struct perf_session *session)
dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
- if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) {
+ if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm,
+ &session->hists)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
@@ -456,6 +456,7 @@ static int event__process_kernel_mmap(event_t *self,
goto out_problem;
map->dso->short_name = name;
+ map->dso->sname_alloc = 1;
map->end = map->start + self->mmap.len;
} else if (is_kernel_mmap) {
const char *symbol_name = (self->mmap.filename +
@@ -514,12 +515,13 @@ int event__process_mmap(event_t *self, struct perf_session *session)
if (machine == NULL)
goto out_problem;
thread = perf_session__findnew(session, self->mmap.pid);
+ if (thread == NULL)
+ goto out_problem;
map = map__new(&machine->user_dsos, self->mmap.start,
self->mmap.len, self->mmap.pgoff,
self->mmap.pid, self->mmap.filename,
- MAP__FUNCTION, session->cwd, session->cwdlen);
-
- if (thread == NULL || map == NULL)
+ MAP__FUNCTION);
+ if (map == NULL)
goto out_problem;
thread__insert_map(thread, map);
@@ -641,16 +643,13 @@ void thread__find_addr_location(struct thread *self,
al->sym = NULL;
}
-static void dso__calc_col_width(struct dso *self)
+static void dso__calc_col_width(struct dso *self, struct hists *hists)
{
if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
(!symbol_conf.dso_list ||
strlist__has_entry(symbol_conf.dso_list, self->name))) {
- u16 slen = self->short_name_len;
- if (verbose)
- slen = self->long_name_len;
- if (dsos__col_width < slen)
- dsos__col_width = slen;
+ u16 slen = dso__name_len(self);
+ hists__new_col_len(hists, HISTC_DSO, slen);
}
self->slen_calculated = 1;
@@ -729,16 +728,17 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
* sampled.
*/
if (!sort_dso.elide && !al->map->dso->slen_calculated)
- dso__calc_col_width(al->map->dso);
+ dso__calc_col_width(al->map->dso, &session->hists);
al->sym = map__find_symbol(al->map, al->addr, filter);
} else {
const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
- if (dsos__col_width < unresolved_col_width &&
+ if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width &&
!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
!symbol_conf.dso_list)
- dsos__col_width = unresolved_col_width;
+ hists__set_col_len(&session->hists, HISTC_DSO,
+ unresolved_col_width);
}
if (symbol_conf.sym_list && al->sym &&
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 7b5848ce150..d0f07f7bdf1 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -5,11 +5,61 @@
#include "sort.h"
#include <math.h>
+enum hist_filter {
+ HIST_FILTER__DSO,
+ HIST_FILTER__THREAD,
+ HIST_FILTER__PARENT,
+};
+
struct callchain_param callchain_param = {
.mode = CHAIN_GRAPH_REL,
.min_percent = 0.5
};
+u16 hists__col_len(struct hists *self, enum hist_column col)
+{
+ return self->col_len[col];
+}
+
+void hists__set_col_len(struct hists *self, enum hist_column col, u16 len)
+{
+ self->col_len[col] = len;
+}
+
+bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len)
+{
+ if (len > hists__col_len(self, col)) {
+ hists__set_col_len(self, col, len);
+ return true;
+ }
+ return false;
+}
+
+static void hists__reset_col_len(struct hists *self)
+{
+ enum hist_column col;
+
+ for (col = 0; col < HISTC_NR_COLS; ++col)
+ hists__set_col_len(self, col, 0);
+}
+
+static void hists__calc_col_len(struct hists *self, struct hist_entry *h)
+{
+ u16 len;
+
+ if (h->ms.sym)
+ hists__new_col_len(self, HISTC_SYMBOL, h->ms.sym->namelen);
+
+ len = thread__comm_len(h->thread);
+ if (hists__new_col_len(self, HISTC_COMM, len))
+ hists__set_col_len(self, HISTC_THREAD, len + 6);
+
+ if (h->ms.map) {
+ len = dso__name_len(h->ms.map->dso);
+ hists__new_col_len(self, HISTC_DSO, len);
+ }
+}
+
static void hist_entry__add_cpumode_period(struct hist_entry *self,
unsigned int cpumode, u64 period)
{
@@ -50,11 +100,19 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
return self;
}
-static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry)
+static void hists__inc_nr_entries(struct hists *self, struct hist_entry *h)
{
- if (entry->ms.sym && self->max_sym_namelen < entry->ms.sym->namelen)
- self->max_sym_namelen = entry->ms.sym->namelen;
- ++self->nr_entries;
+ if (!h->filtered) {
+ hists__calc_col_len(self, h);
+ ++self->nr_entries;
+ }
+}
+
+static u8 symbol__parent_filter(const struct symbol *parent)
+{
+ if (symbol_conf.exclude_other && parent == NULL)
+ return 1 << HIST_FILTER__PARENT;
+ return 0;
}
struct hist_entry *__hists__add_entry(struct hists *self,
@@ -75,6 +133,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
.level = al->level,
.period = period,
.parent = sym_parent,
+ .filtered = symbol__parent_filter(sym_parent),
};
int cmp;
@@ -192,7 +251,7 @@ void hists__collapse_resort(struct hists *self)
tmp = RB_ROOT;
next = rb_first(&self->entries);
self->nr_entries = 0;
- self->max_sym_namelen = 0;
+ hists__reset_col_len(self);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
@@ -249,7 +308,7 @@ void hists__output_resort(struct hists *self)
next = rb_first(&self->entries);
self->nr_entries = 0;
- self->max_sym_namelen = 0;
+ hists__reset_col_len(self);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
@@ -516,8 +575,9 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
}
int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
- struct hists *pair_hists, bool show_displacement,
- long displacement, bool color, u64 session_total)
+ struct hists *hists, struct hists *pair_hists,
+ bool show_displacement, long displacement,
+ bool color, u64 session_total)
{
struct sort_entry *se;
u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
@@ -621,24 +681,25 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
ret += se->se_snprintf(self, s + ret, size - ret,
- se->se_width ? *se->se_width : 0);
+ hists__col_len(hists, se->se_width_idx));
}
return ret;
}
-int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists,
- bool show_displacement, long displacement, FILE *fp,
- u64 session_total)
+int hist_entry__fprintf(struct hist_entry *self, struct hists *hists,
+ struct hists *pair_hists, bool show_displacement,
+ long displacement, FILE *fp, u64 session_total)
{
char bf[512];
- hist_entry__snprintf(self, bf, sizeof(bf), pair_hists,
+ hist_entry__snprintf(self, bf, sizeof(bf), hists, pair_hists,
show_displacement, displacement,
true, session_total);
return fprintf(fp, "%s\n", bf);
}
-static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
+static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
+ struct hists *hists, FILE *fp,
u64 session_total)
{
int left_margin = 0;
@@ -646,7 +707,7 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
if (sort__first_dimension == SORT_COMM) {
struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
typeof(*se), list);
- left_margin = se->se_width ? *se->se_width : 0;
+ left_margin = hists__col_len(hists, se->se_width_idx);
left_margin -= thread__comm_len(self->thread);
}
@@ -717,17 +778,17 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
continue;
}
width = strlen(se->se_header);
- if (se->se_width) {
- if (symbol_conf.col_width_list_str) {
- if (col_width) {
- *se->se_width = atoi(col_width);
- col_width = strchr(col_width, ',');
- if (col_width)
- ++col_width;
- }
+ if (symbol_conf.col_width_list_str) {
+ if (col_width) {
+ hists__set_col_len(self, se->se_width_idx,
+ atoi(col_width));
+ col_width = strchr(col_width, ',');
+ if (col_width)
+ ++col_width;
}
- width = *se->se_width = max(*se->se_width, width);
}
+ if (!hists__new_col_len(self, se->se_width_idx, width))
+ width = hists__col_len(self, se->se_width_idx);
fprintf(fp, " %*s", width, se->se_header);
}
fprintf(fp, "\n");
@@ -750,9 +811,8 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
continue;
fprintf(fp, " ");
- if (se->se_width)
- width = *se->se_width;
- else
+ width = hists__col_len(self, se->se_width_idx);
+ if (width == 0)
width = strlen(se->se_header);
for (i = 0; i < width; i++)
fprintf(fp, ".");
@@ -772,12 +832,12 @@ print_entries:
displacement = 0;
++position;
}
- ret += hist_entry__fprintf(h, pair, show_displacement,
+ ret += hist_entry__fprintf(h, self, pair, show_displacement,
displacement, fp, self->stats.total_period);
if (symbol_conf.use_callchain)
- ret += hist_entry__fprintf_callchain(h, fp, self->stats.total_period);
-
+ ret += hist_entry__fprintf_callchain(h, self, fp,
+ self->stats.total_period);
if (h->ms.map == NULL && verbose > 1) {
__map_groups__fprintf_maps(&h->thread->mg,
MAP__FUNCTION, verbose, fp);
@@ -790,10 +850,32 @@ print_entries:
return ret;
}
-enum hist_filter {
- HIST_FILTER__DSO,
- HIST_FILTER__THREAD,
-};
+/*
+ * See hists__fprintf to match the column widths
+ */
+unsigned int hists__sort_list_width(struct hists *self)
+{
+ struct sort_entry *se;
+ int ret = 9; /* total % */
+
+ if (symbol_conf.show_cpu_utilization) {
+ ret += 7; /* count_sys % */
+ ret += 6; /* count_us % */
+ if (perf_guest) {
+ ret += 13; /* count_guest_sys % */
+ ret += 12; /* count_guest_us % */
+ }
+ }
+
+ if (symbol_conf.show_nr_samples)
+ ret += 11;
+
+ list_for_each_entry(se, &hist_entry__sort_list, list)
+ if (!se->elide)
+ ret += 2 + hists__col_len(self, se->se_width_idx);
+
+ return ret;
+}
static void hists__remove_entry_filter(struct hists *self, struct hist_entry *h,
enum hist_filter filter)
@@ -803,11 +885,13 @@ static void hists__remove_entry_filter(struct hists *self, struct hist_entry *h,
return;
++self->nr_entries;
+ if (h->ms.unfolded)
+ self->nr_entries += h->nr_rows;
+ h->row_offset = 0;
self->stats.total_period += h->period;
self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
- if (h->ms.sym && self->max_sym_namelen < h->ms.sym->namelen)
- self->max_sym_namelen = h->ms.sym->namelen;
+ hists__calc_col_len(self, h);
}
void hists__filter_by_dso(struct hists *self, const struct dso *dso)
@@ -816,7 +900,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
self->nr_entries = self->stats.total_period = 0;
self->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
- self->max_sym_namelen = 0;
+ hists__reset_col_len(self);
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
@@ -839,7 +923,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
self->nr_entries = self->stats.total_period = 0;
self->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
- self->max_sym_namelen = 0;
+ hists__reset_col_len(self);
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 83fa33a7b38..65a48db46a2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -56,6 +56,16 @@ struct events_stats {
u32 nr_unknown_events;
};
+enum hist_column {
+ HISTC_SYMBOL,
+ HISTC_DSO,
+ HISTC_THREAD,
+ HISTC_COMM,
+ HISTC_PARENT,
+ HISTC_CPU,
+ HISTC_NR_COLS, /* Last entry */
+};
+
struct hists {
struct rb_node rb_node;
struct rb_root entries;
@@ -64,7 +74,7 @@ struct hists {
u64 config;
u64 event_stream;
u32 type;
- u32 max_sym_namelen;
+ u16 col_len[HISTC_NR_COLS];
};
struct hist_entry *__hists__add_entry(struct hists *self,
@@ -72,12 +82,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
struct symbol *parent, u64 period);
extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
-int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists,
- bool show_displacement, long displacement, FILE *fp,
- u64 total);
+int hist_entry__fprintf(struct hist_entry *self, struct hists *hists,
+ struct hists *pair_hists, bool show_displacement,
+ long displacement, FILE *fp, u64 total);
int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
- struct hists *pair_hists, bool show_displacement,
- long displacement, bool color, u64 total);
+ struct hists *hists, struct hists *pair_hists,
+ bool show_displacement, long displacement,
+ bool color, u64 total);
void hist_entry__free(struct hist_entry *);
void hists__output_resort(struct hists *self);
@@ -95,6 +106,10 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head);
void hists__filter_by_dso(struct hists *self, const struct dso *dso);
void hists__filter_by_thread(struct hists *self, const struct thread *thread);
+u16 hists__col_len(struct hists *self, enum hist_column col);
+void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
+bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
+
#ifdef NO_NEWT_SUPPORT
static inline int hists__browse(struct hists *self __used,
const char *helpline __used,
@@ -126,4 +141,7 @@ int hist_entry__tui_annotate(struct hist_entry *self);
int hists__tui_browse_tree(struct rb_root *self, const char *help);
#endif
+
+unsigned int hists__sort_list_width(struct hists *self);
+
#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index e672f2fef65..15d6a6dd50c 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -17,16 +17,6 @@ static inline int is_anon_memory(const char *filename)
return strcmp(filename, "//anon") == 0;
}
-static int strcommon(const char *pathname, char *cwd, int cwdlen)
-{
- int n = 0;
-
- while (n < cwdlen && pathname[n] == cwd[n])
- ++n;
-
- return n;
-}
-
void map__init(struct map *self, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso)
{
@@ -43,7 +33,7 @@ void map__init(struct map *self, enum map_type type,
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
u64 pgoff, u32 pid, char *filename,
- enum map_type type, char *cwd, int cwdlen)
+ enum map_type type)
{
struct map *self = malloc(sizeof(*self));
@@ -52,16 +42,6 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
struct dso *dso;
int anon;
- if (cwd) {
- int n = strcommon(filename, cwd, cwdlen);
-
- if (n == cwdlen) {
- snprintf(newfilename, sizeof(newfilename),
- ".%s", filename + n);
- filename = newfilename;
- }
- }
-
anon = is_anon_memory(filename);
if (anon) {
@@ -248,6 +228,39 @@ void map_groups__init(struct map_groups *self)
self->machine = NULL;
}
+static void maps__delete(struct rb_root *self)
+{
+ struct rb_node *next = rb_first(self);
+
+ while (next) {
+ struct map *pos = rb_entry(next, struct map, rb_node);
+
+ next = rb_next(&pos->rb_node);
+ rb_erase(&pos->rb_node, self);
+ map__delete(pos);
+ }
+}
+
+static void maps__delete_removed(struct list_head *self)
+{
+ struct map *pos, *n;
+
+ list_for_each_entry_safe(pos, n, self, node) {
+ list_del(&pos->node);
+ map__delete(pos);
+ }
+}
+
+void map_groups__exit(struct map_groups *self)
+{
+ int i;
+
+ for (i = 0; i < MAP__NR_TYPES; ++i) {
+ maps__delete(&self->maps[i]);
+ maps__delete_removed(&self->removed_maps[i]);
+ }
+}
+
void map_groups__flush(struct map_groups *self)
{
int type;
@@ -526,6 +539,32 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
return self->root_dir == NULL ? -ENOMEM : 0;
}
+static void dsos__delete(struct list_head *self)
+{
+ struct dso *pos, *n;
+
+ list_for_each_entry_safe(pos, n, self, node) {
+ list_del(&pos->node);
+ dso__delete(pos);
+ }
+}
+
+void machine__exit(struct machine *self)
+{
+ struct kmap *kmap = map__kmap(self->vmlinux_maps[MAP__FUNCTION]);
+
+ if (kmap->ref_reloc_sym) {
+ free((char *)kmap->ref_reloc_sym->name);
+ free(kmap->ref_reloc_sym);
+ }
+
+ map_groups__exit(&self->kmaps);
+ dsos__delete(&self->user_dsos);
+ dsos__delete(&self->kernel_dsos);
+ free(self->root_dir);
+ self->root_dir = NULL;
+}
+
struct machine *machines__add(struct rb_root *self, pid_t pid,
const char *root_dir)
{
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f3913451282..0e0984e86fc 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -106,7 +106,7 @@ void map__init(struct map *self, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso);
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
u64 pgoff, u32 pid, char *filename,
- enum map_type type, char *cwd, int cwdlen);
+ enum map_type type);
void map__delete(struct map *self);
struct map *map__clone(struct map *self);
int map__overlap(struct map *l, struct map *r);
@@ -127,6 +127,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *self,
void maps__insert(struct rb_root *maps, struct map *map);
struct map *maps__find(struct rb_root *maps, u64 addr);
void map_groups__init(struct map_groups *self);
+void map_groups__exit(struct map_groups *self);
int map_groups__clone(struct map_groups *self,
struct map_groups *parent, enum map_type type);
size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp);
@@ -142,6 +143,7 @@ struct machine *machines__find(struct rb_root *self, pid_t pid);
struct machine *machines__findnew(struct rb_root *self, pid_t pid);
char *machine__mmap_name(struct machine *self, char *bf, size_t size);
int machine__init(struct machine *self, const char *root_dir, pid_t pid);
+void machine__exit(struct machine *self);
/*
* Default guest kernel is defined by parameter --guestkallsyms
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 7979003adea..91de99b5844 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -11,6 +11,7 @@
#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
#endif
#include <slang.h>
+#include <signal.h>
#include <stdlib.h>
#include <newt.h>
#include <sys/ttydefaults.h>
@@ -342,15 +343,17 @@ static void ui_browser__reset_index(struct ui_browser *self)
static int ui_browser__show(struct ui_browser