aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-07 12:38:11 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-07 12:38:11 -0800
commit54a0f91301950af3d6ae2ff2bf710c9c68a9bfea (patch)
treeffcdf0b916f9c5f805cab347e53b60be17c9aead /tools
parent94956eed14b4b16d401c8ad36d68df0608f968cb (diff)
parentf9e3d4b1a9c86217655997d3ef109b1eaae967bc (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf top: Fix live annotation in the --stdio interface perf top tui: Don't recalc column widths considering just the first page perf report: Add progress bar when processing time ordered events perf hists browser: Warn about lost events perf tools: Fix a typo of command name as trace-cmd perf hists: Fix recalculation of total_period when sorting entries perf header: Fix build on old systems perf ui browser: Handle K_RESIZE in dialog windows perf ui browser: No need to switch char sets that often perf hists browser: Use K_TIMER perf ui: Rename ui__warning_paranoid to ui__error_paranoid perf ui: Reimplement the popup windows using libslang perf ui: Reimplement ui__popup_menu using ui__browser perf ui: Reimplement ui_helpline using libslang perf ui: Improve handling sigwinch a bit perf ui progress: Reimplement using slang perf evlist: Fix grouping of multiple events
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-record.c13
-rw-r--r--tools/perf/builtin-stat.c20
-rw-r--r--tools/perf/builtin-test.c6
-rw-r--r--tools/perf/builtin-top.c54
-rw-r--r--tools/perf/util/annotate.c9
-rw-r--r--tools/perf/util/debug.c7
-rw-r--r--tools/perf/util/debug.h17
-rw-r--r--tools/perf/util/evlist.c30
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c43
-rw-r--r--tools/perf/util/evsel.h10
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c3
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/python.c31
-rw-r--r--tools/perf/util/session.c46
-rw-r--r--tools/perf/util/session.h1
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/trace-event-info.c2
-rw-r--r--tools/perf/util/ui/browser.c151
-rw-r--r--tools/perf/util/ui/browser.h9
-rw-r--r--tools/perf/util/ui/browsers/annotate.c14
-rw-r--r--tools/perf/util/ui/browsers/hists.c74
-rw-r--r--tools/perf/util/ui/helpline.c16
-rw-r--r--tools/perf/util/ui/helpline.h2
-rw-r--r--tools/perf/util/ui/progress.c65
-rw-r--r--tools/perf/util/ui/progress.h7
-rw-r--r--tools/perf/util/ui/setup.c83
-rw-r--r--tools/perf/util/ui/ui.h3
-rw-r--r--tools/perf/util/ui/util.c182
-rw-r--r--tools/perf/util/ui/util.h8
31 files changed, 624 insertions, 288 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f82480fa7f2..6ab58cc99d5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -262,13 +262,16 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
static void open_counters(struct perf_evlist *evlist)
{
- struct perf_evsel *pos;
+ struct perf_evsel *pos, *first;
if (evlist->cpus->map[0] < 0)
no_inherit = true;
+ first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
+ struct xyarray *group_fd = NULL;
/*
* Check if parse_single_tracepoint_event has already asked for
* PERF_SAMPLE_TIME.
@@ -283,15 +286,19 @@ static void open_counters(struct perf_evlist *evlist)
*/
bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
+ if (group && pos != first)
+ group_fd = first->fd;
+
config_attr(pos, evlist);
retry_sample_id:
attr->sample_id_all = sample_id_all_avail ? 1 : 0;
try_again:
- if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
+ if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
+ group_fd) < 0) {
int err = errno;
if (err == EPERM || err == EACCES) {
- ui__warning_paranoid();
+ ui__error_paranoid();
exit(EXIT_FAILURE);
} else if (err == ENODEV && cpu_list) {
die("No such device - did you specify"
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 7ce65f52415..7d98676808d 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -278,9 +278,14 @@ struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
struct stats walltime_nsecs_stats;
-static int create_perf_stat_counter(struct perf_evsel *evsel)
+static int create_perf_stat_counter(struct perf_evsel *evsel,
+ struct perf_evsel *first)
{
struct perf_event_attr *attr = &evsel->attr;
+ struct xyarray *group_fd = NULL;
+
+ if (group && evsel != first)
+ group_fd = first->fd;
if (scale)
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
@@ -289,14 +294,15 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
attr->inherit = !no_inherit;
if (system_wide)
- return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, group);
-
+ return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
+ group, group_fd);
if (target_pid == -1 && target_tid == -1) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
- return perf_evsel__open_per_thread(evsel, evsel_list->threads, group);
+ return perf_evsel__open_per_thread(evsel, evsel_list->threads,
+ group, group_fd);
}
/*
@@ -396,7 +402,7 @@ static int read_counter(struct perf_evsel *counter)
static int run_perf_stat(int argc __used, const char **argv)
{
unsigned long long t0, t1;
- struct perf_evsel *counter;
+ struct perf_evsel *counter, *first;
int status = 0;
int child_ready_pipe[2], go_pipe[2];
const bool forks = (argc > 0);
@@ -453,8 +459,10 @@ static int run_perf_stat(int argc __used, const char **argv)
close(child_ready_pipe[0]);
}
+ first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
+
list_for_each_entry(counter, &evsel_list->entries, node) {
- if (create_perf_stat_counter(counter) < 0) {
+ if (create_perf_stat_counter(counter, first) < 0) {
if (errno == EINVAL || errno == ENOSYS || errno == ENOENT) {
if (verbose)
ui__warning("%s event is not supported by the kernel.\n",
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index efe696f936e..831d1baeac3 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -291,7 +291,7 @@ static int test__open_syscall_event(void)
goto out_thread_map_delete;
}
- if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
+ if (perf_evsel__open_per_thread(evsel, threads, false, NULL) < 0) {
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno));
@@ -366,7 +366,7 @@ static int test__open_syscall_event_on_all_cpus(void)
goto out_thread_map_delete;
}
- if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
+ if (perf_evsel__open(evsel, cpus, threads, false, NULL) < 0) {
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno));
@@ -531,7 +531,7 @@ static int test__basic_mmap(void)
perf_evlist__add(evlist, evsels[i]);
- if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
+ if (perf_evsel__open(evsels[i], cpus, threads, false, NULL) < 0) {
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno));
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 7a871714d44..c9cdedb5813 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -89,6 +89,7 @@ static bool vmlinux_warned;
static bool inherit = false;
static int realtime_prio = 0;
static bool group = false;
+static bool sample_id_all_avail = true;
static unsigned int mmap_pages = 128;
static bool dump_symtab = false;
@@ -199,7 +200,8 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
struct symbol *sym;
if (he == NULL || he->ms.sym == NULL ||
- (he != top.sym_filter_entry && use_browser != 1))
+ ((top.sym_filter_entry == NULL ||
+ top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
return;
sym = he->ms.sym;
@@ -289,11 +291,13 @@ static void print_sym_table(void)
printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
- if (top.total_lost_warned != top.session->hists.stats.total_lost) {
- top.total_lost_warned = top.session->hists.stats.total_lost;
- color_fprintf(stdout, PERF_COLOR_RED, "WARNING:");
- printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n",
- top.total_lost_warned);
+ if (top.sym_evsel->hists.stats.nr_lost_warned !=
+ top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
+ top.sym_evsel->hists.stats.nr_lost_warned =
+ top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
+ color_fprintf(stdout, PERF_COLOR_RED,
+ "WARNING: LOST %d chunks, Check IO/CPU overload",
+ top.sym_evsel->hists.stats.nr_lost_warned);
++printed;
}
@@ -561,7 +565,6 @@ static void perf_top__sort_new_samples(void *arg)
hists__decay_entries_threaded(&t->sym_evsel->hists,
top.hide_user_symbols,
top.hide_kernel_symbols);
- hists__output_recalc_col_len(&t->sym_evsel->hists, winsize.ws_row - 3);
}
static void *display_thread_tui(void *arg __used)
@@ -671,6 +674,7 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
}
static void perf_event__process_sample(const union perf_event *event,
+ struct perf_evsel *evsel,
struct perf_sample *sample,
struct perf_session *session)
{
@@ -770,12 +774,8 @@ static void perf_event__process_sample(const union perf_event *event,
}
if (al.sym == NULL || !al.sym->ignore) {
- struct perf_evsel *evsel;
struct hist_entry *he;
- evsel = perf_evlist__id2evsel(top.evlist, sample->id);
- assert(evsel != NULL);
-
if ((sort__has_parent || symbol_conf.use_callchain) &&
sample->callchain) {
err = perf_session__resolve_callchain(session, al.thread,
@@ -807,6 +807,7 @@ static void perf_event__process_sample(const union perf_event *event,
static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
{
struct perf_sample sample;
+ struct perf_evsel *evsel;
union perf_event *event;
int ret;
@@ -817,10 +818,16 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
continue;
}
+ evsel = perf_evlist__id2evsel(self->evlist, sample.id);
+ assert(evsel != NULL);
+
if (event->header.type == PERF_RECORD_SAMPLE)
- perf_event__process_sample(event, &sample, self);
- else
+ perf_event__process_sample(event, evsel, &sample, self);
+ else if (event->header.type < PERF_RECORD_MAX) {
+ hists__inc_nr_events(&evsel->hists, event->header.type);
perf_event__process(event, &sample, self);
+ } else
+ ++self->hists.stats.nr_unknown_events;
}
}
@@ -834,10 +841,16 @@ static void perf_session__mmap_read(struct perf_session *self)
static void start_counters(struct perf_evlist *evlist)
{
- struct perf_evsel *counter;
+ struct perf_evsel *counter, *first;
+
+ first = list_entry(evlist->entries.next, struct perf_evsel, node);
list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;
+ struct xyarray *group_fd = NULL;
+
+ if (group && counter != first)
+ group_fd = first->fd;
attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
@@ -858,14 +871,23 @@ static void start_counters(struct perf_evlist *evlist)
attr->mmap = 1;
attr->comm = 1;
attr->inherit = inherit;
+retry_sample_id:
+ attr->sample_id_all = sample_id_all_avail ? 1 : 0;
try_again:
if (perf_evsel__open(counter, top.evlist->cpus,
- top.evlist->threads, group) < 0) {
+ top.evlist->threads, group,
+ group_fd) < 0) {
int err = errno;
if (err == EPERM || err == EACCES) {
- ui__warning_paranoid();
+ ui__error_paranoid();
goto out_err;
+ } else if (err == EINVAL && sample_id_all_avail) {
+ /*
+ * Old kernel, no attr->sample_id_type_all field
+ */
+ sample_id_all_avail = false;
+ goto retry_sample_id;
}
/*
* If it's cycles then fall back to hrtimer
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index bc8f4773d4d..119e996035c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -310,9 +310,12 @@ fallback:
}
err = -ENOENT;
dso->annotate_warned = 1;
- pr_err("Can't annotate %s: No vmlinux file%s was found in the "
- "path.\nPlease use 'perf buildid-cache -av vmlinux' or "
- "--vmlinux vmlinux.\n",
+ pr_err("Can't annotate %s:\n\n"
+ "No vmlinux file%s\nwas found in the path.\n\n"
+ "Please use:\n\n"
+ " perf buildid-cache -av vmlinux\n\n"
+ "or:\n\n"
+ " --vmlinux vmlinux",
sym->name, build_id_msg ?: "");
goto out_free_filename;
}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 155749d7435..26817daa296 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -47,19 +47,20 @@ int dump_printf(const char *fmt, ...)
}
#ifdef NO_NEWT_SUPPORT
-void ui__warning(const char *format, ...)
+int ui__warning(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
+ return 0;
}
#endif
-void ui__warning_paranoid(void)
+int ui__error_paranoid(void)
{
- ui__warning("Permission error - are you root?\n"
+ return ui__error("Permission error - are you root?\n"
"Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
" -1 - Not paranoid at all\n"
" 0 - Disallow raw tracepoint access for unpriv\n"
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index fd53db47e3d..f2ce88d04f5 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -19,23 +19,18 @@ static inline int ui_helpline__show_help(const char *format __used, va_list ap _
return 0;
}
-static inline struct ui_progress *ui_progress__new(const char *title __used,
- u64 total __used)
-{
- return (struct ui_progress *)1;
-}
-
-static inline void ui_progress__update(struct ui_progress *self __used,
- u64 curr __used) {}
+static inline void ui_progress__update(u64 curr __used, u64 total __used,
+ const char *title __used) {}
-static inline void ui_progress__delete(struct ui_progress *self __used) {}
+#define ui__error(format, arg...) ui__warning(format, ##arg)
#else
extern char ui_helpline__last_msg[];
int ui_helpline__show_help(const char *format, va_list ap);
#include "ui/progress.h"
+int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
#endif
-void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
-void ui__warning_paranoid(void);
+int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
+int ui__error_paranoid(void);
#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2f6bc89027d..fbb4b4ab9cc 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -539,3 +539,33 @@ void perf_evlist__set_selected(struct perf_evlist *evlist,
{
evlist->selected = evsel;
}
+
+int perf_evlist__open(struct perf_evlist *evlist, bool group)
+{
+ struct perf_evsel *evsel, *first;
+ int err, ncpus, nthreads;
+
+ first = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ struct xyarray *group_fd = NULL;
+
+ if (group && evsel != first)
+ group_fd = first->fd;
+
+ err = perf_evsel__open(evsel, evlist->cpus, evlist->threads,
+ group, group_fd);
+ if (err < 0)
+ goto out_err;
+ }
+
+ return 0;
+out_err:
+ ncpus = evlist->cpus ? evlist->cpus->nr : 1;
+ nthreads = evlist->threads ? evlist->threads->nr : 1;
+
+ list_for_each_entry_reverse(evsel, &evlist->entries, node)
+ perf_evsel__close(evsel, ncpus, nthreads);
+
+ return err;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 6be71fc5779..1779ffef782 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -50,6 +50,8 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
+int perf_evlist__open(struct perf_evlist *evlist, bool group);
+
int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
void perf_evlist__munmap(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b46f6e4bff3..e4262642258 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -16,6 +16,7 @@
#include "thread_map.h"
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
int __perf_evsel__sample_size(u64 sample_type)
{
@@ -204,15 +205,16 @@ int __perf_evsel__read(struct perf_evsel *evsel,
}
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group)
+ struct thread_map *threads, bool group,
+ struct xyarray *group_fds)
{
int cpu, thread;
unsigned long flags = 0;
- int pid = -1;
+ int pid = -1, err;
if (evsel->fd == NULL &&
perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
- return -1;
+ return -ENOMEM;
if (evsel->cgrp) {
flags = PERF_FLAG_PID_CGROUP;
@@ -220,7 +222,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
}
for (cpu = 0; cpu < cpus->nr; cpu++) {
- int group_fd = -1;
+ int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
for (thread = 0; thread < threads->nr; thread++) {
@@ -231,8 +233,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
pid,
cpus->map[cpu],
group_fd, flags);
- if (FD(evsel, cpu, thread) < 0)
+ if (FD(evsel, cpu, thread) < 0) {
+ err = -errno;
goto out_close;
+ }
if (group && group_fd == -1)
group_fd = FD(evsel, cpu, thread);
@@ -249,7 +253,17 @@ out_close:
}
thread = threads->nr;
} while (--cpu >= 0);
- return -1;
+ return err;
+}
+
+void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+ if (evsel->fd == NULL)
+ return;
+
+ perf_evsel__close_fd(evsel, ncpus, nthreads);
+ perf_evsel__free_fd(evsel);
+ evsel->fd = NULL;
}
static struct {
@@ -269,7 +283,8 @@ static struct {
};
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group)
+ struct thread_map *threads, bool group,
+ struct xyarray *group_fd)
{
if (cpus == NULL) {
/* Work around old compiler warnings about strict aliasing */
@@ -279,19 +294,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (threads == NULL)
threads = &empty_thread_map.map;
- return __perf_evsel__open(evsel, cpus, threads, group);
+ return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
}
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus, bool group)
+ struct cpu_map *cpus, bool group,
+ struct xyarray *group_fd)
{
- return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
+ return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
+ group_fd);
}
int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads, bool group)
+ struct thread_map *threads, bool group,
+ struct xyarray *group_fd)
{
- return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
+ return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
+ group_fd);
}
static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index e9a31554e26..b1d15e6f7ae 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -82,11 +82,15 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
- struct cpu_map *cpus, bool group);
+ struct cpu_map *cpus, bool group,
+ struct xyarray *group_fds);
int perf_evsel__open_per_thread(struct perf_evsel *evsel,
- struct thread_map *threads, bool group);
+ struct thread_map *threads, bool group,
+ struct xyarray *group_fds);
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
- struct thread_map *threads, bool group);
+ struct thread_map *threads, bool group,
+ struct xyarray *group_fds);
+void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
#define perf_evsel__match(evsel, t, c) \
(evsel->attr.type == PERF_TYPE_##t && \
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 76c0b2c49eb..bcd05d05b4f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1,5 +1,6 @@
#define _FILE_OFFSET_BITS 64
+#include "util.h"
#include <sys/types.h>
#include <byteswap.h>
#include <unistd.h>
@@ -11,7 +12,6 @@
#include "evlist.h"
#include "evsel.h"
-#include "util.h"
#include "header.h"
#include "../perf.h"
#include "trace-event.h"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f6a993963a1..a36a3fa81ff 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -365,7 +365,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)
root = hists__get_rotate_entries_in(hists);
next = rb_first(root);
- hists->stats.total_period = 0;
while (next) {
n = rb_entry(next, struct hist_entry, rb_node_in);
@@ -379,7 +378,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)
* been set by, say, the hist_browser.
*/
hists__apply_filters(hists, n);
- hists__inc_nr_entries(hists, n);
}
}
}
@@ -442,6 +440,7 @@ static void __hists__output_resort(struct hists *hists, bool threaded)
hists->entries = RB_ROOT;
hists->nr_entries = 0;
+ hists->stats.total_period = 0;
hists__reset_col_len(hists);
while (next) {
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ff93ddc91c5..c86c1d27bd1 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -28,6 +28,7 @@ struct events_stats {
u64 total_lost;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
+ u32 nr_lost_warned;
u32 nr_unknown_events;
u32 nr_invalid_chains;
u32 nr_unknown_id;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 7624324efad..9dd47a4f259 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -623,7 +623,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
evsel->attr.inherit = inherit;
- if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
+ /*
+ * This will group just the fds for this single evsel, to group
+ * multiple events, use evlist.open().
+ */
+ if (perf_evsel__open(evsel, cpus, threads, group, NULL) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@@ -814,6 +818,25 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
return Py_None;
}
+static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
+ PyObject *args, PyObject *kwargs)
+{
+ struct perf_evlist *evlist = &pevlist->evlist;
+ int group = 0;
+ static char *kwlist[] = { "group", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
+ return NULL;
+
+ if (perf_evlist__open(evlist, group) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
static PyMethodDef pyrf_evlist__methods[] = {
{
.ml_name = "mmap",
@@ -822,6 +845,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
.ml_doc = PyDoc_STR("mmap the file descriptor table.")
},
{
+ .ml_name = "open",
+ .ml_meth = (PyCFunction)pyrf_evlist__open,
+ .ml_flags = METH_VARARGS | METH_KEYWORDS,
+ .ml_doc = PyDoc_STR("open the file descriptors.")
+ },
+ {
.ml_name = "poll",
.ml_meth = (PyCFunction)pyrf_evlist__poll,
.ml_flags = METH_VARARGS | METH_KEYWORDS,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 20e011c99a9..85c1e6b76f0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -502,6 +502,7 @@ static void flush_sample_queue(struct perf_session *s,
struct perf_sample sample;
u64 limit = os->next_flush;
u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
+ unsigned idx = 0, progress_next = os->nr_samples / 16;
int ret;
if (!ops->ordered_samples || !limit)
@@ -521,6 +522,11 @@ static void flush_sample_queue(struct perf_session *s,
os->last_flush = iter->timestamp;
list_del(&iter->list);
list_add(&iter->list, &os->sample_cache);
+ if (++idx >= progress_next) {
+ progress_next += os->nr_samples / 16;
+ ui_progress__update(idx, os->nr_samples,
+ "Processing time ordered events...");
+ }
}
if (list_empty(head)) {
@@ -529,6 +535,8 @@ static void flush_sample_queue(struct perf_session *s,
os->last_sample =
list_entry(head->prev, struct sample_queue, list);
}
+
+ os->nr_samples = 0;
}
/*
@@ -588,6 +596,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
u64 timestamp = new->timestamp;
struct list_head *p;
+ ++os->nr_samples;
os->last_sample = new;
if (!sample) {
@@ -738,10 +747,27 @@ static int perf_session_deliver_event(struct perf_session *session,
dump_event(session, event, file_offset, sample);
+ evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
+ /*
+ * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
+ * because the tools right now may apply filters, discarding
+ * some of the samples. For consistency, in the future we
+ * should have something like nr_filtered_samples and remove
+ * the sample->period from total_sample_period, etc, KISS for
+ * now tho.
+ *
+ * Also testing against NULL allows us to handle files without
+ * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
+ * future probably it'll be a good idea to restrict event
+ * processing via perf_session to files with both set.
+ */
+ hists__inc_nr_events(&evsel->hists, event->header.type);
+ }
+
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
dump_sample(session, event, sample);
- evsel = perf_evlist__id2evsel(session->evlist, sample->id);
if (evsel == NULL) {
++session->hists.stats.nr_unknown_id;
return -1;
@@ -874,11 +900,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
const struct perf_event_ops *ops)
{
if (ops->lost == perf_event__process_lost &&
- session->hists.stats.total_lost != 0) {
- ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
- "!\n\nCheck IO/CPU overload!\n\n",
- session->hists.stats.total_period,
- session->hists.stats.total_lost);
+ session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
+ ui__warning("Processed %d events and lost %d chunks!\n\n"
+ "Check IO/CPU overload!\n\n",
+ session->hists.stats.nr_events[0],
+ session->hists.stats.nr_events[PERF_RECORD_LOST]);
}
if (session->hists.stats.nr_unknown_events != 0) {
@@ -1012,7 +1038,6 @@ int __perf_session__process_events(struct perf_session *session,
{
u64 head, page_offset, file_offset, file_pos, progress_next;
int err, mmap_prot, mmap_flags, map_idx = 0;
- struct ui_progress *progress;
size_t page_size, mmap_size;
cha