* [GIT PULL 00/25] perf/core improvements and fixes
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
David Ahern, Frederic Weisbecker, Jiri Olsa, Joonsoo Kim,
linux-mm, Masami Hiramatsu, Minchan Kim, Namhyung Kim,
Pekka Enberg, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
Hi Ingo,
Please consider applying, on top of previous requests,
- Arnaldo
The following changes since commit 0c160d495b5616e071bb4f873812e8f473128149:
perf kmem: Add kmem.default config option (2015-05-04 13:34:48 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3
for you to fetch changes up to 3698dab1c849c7e1cd440df4fca24baa1973d53b:
perf tools: Move TUI-specific fields out of map_symbol (2015-05-05 18:13:24 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Improve --filter support for 'perf probe', allowing using its arguments
on other commands, as --add, --del, etc (Masami Hiramatsu)
- Show warning when running 'perf kmem stat' on a unsuitable perf.data file,
i.e. one with events that are not the ones required for the stat variant
used (Namhyung Kim).
Infrastructure:
- Auxtrace support patches, paving the way to support Intel PT and BTS (Adrian Hunter)
- hists browser (top, report) refactorings (Namhyung Kim)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----------------------------------------------------------------
Adrian Hunter (9):
perf report: Fix placement of itrace option in documentation
perf tools: Add AUX area tracing index
perf tools: Hit all build ids when AUX area tracing
perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing
perf auxtrace: Add option to synthesize events for transactions
perf tools: Add support for PERF_RECORD_AUX
perf tools: Add support for PERF_RECORD_ITRACE_START
perf tools: Add AUX area tracing Snapshot Mode
perf record: Add AUX area tracing Snapshot Mode support
Masami Hiramatsu (4):
perf probe: Allow to use filter on --del command
perf probe: Accept filter argument for --funcs
perf probe: Remove redundant cleanup of params.filter
perf probe: Cleanup and consolidate command parsers
Namhyung Kim (12):
perf kmem: Show warning when trying to run stat without record
perf tools: Move TUI-specific fields into unnamed union
perf tools: Move init_have_children field to the unnamed union
perf hists browser: Fix possible memory leak
perf hists browser: Save hist_browser_timer pointer in hist_browser
perf hists browser: Save pstack in the hist_browser
perf hists browser: Save perf_session_env in the hist_browser
perf hists browser: Split popup menu actions
perf hists browser: Split popup menu actions - part 2
perf tools: Introduce pstack_peek()
perf hists browser: Simplify zooming code using pstack_peek()
perf tools: Move TUI-specific fields out of map_symbol
tools/perf/Documentation/perf-inject.txt | 9 +-
tools/perf/Documentation/perf-probe.txt | 3 +-
tools/perf/Documentation/perf-record.txt | 7 +
tools/perf/Documentation/perf-report.txt | 15 +-
tools/perf/Documentation/perf-script.txt | 9 +-
tools/perf/Makefile.perf | 2 +
tools/perf/builtin-buildid-list.c | 9 +
tools/perf/builtin-inject.c | 78 +++-
tools/perf/builtin-kmem.c | 17 +-
tools/perf/builtin-probe.c | 133 +++----
tools/perf/builtin-record.c | 172 ++++++++-
tools/perf/config/Makefile | 5 +
tools/perf/perf.h | 3 +
tools/perf/tests/make | 4 +-
tools/perf/ui/browsers/hists.c | 633 +++++++++++++++++++------------
tools/perf/util/Build | 2 +-
tools/perf/util/auxtrace.c | 305 ++++++++++++++-
tools/perf/util/auxtrace.h | 217 +++++++++++
tools/perf/util/callchain.h | 4 +
tools/perf/util/event.c | 39 ++
tools/perf/util/event.h | 24 ++
tools/perf/util/header.c | 31 +-
tools/perf/util/hist.c | 2 +-
tools/perf/util/machine.c | 21 +
tools/perf/util/machine.h | 4 +
tools/perf/util/parse-options.h | 4 +
tools/perf/util/probe-event.c | 102 ++---
tools/perf/util/probe-event.h | 2 +-
tools/perf/util/pstack.c | 7 +
tools/perf/util/pstack.h | 1 +
tools/perf/util/session.c | 32 ++
tools/perf/util/session.h | 1 +
tools/perf/util/sort.h | 22 +-
tools/perf/util/symbol.h | 2 -
tools/perf/util/tool.h | 2 +
35 files changed, 1455 insertions(+), 468 deletions(-)
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 01/25] perf report: Fix placement of itrace option in documentation
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
(?)
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Jiri Olsa, Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Unwittingly the itrace options for perf report ended up below the
Overhead Calculation section. Move it back with the other options.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-2-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-report.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index b66f6b4..b771340 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -324,9 +324,6 @@ OPTIONS
--header-only::
Show only perf.data header (forces --stdio).
-
-include::callchain-overhead-calculation.txt[]
-
--itrace::
Options for decoding instruction tracing data. The options are:
@@ -354,6 +351,9 @@ include::callchain-overhead-calculation.txt[]
To disable decoding entirely, use --no-itrace.
+
+include::callchain-overhead-calculation.txt[]
+
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-annotate[1]
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 02/25] perf tools: Add AUX area tracing index
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
(?)
(?)
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add an index of AUX area tracing events within a perf.data file.
perf record uses a special user event PERF_RECORD_FINISHED_ROUND to
enable sorting of events in chunks instead of having to sort all events
altogether.
AUX area tracing events contain data that can span back to the very
beginning of the recording period. i.e. they do not obey the rules of
PERF_RECORD_FINISHED_ROUND.
By adding an index, AUX area tracing events can be found in advance and
the PERF_RECORD_FINISHED_ROUND approach works as usual.
The index is recorded with the auxtrace feature in the perf.data file.
A session reads the index but does not process it. An AUX area decoder
can queue all the AUX area data in advance using
auxtrace_queues__process_index() or otherwise process the index in some
custom manner.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-inject.c | 15 ++++
tools/perf/builtin-record.c | 15 ++++
tools/perf/util/auxtrace.c | 215 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/auxtrace.h | 35 ++++++++
| 31 ++++++-
tools/perf/util/session.c | 2 +
tools/perf/util/session.h | 1 +
7 files changed, 310 insertions(+), 4 deletions(-)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index c5f6515..6d4bbde 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -122,6 +122,18 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
tool);
int ret;
+ if (!inject->output.is_pipe) {
+ off_t offset;
+
+ offset = lseek(inject->output.fd, 0, SEEK_CUR);
+ if (offset == -1)
+ return -errno;
+ ret = auxtrace_index__auxtrace_event(&session->auxtrace_index,
+ event, offset);
+ if (ret < 0)
+ return ret;
+ }
+
if (perf_data_file__is_pipe(session->file) || !session->one_mmap) {
ret = output_bytes(inject, event, event->header.size);
if (ret < 0)
@@ -487,6 +499,9 @@ static int __cmd_inject(struct perf_inject *inject)
output_data_offset = 4096;
}
+ if (!inject->itrace_synth_opts.set)
+ auxtrace_index__free(&session->auxtrace_index);
+
if (!file_out->is_pipe)
lseek(fd, output_data_offset, SEEK_SET);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4c9aaa1..c8c784c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -117,9 +117,24 @@ static int record__process_auxtrace(struct perf_tool *tool,
size_t len1, void *data2, size_t len2)
{
struct record *rec = container_of(tool, struct record, tool);
+ struct perf_data_file *file = &rec->file;
size_t padding;
u8 pad[8] = {0};
+ if (!perf_data_file__is_pipe(file)) {
+ off_t file_offset;
+ int fd = perf_data_file__fd(file);
+ int err;
+
+ file_offset = lseek(fd, 0, SEEK_CUR);
+ if (file_offset == -1)
+ return -1;
+ err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
+ event, file_offset);
+ if (err)
+ return err;
+ }
+
/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
padding = (len1 + len2) & 7;
if (padding)
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 3cd89ec..28ce134 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -344,6 +344,33 @@ out_err:
return err;
}
+static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
+ struct perf_session *session,
+ off_t file_offset, size_t sz)
+{
+ union perf_event *event;
+ int err;
+ char buf[PERF_SAMPLE_MAX_SIZE];
+
+ err = perf_session__peek_event(session, file_offset, buf,
+ PERF_SAMPLE_MAX_SIZE, &event, NULL);
+ if (err)
+ return err;
+
+ if (event->header.type == PERF_RECORD_AUXTRACE) {
+ if (event->header.size < sizeof(struct auxtrace_event) ||
+ event->header.size != sz) {
+ err = -EINVAL;
+ goto out;
+ }
+ file_offset += event->header.size;
+ err = auxtrace_queues__add_event(queues, session, event,
+ file_offset, NULL);
+ }
+out:
+ return err;
+}
+
void auxtrace_queues__free(struct auxtrace_queues *queues)
{
unsigned int i;
@@ -500,6 +527,194 @@ auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
return NULL;
}
+static int auxtrace_index__alloc(struct list_head *head)
+{
+ struct auxtrace_index *auxtrace_index;
+
+ auxtrace_index = malloc(sizeof(struct auxtrace_index));
+ if (!auxtrace_index)
+ return -ENOMEM;
+
+ auxtrace_index->nr = 0;
+ INIT_LIST_HEAD(&auxtrace_index->list);
+
+ list_add_tail(&auxtrace_index->list, head);
+
+ return 0;
+}
+
+void auxtrace_index__free(struct list_head *head)
+{
+ struct auxtrace_index *auxtrace_index, *n;
+
+ list_for_each_entry_safe(auxtrace_index, n, head, list) {
+ list_del(&auxtrace_index->list);
+ free(auxtrace_index);
+ }
+}
+
+static struct auxtrace_index *auxtrace_index__last(struct list_head *head)
+{
+ struct auxtrace_index *auxtrace_index;
+ int err;
+
+ if (list_empty(head)) {
+ err = auxtrace_index__alloc(head);
+ if (err)
+ return NULL;
+ }
+
+ auxtrace_index = list_entry(head->prev, struct auxtrace_index, list);
+
+ if (auxtrace_index->nr >= PERF_AUXTRACE_INDEX_ENTRY_COUNT) {
+ err = auxtrace_index__alloc(head);
+ if (err)
+ return NULL;
+ auxtrace_index = list_entry(head->prev, struct auxtrace_index,
+ list);
+ }
+
+ return auxtrace_index;
+}
+
+int auxtrace_index__auxtrace_event(struct list_head *head,
+ union perf_event *event, off_t file_offset)
+{
+ struct auxtrace_index *auxtrace_index;
+ size_t nr;
+
+ auxtrace_index = auxtrace_index__last(head);
+ if (!auxtrace_index)
+ return -ENOMEM;
+
+ nr = auxtrace_index->nr;
+ auxtrace_index->entries[nr].file_offset = file_offset;
+ auxtrace_index->entries[nr].sz = event->header.size;
+ auxtrace_index->nr += 1;
+
+ return 0;
+}
+
+static int auxtrace_index__do_write(int fd,
+ struct auxtrace_index *auxtrace_index)
+{
+ struct auxtrace_index_entry ent;
+ size_t i;
+
+ for (i = 0; i < auxtrace_index->nr; i++) {
+ ent.file_offset = auxtrace_index->entries[i].file_offset;
+ ent.sz = auxtrace_index->entries[i].sz;
+ if (writen(fd, &ent, sizeof(ent)) != sizeof(ent))
+ return -errno;
+ }
+ return 0;
+}
+
+int auxtrace_index__write(int fd, struct list_head *head)
+{
+ struct auxtrace_index *auxtrace_index;
+ u64 total = 0;
+ int err;
+
+ list_for_each_entry(auxtrace_index, head, list)
+ total += auxtrace_index->nr;
+
+ if (writen(fd, &total, sizeof(total)) != sizeof(total))
+ return -errno;
+
+ list_for_each_entry(auxtrace_index, head, list) {
+ err = auxtrace_index__do_write(fd, auxtrace_index);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int auxtrace_index__process_entry(int fd, struct list_head *head,
+ bool needs_swap)
+{
+ struct auxtrace_index *auxtrace_index;
+ struct auxtrace_index_entry ent;
+ size_t nr;
+
+ if (readn(fd, &ent, sizeof(ent)) != sizeof(ent))
+ return -1;
+
+ auxtrace_index = auxtrace_index__last(head);
+ if (!auxtrace_index)
+ return -1;
+
+ nr = auxtrace_index->nr;
+ if (needs_swap) {
+ auxtrace_index->entries[nr].file_offset =
+ bswap_64(ent.file_offset);
+ auxtrace_index->entries[nr].sz = bswap_64(ent.sz);
+ } else {
+ auxtrace_index->entries[nr].file_offset = ent.file_offset;
+ auxtrace_index->entries[nr].sz = ent.sz;
+ }
+
+ auxtrace_index->nr = nr + 1;
+
+ return 0;
+}
+
+int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
+ bool needs_swap)
+{
+ struct list_head *head = &session->auxtrace_index;
+ u64 nr;
+
+ if (readn(fd, &nr, sizeof(u64)) != sizeof(u64))
+ return -1;
+
+ if (needs_swap)
+ nr = bswap_64(nr);
+
+ if (sizeof(u64) + nr * sizeof(struct auxtrace_index_entry) > size)
+ return -1;
+
+ while (nr--) {
+ int err;
+
+ err = auxtrace_index__process_entry(fd, head, needs_swap);
+ if (err)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int auxtrace_queues__process_index_entry(struct auxtrace_queues *queues,
+ struct perf_session *session,
+ struct auxtrace_index_entry *ent)
+{
+ return auxtrace_queues__add_indexed_event(queues, session,
+ ent->file_offset, ent->sz);
+}
+
+int auxtrace_queues__process_index(struct auxtrace_queues *queues,
+ struct perf_session *session)
+{
+ struct auxtrace_index *auxtrace_index;
+ struct auxtrace_index_entry *ent;
+ size_t i;
+ int err;
+
+ list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
+ for (i = 0; i < auxtrace_index->nr; i++) {
+ ent = &auxtrace_index->entries[i];
+ err = auxtrace_queues__process_index_entry(queues,
+ session,
+ ent);
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+}
+
struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
struct auxtrace_buffer *buffer)
{
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 53b60a6..b9e4b9d 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -80,6 +80,32 @@ struct itrace_synth_opts {
};
/**
+ * struct auxtrace_index_entry - indexes a AUX area tracing event within a
+ * perf.data file.
+ * @file_offset: offset within the perf.data file
+ * @sz: size of the event
+ */
+struct auxtrace_index_entry {
+ u64 file_offset;
+ u64 sz;
+};
+
+#define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256
+
+/**
+ * struct auxtrace_index - index of AUX area tracing events within a perf.data
+ * file.
+ * @list: linking a number of arrays of entries
+ * @nr: number of entries
+ * @entries: array of entries
+ */
+struct auxtrace_index {
+ struct list_head list;
+ size_t nr;
+ struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT];
+};
+
+/**
* struct auxtrace - session callbacks to allow AUX area data decoding.
* @process_event: lets the decoder see all session events
* @flush_events: process any remaining data
@@ -321,6 +347,8 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
union perf_event *event, off_t data_offset,
struct auxtrace_buffer **buffer_ptr);
void auxtrace_queues__free(struct auxtrace_queues *queues);
+int auxtrace_queues__process_index(struct auxtrace_queues *queues,
+ struct perf_session *session);
struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
struct auxtrace_buffer *buffer);
void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd);
@@ -361,6 +389,13 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,
void auxtrace_record__free(struct auxtrace_record *itr);
u64 auxtrace_record__reference(struct auxtrace_record *itr);
+int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,
+ off_t file_offset);
+int auxtrace_index__write(int fd, struct list_head *head);
+int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
+ bool needs_swap);
+void auxtrace_index__free(struct list_head *head);
+
void auxtrace_synth_error(struct auxtrace_error_event *auxtrace_error, int type,
int code, int cpu, pid_t pid, pid_t tid, u64 ip,
const char *msg);
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 589c280..3f0d809 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -869,11 +869,18 @@ static int write_branch_stack(int fd __maybe_unused,
return 0;
}
-static int write_auxtrace(int fd __maybe_unused,
- struct perf_header *h __maybe_unused,
+static int write_auxtrace(int fd, struct perf_header *h,
struct perf_evlist *evlist __maybe_unused)
{
- return 0;
+ struct perf_session *session;
+ int err;
+
+ session = container_of(h, struct perf_session, header);
+
+ err = auxtrace_index__write(fd, &session->auxtrace_index);
+ if (err < 0)
+ pr_err("Failed to write auxtrace index\n");
+ return err;
}
static void print_hostname(struct perf_header *ph, int fd __maybe_unused,
@@ -1834,6 +1841,22 @@ out_free:
return ret;
}
+static int process_auxtrace(struct perf_file_section *section,
+ struct perf_header *ph, int fd,
+ void *data __maybe_unused)
+{
+ struct perf_session *session;
+ int err;
+
+ session = container_of(ph, struct perf_session, header);
+
+ err = auxtrace_index__process(fd, section->size, session,
+ ph->needs_swap);
+ if (err < 0)
+ pr_err("Failed to process auxtrace index\n");
+ return err;
+}
+
struct feature_ops {
int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1874,7 +1897,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
FEAT_OPP(HEADER_GROUP_DESC, group_desc),
- FEAT_OPA(HEADER_AUXTRACE, auxtrace),
+ FEAT_OPP(HEADER_AUXTRACE, auxtrace),
};
struct header_print_data {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 90fa567..b6972b1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -120,6 +120,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
session->repipe = repipe;
session->tool = tool;
+ INIT_LIST_HEAD(&session->auxtrace_index);
machines__init(&session->machines);
ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
@@ -187,6 +188,7 @@ static void perf_session_env__delete(struct perf_session_env *env)
void perf_session__delete(struct perf_session *session)
{
auxtrace__free(session);
+ auxtrace_index__free(&session->auxtrace_index);
perf_session__destroy_kernel_maps(session);
perf_session__delete_threads(session);
perf_session_env__delete(&session->header.env);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9ed5135..b44afc7 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -24,6 +24,7 @@ struct perf_session {
struct perf_evlist *evlist;
struct auxtrace *auxtrace;
struct itrace_synth_opts *itrace_synth_opts;
+ struct list_head auxtrace_index;
struct trace_event tevent;
bool repipe;
bool one_mmap;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 03/25] perf tools: Hit all build ids when AUX area tracing
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (2 preceding siblings ...)
(?)
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
We need to include all buildids when a perf.data file contains AUX area
tracing data because we do not decode the trace for that purpose because
it would take too long.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-4-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-buildid-list.c | 9 +++++++++
tools/perf/builtin-inject.c | 8 +++++++-
tools/perf/builtin-record.c | 10 +++++++++-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index feb420f..9fe93c8 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -69,6 +69,15 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
if (session == NULL)
return -1;
+
+ /*
+ * We take all buildids when the file contains AUX area tracing data
+ * because we do not decode the trace because it would take too long.
+ */
+ if (!perf_data_file__is_pipe(&file) &&
+ perf_header__has_feat(&session->header, HEADER_AUXTRACE))
+ with_hits = false;
+
/*
* in pipe-mode, the only way to get the buildids is to parse
* the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6d4bbde..cc905f1 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -27,6 +27,7 @@ struct perf_inject {
struct perf_session *session;
bool build_ids;
bool sched_stat;
+ bool have_auxtrace;
const char *input_name;
struct perf_data_file output;
u64 bytes_written;
@@ -122,6 +123,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
tool);
int ret;
+ inject->have_auxtrace = true;
+
if (!inject->output.is_pipe) {
off_t offset;
@@ -508,9 +511,12 @@ static int __cmd_inject(struct perf_inject *inject)
ret = perf_session__process_events(session);
if (!file_out->is_pipe) {
- if (inject->build_ids)
+ if (inject->build_ids) {
perf_header__set_feat(&session->header,
HEADER_BUILD_ID);
+ if (inject->have_auxtrace)
+ dsos__hit_all(session);
+ }
/*
* The AUX areas have been removed and replaced with
* synthesized hardware events, so clear the feature flag.
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c8c784c..4d0ebbb 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -620,8 +620,16 @@ out_child:
if (!err && !file->is_pipe) {
rec->session->header.data_size += rec->bytes_written;
- if (!rec->no_buildid)
+ if (!rec->no_buildid) {
process_buildids(rec);
+ /*
+ * We take all buildids when the file contains
+ * AUX area tracing data because we do not decode the
+ * trace because it would take too long.
+ */
+ if (rec->opts.full_auxtrace)
+ dsos__hit_all(rec->session);
+ }
perf_session__write_header(rec->session, rec->evlist, fd, true);
}
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 04/25] perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (3 preceding siblings ...)
(?)
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add build option NO_AUXTRACE to exclude compiling support for AUX area
tracing. Support for both recording and processing is excluded and by
implication any future additions such as Intel PT and Intel BTS will
also not be compiled in with this option.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Makefile.perf | 2 +
tools/perf/builtin-inject.c | 53 +++++++++++-------
tools/perf/builtin-record.c | 13 +++++
tools/perf/config/Makefile | 5 ++
tools/perf/tests/make | 4 +-
tools/perf/util/Build | 2 +-
tools/perf/util/auxtrace.h | 128 ++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 186 insertions(+), 21 deletions(-)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index c43a205..03409cc 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -73,6 +73,8 @@ include config/utilities.mak
# for CTF data format.
#
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
+#
+# Define NO_AUXTRACE if you do not want AUX area tracing support
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(shell pwd)))
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index cc905f1..7c7a7ee 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -53,25 +53,6 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz)
return 0;
}
-static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
-{
- char buf[4096];
- ssize_t ssz;
- int ret;
-
- while (size > 0) {
- ssz = read(fd, buf, min(size, (off_t)sizeof(buf)));
- if (ssz < 0)
- return -errno;
- ret = output_bytes(inject, buf, ssz);
- if (ret)
- return ret;
- size -= ssz;
- }
-
- return 0;
-}
-
static int perf_event__repipe_synth(struct perf_tool *tool,
union perf_event *event)
{
@@ -114,6 +95,27 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
return perf_event__repipe_synth(tool, event);
}
+#ifdef HAVE_AUXTRACE_SUPPORT
+
+static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
+{
+ char buf[4096];
+ ssize_t ssz;
+ int ret;
+
+ while (size > 0) {
+ ssz = read(fd, buf, min(size, (off_t)sizeof(buf)));
+ if (ssz < 0)
+ return -errno;
+ ret = output_bytes(inject, buf, ssz);
+ if (ret)
+ return ret;
+ size -= ssz;
+ }
+
+ return 0;
+}
+
static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session
@@ -153,6 +155,19 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
return event->auxtrace.size;
}
+#else
+
+static s64
+perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_session *session __maybe_unused)
+{
+ pr_err("AUX area tracing not supported\n");
+ return -EINVAL;
+}
+
+#endif
+
static int perf_event__repipe(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4d0ebbb..dbb2c02 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -112,6 +112,8 @@ out:
return rc;
}
+#ifdef HAVE_AUXTRACE_SUPPORT
+
static int record__process_auxtrace(struct perf_tool *tool,
union perf_event *event, void *data1,
size_t len1, void *data2, size_t len2)
@@ -165,6 +167,17 @@ static int record__auxtrace_mmap_read(struct record *rec,
return 0;
}
+#else
+
+static inline
+int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
+ struct auxtrace_mmap *mm __maybe_unused)
+{
+ return 0;
+}
+
+#endif
+
static volatile int done = 0;
static volatile int signr = -1;
static volatile int child_finished = 0;
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 59a98c6..435b6ca 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -610,6 +610,11 @@ ifdef LIBBABELTRACE
endif
endif
+ifndef NO_AUXTRACE
+ $(call detected,CONFIG_AUXTRACE)
+ CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+endif
+
# Among the variables below, these:
# perfexecdir
# template_dir
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 901ec91..65280d2 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -32,6 +32,7 @@ make_no_backtrace := NO_BACKTRACE=1
make_no_libnuma := NO_LIBNUMA=1
make_no_libaudit := NO_LIBAUDIT=1
make_no_libbionic := NO_LIBBIONIC=1
+make_no_auxtrace := NO_AUXTRACE=1
make_tags := tags
make_cscope := cscope
make_help := help
@@ -52,7 +53,7 @@ make_static := LDFLAGS=-static
make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
-make_minimal += NO_LIBDW_DWARF_UNWIND=1
+make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1
# $(run) contains all available tests
run := make_pure
@@ -74,6 +75,7 @@ run += make_no_backtrace
run += make_no_libnuma
run += make_no_libaudit
run += make_no_libbionic
+run += make_no_auxtrace
run += make_help
run += make_doc
run += make_perf_o
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 28af8e2..d552203 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -74,7 +74,7 @@ libperf-y += data.o
libperf-$(CONFIG_X86) += tsc.o
libperf-y += cloexec.o
libperf-y += thread-stack.o
-libperf-y += auxtrace.o
+libperf-$(CONFIG_AUXTRACE) += auxtrace.o
libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index b9e4b9d..77b4699 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -26,6 +26,7 @@
#include "../perf.h"
#include "event.h"
#include "session.h"
+#include "debug.h"
union perf_event;
struct perf_session;
@@ -290,6 +291,8 @@ struct auxtrace_record {
int (*read_finish)(struct auxtrace_record *itr, int idx);
};
+#ifdef HAVE_AUXTRACE_SUPPORT
+
static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
{
struct perf_event_mmap_page *pc = mm->userpg;
@@ -458,4 +461,129 @@ static inline void auxtrace__free(struct perf_session *session)
return session->auxtrace->free(session);
}
+#else
+
+static inline struct auxtrace_record *
+auxtrace_record__init(struct perf_evlist *evlist __maybe_unused,
+ int *err __maybe_unused)
+{
+ *err = 0;
+ return NULL;
+}
+
+static inline
+void auxtrace_record__free(struct auxtrace_record *itr __maybe_unused)
+{
+}
+
+static inline int
+perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr __maybe_unused,
+ struct perf_tool *tool __maybe_unused,
+ struct perf_session *session __maybe_unused,
+ perf_event__handler_t process __maybe_unused)
+{
+ return -EINVAL;
+}
+
+static inline
+int auxtrace_record__options(struct auxtrace_record *itr __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused,
+ struct record_opts *opts __maybe_unused)
+{
+ return 0;
+}
+
+#define perf_event__process_auxtrace_info 0
+#define perf_event__process_auxtrace 0
+#define perf_event__process_auxtrace_error 0
+
+static inline
+void perf_session__auxtrace_error_inc(struct perf_session *session
+ __maybe_unused,
+ union perf_event *event
+ __maybe_unused)
+{
+}
+
+static inline
+void events_stats__auxtrace_error_warn(const struct events_stats *stats
+ __maybe_unused)
+{
+}
+
+static inline
+int itrace_parse_synth_opts(const struct option *opt __maybe_unused,
+ const char *str __maybe_unused,
+ int unset __maybe_unused)
+{
+ pr_err("AUX area tracing not supported\n");
+ return -EINVAL;
+}
+
+static inline
+int auxtrace__process_event(struct perf_session *session __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample __maybe_unused,
+ struct perf_tool *tool __maybe_unused)
+{
+ return 0;
+}
+
+static inline
+int auxtrace__flush_events(struct perf_session *session __maybe_unused,
+ struct perf_tool *tool __maybe_unused)
+{
+ return 0;
+}
+
+static inline
+void auxtrace__free_events(struct perf_session *session __maybe_unused)
+{
+}
+
+static inline
+void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache __maybe_unused)
+{
+}
+
+static inline
+void auxtrace__free(struct perf_session *session __maybe_unused)
+{
+}
+
+static inline
+int auxtrace_index__write(int fd __maybe_unused,
+ struct list_head *head __maybe_unused)
+{
+ return -EINVAL;
+}
+
+static inline
+int auxtrace_index__process(int fd __maybe_unused,
+ u64 size __maybe_unused,
+ struct perf_session *session __maybe_unused,
+ bool needs_swap __maybe_unused)
+{
+ return -EINVAL;
+}
+
+static inline
+void auxtrace_index__free(struct list_head *head __maybe_unused)
+{
+}
+
+int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
+ struct auxtrace_mmap_params *mp,
+ void *userpg, int fd);
+void auxtrace_mmap__munmap(struct auxtrace_mmap *mm);
+void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
+ off_t auxtrace_offset,
+ unsigned int auxtrace_pages,
+ bool auxtrace_overwrite);
+void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
+ struct perf_evlist *evlist, int idx,
+ bool per_cpu);
+
+#endif
+
#endif
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 05/25] perf auxtrace: Add option to synthesize events for transactions
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (4 preceding siblings ...)
(?)
@ 2015-05-05 21:31 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:31 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add AUX area tracing option 'x' to synthesize events for transactions.
This will be used by Intel PT to synthesize an event record for each TSX
start, commit or abort.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-6-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-inject.txt | 9 +++++----
tools/perf/Documentation/perf-report.txt | 9 +++++----
tools/perf/Documentation/perf-script.txt | 9 +++++----
tools/perf/util/auxtrace.c | 5 ++++-
tools/perf/util/auxtrace.h | 2 ++
5 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index bb1f655..b876ae3 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -52,11 +52,12 @@ OPTIONS
b synthesize branches events
c synthesize branches events (calls only)
r synthesize branches events (returns only)
+ x synthesize transactions events
e synthesize error events
d create a debug log
- g synthesize a call chain for instructions events
+ g synthesize a call chain (use with i or x)
- The default is all events i.e. the same as --itrace=ibe
+ The default is all events i.e. the same as --itrace=ibxe
In addition, the period (default 100000) for instructions events
can be specified in units of:
@@ -67,8 +68,8 @@ OPTIONS
us microseconds
ns nanoseconds (default)
- Also the call chain size (default 16, max. 1024) for instructions
- events can be specified.
+ Also the call chain size (default 16, max. 1024) for instructions or
+ transactions events can be specified.
SEE ALSO
--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index b771340..27190ed 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -331,11 +331,12 @@ OPTIONS
b synthesize branches events
c synthesize branches events (calls only)
r synthesize branches events (returns only)
+ x synthesize transactions events
e synthesize error events
d create a debug log
- g synthesize a call chain for instructions events
+ g synthesize a call chain (use with i or x)
- The default is all events i.e. the same as --itrace=ibe
+ The default is all events i.e. the same as --itrace=ibxe
In addition, the period (default 100000) for instructions events
can be specified in units of:
@@ -346,8 +347,8 @@ OPTIONS
us microseconds
ns nanoseconds (default)
- Also the call chain size (default 16, max. 1024) for instructions
- events can be specified.
+ Also the call chain size (default 16, max. 1024) for instructions or
+ transactions events can be specified.
To disable decoding entirely, use --no-itrace.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index b29cd2f..c82df57 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -235,11 +235,12 @@ OPTIONS
b synthesize branches events
c synthesize branches events (calls only)
r synthesize branches events (returns only)
+ x synthesize transactions events
e synthesize error events
d create a debug log
- g synthesize a call chain for instructions events
+ g synthesize a call chain (use with i or x)
- The default is all events i.e. the same as --itrace=ibe
+ The default is all events i.e. the same as --itrace=ibxe
In addition, the period (default 100000) for instructions events
can be specified in units of:
@@ -250,8 +251,8 @@ OPTIONS
us microseconds
ns nanoseconds (default)
- Also the call chain size (default 16, max. 1024) for instructions
- events can be specified.
+ Also the call chain size (default 16, max. 1024) for instructions or
+ transactions events can be specified.
To disable decoding entirely, use --no-itrace.
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 28ce134..1293710 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -888,6 +888,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
{
synth_opts->instructions = true;
synth_opts->branches = true;
+ synth_opts->transactions = true;
synth_opts->errors = true;
synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
@@ -960,6 +961,9 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
case 'b':
synth_opts->branches = true;
break;
+ case 'x':
+ synth_opts->transactions = true;
+ break;
case 'e':
synth_opts->errors = true;
break;
@@ -975,7 +979,6 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
synth_opts->returns = true;
break;
case 'g':
- synth_opts->instructions = true;
synth_opts->callchain = true;
synth_opts->callchain_sz =
PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 77b4699..8c6cbb1 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -54,6 +54,7 @@ enum itrace_period_type {
* because 'perf inject' will write it out
* @instructions: whether to synthesize 'instructions' events
* @branches: whether to synthesize 'branches' events
+ * @transactions: whether to synthesize events for transactions
* @errors: whether to synthesize decoder error events
* @dont_decode: whether to skip decoding entirely
* @log: write a decoding log
@@ -69,6 +70,7 @@ struct itrace_synth_opts {
bool inject;
bool instructions;
bool branches;
+ bool transactions;
bool errors;
bool dont_decode;
bool log;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 06/25] perf tools: Add support for PERF_RECORD_AUX
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (5 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add support for the PERF_RECORD_AUX event type.
PERF_RECORD_AUX is a new kernel event that records when new data lands
in the AUX buffer. Currently it is assumed that AUX data follows the
same ring buffer conventions used by the perf events buffer, and
consequently the AUX event is not processed during recording.
It is processed during session processing so that the information in the
'flags' member is made available.
The format of PERF_RECORD_AUX is outlined in the linux/perf_events.h
header file. The 'flags' are also enumerated.
Intel PT and Intel BTS use the flag named PERF_AUX_FLAG_TRUNCATED to
determine if data has been lost because the buffer became full as perf
was not able to empty it fast enough.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-7-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-inject.c | 1 +
tools/perf/util/event.c | 21 +++++++++++++++++++++
tools/perf/util/event.h | 13 +++++++++++++
tools/perf/util/machine.c | 10 ++++++++++
tools/perf/util/machine.h | 2 ++
tools/perf/util/session.c | 15 +++++++++++++++
tools/perf/util/tool.h | 1 +
7 files changed, 63 insertions(+)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 7c7a7ee..3e8f730 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -558,6 +558,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
.fork = perf_event__repipe,
.exit = perf_event__repipe,
.lost = perf_event__repipe,
+ .aux = perf_event__repipe,
.read = perf_event__repipe_sample,
.throttle = perf_event__repipe,
.unthrottle = perf_event__repipe,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 32323e5..724ffde 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -23,6 +23,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_FORK] = "FORK",
[PERF_RECORD_READ] = "READ",
[PERF_RECORD_SAMPLE] = "SAMPLE",
+ [PERF_RECORD_AUX] = "AUX",
[PERF_RECORD_HEADER_ATTR] = "ATTR",
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@@ -695,6 +696,14 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
return machine__process_lost_event(machine, event, sample);
}
+int perf_event__process_aux(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine)
+{
+ return machine__process_aux_event(machine, event);
+}
+
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
@@ -758,6 +767,15 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
return machine__process_exit_event(machine, event, sample);
}
+size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
+{
+ return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s]\n",
+ event->aux.aux_offset, event->aux.aux_size,
+ event->aux.flags,
+ event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
+ event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "");
+}
+
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{
size_t ret = fprintf(fp, "PERF_RECORD_%s",
@@ -777,6 +795,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
case PERF_RECORD_MMAP2:
ret += perf_event__fprintf_mmap2(event, fp);
break;
+ case PERF_RECORD_AUX:
+ ret += perf_event__fprintf_aux(event, fp);
+ break;
default:
ret += fprintf(fp, "\n");
}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 80e9f59..b3c350e 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -323,6 +323,13 @@ struct auxtrace_error_event {
char msg[MAX_AUXTRACE_ERROR_MSG];
};
+struct aux_event {
+ struct perf_event_header header;
+ u64 aux_offset;
+ u64 aux_size;
+ u64 flags;
+};
+
union perf_event {
struct perf_event_header header;
struct mmap_event mmap;
@@ -341,6 +348,7 @@ union perf_event {
struct auxtrace_info_event auxtrace_info;
struct auxtrace_event auxtrace;
struct auxtrace_error_event auxtrace_error;
+ struct aux_event aux;
};
void perf_event__print_totals(void);
@@ -376,6 +384,10 @@ int perf_event__process_lost(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
+int perf_event__process_aux(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine);
int perf_event__process_mmap(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -433,6 +445,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
u64 kallsyms__get_function_start(const char *kallsyms_filename,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 527e032..a7ad511 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -486,6 +486,14 @@ machine__module_dso(struct machine *machine, struct kmod_path *m,
return dso;
}
+int machine__process_aux_event(struct machine *machine __maybe_unused,
+ union perf_event *event)
+{
+ if (dump_trace)
+ perf_event__fprintf_aux(event, stdout);
+ return 0;
+}
+
struct map *machine__new_module(struct machine *machine, u64 start,
const char *filename)
{
@@ -1331,6 +1339,8 @@ int machine__process_event(struct machine *machine, union perf_event *event,
ret = machine__process_exit_event(machine, event, sample); break;
case PERF_RECORD_LOST:
ret = machine__process_lost_event(machine, event, sample); break;
+ case PERF_RECORD_AUX:
+ ret = machine__process_aux_event(machine, event); break;
default:
ret = -1;
break;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 6d64ced..fc5432a 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -81,6 +81,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
struct perf_sample *sample);
int machine__process_lost_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample);
+int machine__process_aux_event(struct machine *machine,
+ union perf_event *event);
int machine__process_mmap_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample);
int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b6972b1..0b4646c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -325,6 +325,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->exit = process_event_stub;
if (tool->lost == NULL)
tool->lost = perf_event__process_lost;
+ if (tool->aux == NULL)
+ tool->aux = perf_event__process_aux;
if (tool->read == NULL)
tool->read = process_event_sample_stub;
if (tool->throttle == NULL)
@@ -443,6 +445,16 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
swap_sample_id_all(event, &event->read + 1);
}
+static void perf_event__aux_swap(union perf_event *event, bool sample_id_all)
+{
+ event->aux.aux_offset = bswap_64(event->aux.aux_offset);
+ event->aux.aux_size = bswap_64(event->aux.aux_size);
+ event->aux.flags = bswap_64(event->aux.flags);
+
+ if (sample_id_all)
+ swap_sample_id_all(event, &event->aux + 1);
+}
+
static void perf_event__throttle_swap(union perf_event *event,
bool sample_id_all)
{
@@ -580,6 +592,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
[PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
[PERF_RECORD_SAMPLE] = perf_event__all64_swap,
+ [PERF_RECORD_AUX] = perf_event__aux_swap,
[PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
[PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
@@ -1029,6 +1042,8 @@ static int machines__deliver_event(struct machines *machines,
return tool->throttle(tool, event, sample, machine);
case PERF_RECORD_UNTHROTTLE:
return tool->unthrottle(tool, event, sample, machine);
+ case PERF_RECORD_AUX:
+ return tool->aux(tool, event, sample, machine);
default:
++evlist->stats.nr_unknown_events;
return -1;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 20afe19..8288caf 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -43,6 +43,7 @@ struct perf_tool {
fork,
exit,
lost,
+ aux,
throttle,
unthrottle;
event_attr_op attr;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 07/25] perf tools: Add support for PERF_RECORD_ITRACE_START
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (6 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add support for the PERF_RECORD_ITRACE_START event type. This event can
be used to determine the pid and tid that are running when Instruction
Tracing starts. Generally that information would come from a
sched_switch event but, at the start, no sched_switch events may yet
have been recorded.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-8-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-inject.c | 1 +
tools/perf/util/event.c | 18 ++++++++++++++++++
tools/perf/util/event.h | 11 +++++++++++
tools/perf/util/machine.c | 11 +++++++++++
tools/perf/util/machine.h | 2 ++
tools/perf/util/session.c | 15 +++++++++++++++
tools/perf/util/tool.h | 1 +
7 files changed, 59 insertions(+)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 3e8f730..d6a47e8 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -559,6 +559,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
.exit = perf_event__repipe,
.lost = perf_event__repipe,
.aux = perf_event__repipe,
+ .itrace_start = perf_event__repipe,
.read = perf_event__repipe_sample,
.throttle = perf_event__repipe,
.unthrottle = perf_event__repipe,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 724ffde..db52609 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -24,6 +24,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_READ] = "READ",
[PERF_RECORD_SAMPLE] = "SAMPLE",
[PERF_RECORD_AUX] = "AUX",
+ [PERF_RECORD_ITRACE_START] = "ITRACE_START",
[PERF_RECORD_HEADER_ATTR] = "ATTR",
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@@ -704,6 +705,14 @@ int perf_event__process_aux(struct perf_tool *tool __maybe_unused,
return machine__process_aux_event(machine, event);
}
+int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine)
+{
+ return machine__process_itrace_start_event(machine, event);
+}
+
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
@@ -776,6 +785,12 @@ size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "");
}
+size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
+{
+ return fprintf(fp, " pid: %u tid: %u\n",
+ event->itrace_start.pid, event->itrace_start.tid);
+}
+
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{
size_t ret = fprintf(fp, "PERF_RECORD_%s",
@@ -798,6 +813,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
case PERF_RECORD_AUX:
ret += perf_event__fprintf_aux(event, fp);
break;
+ case PERF_RECORD_ITRACE_START:
+ ret += perf_event__fprintf_itrace_start(event, fp);
+ break;
default:
ret += fprintf(fp, "\n");
}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index b3c350e..7eecd5e 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -330,6 +330,11 @@ struct aux_event {
u64 flags;
};
+struct itrace_start_event {
+ struct perf_event_header header;
+ u32 pid, tid;
+};
+
union perf_event {
struct perf_event_header header;
struct mmap_event mmap;
@@ -349,6 +354,7 @@ union perf_event {
struct auxtrace_event auxtrace;
struct auxtrace_error_event auxtrace_error;
struct aux_event aux;
+ struct itrace_start_event itrace_start;
};
void perf_event__print_totals(void);
@@ -388,6 +394,10 @@ int perf_event__process_aux(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
+int perf_event__process_itrace_start(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine);
int perf_event__process_mmap(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -446,6 +456,7 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
u64 kallsyms__get_function_start(const char *kallsyms_filename,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index a7ad511..2f47110 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -494,6 +494,14 @@ int machine__process_aux_event(struct machine *machine __maybe_unused,
return 0;
}
+int machine__process_itrace_start_event(struct machine *machine __maybe_unused,
+ union perf_event *event)
+{
+ if (dump_trace)
+ perf_event__fprintf_itrace_start(event, stdout);
+ return 0;
+}
+
struct map *machine__new_module(struct machine *machine, u64 start,
const char *filename)
{
@@ -1341,6 +1349,9 @@ int machine__process_event(struct machine *machine, union perf_event *event,
ret = machine__process_lost_event(machine, event, sample); break;
case PERF_RECORD_AUX:
ret = machine__process_aux_event(machine, event); break;
+ case PERF_RECORD_ITRACE_START:
+ ret = machine__process_itrace_start_event(machine, event);
+ break;
default:
ret = -1;
break;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index fc5432a..1d99296 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -83,6 +83,8 @@ int machine__process_lost_event(struct machine *machine, union perf_event *event
struct perf_sample *sample);
int machine__process_aux_event(struct machine *machine,
union perf_event *event);
+int machine__process_itrace_start_event(struct machine *machine,
+ union perf_event *event);
int machine__process_mmap_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample);
int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0b4646c..e722107 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -327,6 +327,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->lost = perf_event__process_lost;
if (tool->aux == NULL)
tool->aux = perf_event__process_aux;
+ if (tool->itrace_start == NULL)
+ tool->itrace_start = perf_event__process_itrace_start;
if (tool->read == NULL)
tool->read = process_event_sample_stub;
if (tool->throttle == NULL)
@@ -455,6 +457,16 @@ static void perf_event__aux_swap(union perf_event *event, bool sample_id_all)
swap_sample_id_all(event, &event->aux + 1);
}
+static void perf_event__itrace_start_swap(union perf_event *event,
+ bool sample_id_all)
+{
+ event->itrace_start.pid = bswap_32(event->itrace_start.pid);
+ event->itrace_start.tid = bswap_32(event->itrace_start.tid);
+
+ if (sample_id_all)
+ swap_sample_id_all(event, &event->itrace_start + 1);
+}
+
static void perf_event__throttle_swap(union perf_event *event,
bool sample_id_all)
{
@@ -593,6 +605,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
[PERF_RECORD_SAMPLE] = perf_event__all64_swap,
[PERF_RECORD_AUX] = perf_event__aux_swap,
+ [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap,
[PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
[PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
@@ -1044,6 +1057,8 @@ static int machines__deliver_event(struct machines *machines,
return tool->unthrottle(tool, event, sample, machine);
case PERF_RECORD_AUX:
return tool->aux(tool, event, sample, machine);
+ case PERF_RECORD_ITRACE_START:
+ return tool->itrace_start(tool, event, sample, machine);
default:
++evlist->stats.nr_unknown_events;
return -1;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 8288caf..7f282ad 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -44,6 +44,7 @@ struct perf_tool {
exit,
lost,
aux,
+ itrace_start,
throttle,
unthrottle;
event_attr_op attr;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 08/25] perf tools: Add AUX area tracing Snapshot Mode
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (7 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add support for making snapshots of AUX area tracing data.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-9-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/perf.h | 3 ++
tools/perf/util/auxtrace.c | 85 ++++++++++++++++++++++++++++++++++++++++------
tools/perf/util/auxtrace.h | 41 ++++++++++++++++++++++
3 files changed, 119 insertions(+), 10 deletions(-)
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 5042093..aa79fb8 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -55,6 +55,7 @@ struct record_opts {
bool sample_intr_regs;
bool running_time;
bool full_auxtrace;
+ bool auxtrace_snapshot_mode;
unsigned int freq;
unsigned int mmap_pages;
unsigned int auxtrace_mmap_pages;
@@ -62,6 +63,8 @@ struct record_opts {
u64 branch_stack;
u64 default_interval;
u64 user_interval;
+ size_t auxtrace_snapshot_size;
+ const char *auxtrace_snapshot_opts;
bool sample_transaction;
unsigned initial_delay;
bool use_clockid;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 1293710..df66966 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -504,6 +504,29 @@ void auxtrace_record__free(struct auxtrace_record *itr)
itr->free(itr);
}
+int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
+{
+ if (itr && itr->snapshot_start)
+ return itr->snapshot_start(itr);
+ return 0;
+}
+
+int auxtrace_record__snapshot_finish(struct auxtrace_record *itr)
+{
+ if (itr && itr->snapshot_finish)
+ return itr->snapshot_finish(itr);
+ return 0;
+}
+
+int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
+ struct auxtrace_mmap *mm,
+ unsigned char *data, u64 *head, u64 *old)
+{
+ if (itr && itr->find_snapshot)
+ return itr->find_snapshot(itr, idx, mm, data, head, old);
+ return 0;
+}
+
int auxtrace_record__options(struct auxtrace_record *itr,
struct perf_evlist *evlist,
struct record_opts *opts)
@@ -520,6 +543,19 @@ u64 auxtrace_record__reference(struct auxtrace_record *itr)
return 0;
}
+int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
+ struct record_opts *opts, const char *str)
+{
+ if (!str)
+ return 0;
+
+ if (itr)
+ return itr->parse_snapshot_options(itr, opts, str);
+
+ pr_err("No AUX area tracing to snapshot\n");
+ return -EINVAL;
+}
+
struct auxtrace_record *__weak
auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
{
@@ -1077,16 +1113,26 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
return 0;
}
-int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
- struct perf_tool *tool, process_auxtrace_t fn)
+static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
+ struct auxtrace_record *itr,
+ struct perf_tool *tool, process_auxtrace_t fn,
+ bool snapshot, size_t snapshot_size)
{
- u64 head = auxtrace_mmap__read_head(mm);
- u64 old = mm->prev, offset, ref;
+ u64 head, old = mm->prev, offset, ref;
unsigned char *data = mm->base;
size_t size, head_off, old_off, len1, len2, padding;
union perf_event ev;
void *data1, *data2;
+ if (snapshot) {
+ head = auxtrace_mmap__read_snapshot_head(mm);
+ if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
+ &head, &old))
+ return -1;
+ } else {
+ head = auxtrace_mmap__read_head(mm);
+ }
+
if (old == head)
return 0;
@@ -1106,6 +1152,9 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
else
size = mm->len - (old_off - head_off);
+ if (snapshot && size > snapshot_size)
+ size = snapshot_size;
+
ref = auxtrace_record__reference(itr);
if (head > old || size <= head || mm->mask) {
@@ -1153,18 +1202,34 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
mm->prev = head;
- auxtrace_mmap__write_tail(mm, head);
- if (itr->read_finish) {
- int err;
+ if (!snapshot) {
+ auxtrace_mmap__write_tail(mm, head);
+ if (itr->read_finish) {
+ int err;
- err = itr->read_finish(itr, mm->idx);
- if (err < 0)
- return err;
+ err = itr->read_finish(itr, mm->idx);
+ if (err < 0)
+ return err;
+ }
}
return 1;
}
+int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
+ struct perf_tool *tool, process_auxtrace_t fn)
+{
+ return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
+}
+
+int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
+ struct auxtrace_record *itr,
+ struct perf_tool *tool, process_auxtrace_t fn,
+ size_t snapshot_size)
+{
+ return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
+}
+
/**
* struct auxtrace_cache - hash table to implement a cache
* @hashtable: the hashtable
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 8c6cbb1..c2c677e 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -276,6 +276,10 @@ struct auxtrace_mmap_params {
* @info_priv_size: return the size of the private data in auxtrace_info_event
* @info_fill: fill-in the private data in auxtrace_info_event
* @free: free this auxtrace record structure
+ * @snapshot_start: starting a snapshot
+ * @snapshot_finish: finishing a snapshot
+ * @find_snapshot: find data to snapshot within auxtrace mmap
+ * @parse_snapshot_options: parse snapshot options
* @reference: provide a 64-bit reference number for auxtrace_event
* @read_finish: called after reading from an auxtrace mmap
*/
@@ -289,12 +293,36 @@ struct auxtrace_record {
struct auxtrace_info_event *auxtrace_info,
size_t priv_size);
void (*free)(struct auxtrace_record *itr);
+ int (*snapshot_start)(struct auxtrace_record *itr);
+ int (*snapshot_finish)(struct auxtrace_record *itr);
+ int (*find_snapshot)(struct auxtrace_record *itr, int idx,
+ struct auxtrace_mmap *mm, unsigned char *data,
+ u64 *head, u64 *old);
+ int (*parse_snapshot_options)(struct auxtrace_record *itr,
+ struct record_opts *opts,
+ const char *str);
u64 (*reference)(struct auxtrace_record *itr);
int (*read_finish)(struct auxtrace_record *itr, int idx);
};
#ifdef HAVE_AUXTRACE_SUPPORT
+/*
+ * In snapshot mode the mmapped page is read-only which makes using
+ * __sync_val_compare_and_swap() problematic. However, snapshot mode expects
+ * the buffer is not updated while the snapshot is made (e.g. Intel PT disables
+ * the event) so there is not a race anyway.
+ */
+static inline u64 auxtrace_mmap__read_snapshot_head(struct auxtrace_mmap *mm)
+{
+ struct perf_event_mmap_page *pc = mm->userpg;
+ u64 head = ACCESS_ONCE(pc->aux_head);
+
+ /* Ensure all reads are done after we read the head */
+ rmb();
+ return head;
+}
+
static inline u64 auxtrace_mmap__read_head(struct auxtrace_mmap *mm)
{
struct perf_event_mmap_page *pc = mm->userpg;
@@ -346,6 +374,11 @@ typedef int (*process_auxtrace_t)(struct perf_tool *tool,
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn);
+int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
+ struct auxtrace_record *itr,
+ struct perf_tool *tool, process_auxtrace_t fn,
+ size_t snapshot_size);
+
int auxtrace_queues__init(struct auxtrace_queues *queues);
int auxtrace_queues__add_event(struct auxtrace_queues *queues,
struct perf_session *session,
@@ -383,6 +416,9 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
int *err);
+int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
+ struct record_opts *opts,
+ const char *str);
int auxtrace_record__options(struct auxtrace_record *itr,
struct perf_evlist *evlist,
struct record_opts *opts);
@@ -392,6 +428,11 @@ int auxtrace_record__info_fill(struct auxtrace_record *itr,
struct auxtrace_info_event *auxtrace_info,
size_t priv_size);
void auxtrace_record__free(struct auxtrace_record *itr);
+int auxtrace_record__snapshot_start(struct auxtrace_record *itr);
+int auxtrace_record__snapshot_finish(struct auxtrace_record *itr);
+int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
+ struct auxtrace_mmap *mm,
+ unsigned char *data, u64 *head, u64 *old);
u64 auxtrace_record__reference(struct auxtrace_record *itr);
int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 09/25] perf record: Add AUX area tracing Snapshot Mode support
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (8 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Namhyung Kim, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian.hunter@intel.com>
Add a new option and support for Instruction Tracing Snapshot Mode.
When the new option is selected, no AUX area tracing data is captured
until a signal (SIGUSR2) is received.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-10-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-record.txt | 7 ++
tools/perf/builtin-record.c | 144 ++++++++++++++++++++++++++-----
tools/perf/util/auxtrace.h | 11 +++
tools/perf/util/parse-options.h | 4 +
4 files changed, 145 insertions(+), 21 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 76a141e..57dd57b 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -259,6 +259,13 @@ records. See clock_gettime(). In particular CLOCK_MONOTONIC and
CLOCK_MONOTONIC_RAW are supported, some events might also allow
CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
+-S::
+--snapshot::
+Select AUX area tracing Snapshot Mode. This option is valid only with an
+AUX area tracing event. Optionally the number of bytes to capture per
+snapshot can be specified. In Snapshot Mode, trace data is captured only when
+signal SIGUSR2 is received.
+
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index dbb2c02..5dfe913 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -112,6 +112,32 @@ out:
return rc;
}
+static volatile int done;
+static volatile int signr = -1;
+static volatile int child_finished;
+static volatile int auxtrace_snapshot_enabled;
+static volatile int auxtrace_snapshot_err;
+static volatile int auxtrace_record__snapshot_started;
+
+static void sig_handler(int sig)
+{
+ if (sig == SIGCHLD)
+ child_finished = 1;
+ else
+ signr = sig;
+
+ done = 1;
+}
+
+static void record__sig_exit(void)
+{
+ if (signr == -1)
+ return;
+
+ signal(signr, SIG_DFL);
+ raise(signr);
+}
+
#ifdef HAVE_AUXTRACE_SUPPORT
static int record__process_auxtrace(struct perf_tool *tool,
@@ -167,6 +193,56 @@ static int record__auxtrace_mmap_read(struct record *rec,
return 0;
}
+static int record__auxtrace_mmap_read_snapshot(struct record *rec,
+ struct auxtrace_mmap *mm)
+{
+ int ret;
+
+ ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
+ record__process_auxtrace,
+ rec->opts.auxtrace_snapshot_size);
+ if (ret < 0)
+ return ret;
+
+ if (ret)
+ rec->samples++;
+
+ return 0;
+}
+
+static int record__auxtrace_read_snapshot_all(struct record *rec)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < rec->evlist->nr_mmaps; i++) {
+ struct auxtrace_mmap *mm =
+ &rec->evlist->mmap[i].auxtrace_mmap;
+
+ if (!mm->base)
+ continue;
+
+ if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
+ rc = -1;
+ goto out;
+ }
+ }
+out:
+ return rc;
+}
+
+static void record__read_auxtrace_snapshot(struct record *rec)
+{
+ pr_debug("Recording AUX area tracing snapshot\n");
+ if (record__auxtrace_read_snapshot_all(rec) < 0) {
+ auxtrace_snapshot_err = -1;
+ } else {
+ auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);
+ if (!auxtrace_snapshot_err)
+ auxtrace_snapshot_enabled = 1;
+ }
+}
+
#else
static inline
@@ -176,31 +252,19 @@ int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
return 0;
}
-#endif
-
-static volatile int done = 0;
-static volatile int signr = -1;
-static volatile int child_finished = 0;
-
-static void sig_handler(int sig)
+static inline
+void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
{
- if (sig == SIGCHLD)
- child_finished = 1;
- else
- signr = sig;
-
- done = 1;
}
-static void record__sig_exit(void)
+static inline
+int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
{
- if (signr == -1)
- return;
-
- signal(signr, SIG_DFL);
- raise(signr);
+ return 0;
}
+#endif
+
static int record__open(struct record *rec)
{
char msg[512];
@@ -238,7 +302,8 @@ try_again:
}
if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
- opts->auxtrace_mmap_pages, false) < 0) {
+ opts->auxtrace_mmap_pages,
+ opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
pr_err("Permission error mapping pages.\n"
"Consider increasing "
@@ -349,7 +414,7 @@ static int record__mmap_read_all(struct record *rec)
}
}
- if (mm->base &&
+ if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
record__auxtrace_mmap_read(rec, mm) != 0) {
rc = -1;
goto out;
@@ -404,6 +469,8 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
child_finished = 1;
}
+static void snapshot_sig_handler(int sig);
+
static int __cmd_record(struct record *rec, int argc, const char **argv)
{
int err;
@@ -424,6 +491,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
+ if (rec->opts.auxtrace_snapshot_mode)
+ signal(SIGUSR2, snapshot_sig_handler);
+ else
+ signal(SIGUSR2, SIG_IGN);
session = perf_session__new(file, false, tool);
if (session == NULL) {
@@ -563,14 +634,27 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
perf_evlist__enable(rec->evlist);
}
+ auxtrace_snapshot_enabled = 1;
for (;;) {
int hits = rec->samples;
if (record__mmap_read_all(rec) < 0) {
+ auxtrace_snapshot_enabled = 0;
err = -1;
goto out_child;
}
+ if (auxtrace_record__snapshot_started) {
+ auxtrace_record__snapshot_started = 0;
+ if (!auxtrace_snapshot_err)
+ record__read_auxtrace_snapshot(rec);
+ if (auxtrace_snapshot_err) {
+ pr_err("AUX area tracing snapshot failed\n");
+ err = -1;
+ goto out_child;
+ }
+ }
+
if (hits == rec->samples) {
if (done || draining)
break;
@@ -593,10 +677,12 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
* disable events in this case.
*/
if (done && !disabled && !target__none(&opts->target)) {
+ auxtrace_snapshot_enabled = 0;
perf_evlist__disable(rec->evlist);
disabled = true;
}
}
+ auxtrace_snapshot_enabled = 0;
if (forks && workload_exec_errno) {
char msg[STRERR_BUFSIZE];
@@ -1068,6 +1154,8 @@ struct option __record_options[] = {
OPT_CALLBACK('k', "clockid", &record.opts,
"clockid", "clockid to use for events, see clock_gettime()",
parse_clockid),
+ OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
+ "opts", "AUX area tracing Snapshot Mode", ""),
OPT_END()
};
@@ -1102,6 +1190,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
return err;
}
+ err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
+ rec->opts.auxtrace_snapshot_opts);
+ if (err)
+ return err;
+
err = -ENOMEM;
symbol__init(NULL);
@@ -1165,3 +1258,12 @@ out_symbol_exit:
auxtrace_record__free(rec->itr);
return err;
}
+
+static void snapshot_sig_handler(int sig __maybe_unused)
+{
+ if (!auxtrace_snapshot_enabled)
+ return;
+ auxtrace_snapshot_enabled = 0;
+ auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);
+ auxtrace_record__snapshot_started = 1;
+}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index c2c677e..a171abb 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -564,6 +564,17 @@ int itrace_parse_synth_opts(const struct option *opt __maybe_unused,
}
static inline
+int auxtrace_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
+ struct record_opts *opts __maybe_unused,
+ const char *str)
+{
+ if (!str)
+ return 0;
+ pr_err("AUX area tracing not supported\n");
+ return -EINVAL;
+}
+
+static inline
int auxtrace__process_event(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 59561fd..367d8b8 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -123,6 +123,10 @@ struct option {
#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
+#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
+ { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
+ .value = check_vtype(v, const char **), (a), .help = (h), \
+ .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
#define OPT_DATE(s, l, v, h) \
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 10/25] perf probe: Allow to use filter on --del command
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (9 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Masami Hiramatsu, David Ahern, Jiri Olsa,
Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
This makes perf-probe --del option to accept filter rules
not only simple glob pattern. This simplifies the code and
improve the flexibility.
E.g. if we remove 2 different pattern events, we need 2
-d options.
----
# ./perf probe -d vfs\* -d malloc
Removed event: probe_libc:malloc
Removed event: probe:vfs_read
----
This allows you to joint the 2 patterns with '|'.
----
# ./perf probe -d 'vfs*|malloc'
Removed event: probe:vfs_read
Removed event: probe_libc:malloc
----
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150505022948.23399.4197.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-probe.c | 16 +++----
tools/perf/util/probe-event.c | 102 +++++++++++++-----------------------------
tools/perf/util/probe-event.h | 2 +-
3 files changed, 39 insertions(+), 81 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index feca316..1f41b4e 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -55,12 +55,12 @@ static struct {
bool show_ext_vars;
bool show_funcs;
bool mod_events;
+ bool del_events;
bool uprobes;
bool quiet;
bool target_used;
int nevents;
struct perf_probe_event events[MAX_PROBES];
- struct strlist *dellist;
struct line_range line_range;
char *target;
int max_probe_points;
@@ -195,10 +195,8 @@ static int opt_del_probe_event(const struct option *opt __maybe_unused,
const char *str, int unset __maybe_unused)
{
if (str) {
- params.mod_events = true;
- if (!params.dellist)
- params.dellist = strlist__new(true, NULL);
- strlist__add(params.dellist, str);
+ params.del_events = true;
+ return params_add_filter(str);
}
return 0;
}
@@ -313,8 +311,6 @@ static void cleanup_params(void)
for (i = 0; i < params.nevents; i++)
clear_perf_probe_event(params.events + i);
- if (params.dellist)
- strlist__delete(params.dellist);
line_range__clear(¶ms.line_range);
free(params.target);
if (params.filter)
@@ -454,7 +450,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (params.max_probe_points == 0)
params.max_probe_points = MAX_PROBES;
- if ((!params.nevents && !params.dellist && !params.list_events &&
+ if ((!params.nevents && !params.del_events && !params.list_events &&
!params.show_lines && !params.show_funcs))
usage_with_options(probe_usage, options);
@@ -514,8 +510,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
}
#endif
- if (params.dellist) {
- ret = del_perf_probe_events(params.dellist);
+ if (params.del_events) {
+ ret = del_perf_probe_events(params.filter);
if (ret < 0) {
pr_err_with_code(" Error: Failed to delete events.", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5995d81..abf5845 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2734,40 +2734,39 @@ error:
return ret;
}
-static int del_trace_probe_event(int fd, const char *buf,
- struct strlist *namelist)
+static int del_trace_probe_events(int fd, struct strfilter *filter,
+ struct strlist *namelist)
{
- struct str_node *ent, *n;
+ struct str_node *ent;
+ const char *p;
int ret = -ENOENT;
- if (strpbrk(buf, "*?")) { /* Glob-exp */
- strlist__for_each_safe(ent, n, namelist)
- if (strglobmatch(ent->s, buf)) {
- ret = __del_trace_probe_event(fd, ent);
- if (ret < 0)
- break;
- strlist__remove(namelist, ent);
- }
- } else {
- ent = strlist__find(namelist, buf);
- if (ent) {
+ if (!namelist)
+ return -ENOENT;
+
+ strlist__for_each(ent, namelist) {
+ p = strchr(ent->s, ':');
+ if ((p && strfilter__compare(filter, p + 1)) ||
+ strfilter__compare(filter, ent->s)) {
ret = __del_trace_probe_event(fd, ent);
- if (ret >= 0)
- strlist__remove(namelist, ent);
+ if (ret < 0)
+ break;
}
}
return ret;
}
-int del_perf_probe_events(struct strlist *dellist)
+int del_perf_probe_events(struct strfilter *filter)
{
- int ret = -1, ret2, ufd = -1, kfd = -1;
- char buf[128];
- const char *group, *event;
- char *p, *str;
- struct str_node *ent;
+ int ret, ret2, ufd = -1, kfd = -1;
struct strlist *namelist = NULL, *unamelist = NULL;
+ char *str = strfilter__string(filter);
+
+ if (!str)
+ return -EINVAL;
+
+ pr_debug("Delete filter: \'%s\'\n", str);
/* Get current event names */
kfd = open_kprobe_events(true);
@@ -2780,59 +2779,21 @@ int del_perf_probe_events(struct strlist *dellist)
if (kfd < 0 && ufd < 0) {
print_both_open_warning(kfd, ufd);
+ ret = kfd;
goto error;
}
- if (namelist == NULL && unamelist == NULL) {
- ret = -ENOENT;
+ ret = del_trace_probe_events(kfd, filter, namelist);
+ if (ret < 0 && ret != -ENOENT)
goto error;
- }
-
- strlist__for_each(ent, dellist) {
- str = strdup(ent->s);
- if (str == NULL) {
- ret = -ENOMEM;
- goto error;
- }
- pr_debug("Parsing: %s\n", str);
- p = strchr(str, ':');
- if (p) {
- group = str;
- *p = '\0';
- event = p + 1;
- } else {
- group = "*";
- event = str;
- }
- if (event && *event == '.')
- event++;
-
- ret = e_snprintf(buf, 128, "%s:%s", group, event);
- if (ret < 0) {
- pr_err("Failed to copy event.");
- free(str);
- goto error;
- }
-
- pr_debug("Group: %s, Event: %s\n", group, event);
- free(str);
-
- ret = ret2 = -ENOENT;
- if (namelist)
- ret = del_trace_probe_event(kfd, buf, namelist);
-
- if ((ret >= 0 || ret == -ENOENT) && unamelist)
- ret2 = del_trace_probe_event(ufd, buf, unamelist);
-
- /* Since we can remove probes which already removed, don't check it */
- if (ret == -ENOENT && ret2 == -ENOENT)
- pr_debug("Event \"%s\" does not exist.\n", buf);
- else if (ret < 0 || ret2 < 0) {
- if (ret >= 0)
- ret = ret2;
- break;
- }
+ ret2 = del_trace_probe_events(ufd, filter, unamelist);
+ if (ret2 < 0 && ret2 != -ENOENT)
+ ret = ret2;
+ else if (ret == -ENOENT && ret2 == -ENOENT) {
+ pr_debug("\"%s\" does not hit any event.\n", str);
+ /* Note that this is silently ignored */
+ ret = 0;
}
error:
@@ -2845,6 +2806,7 @@ error:
strlist__delete(unamelist);
close(ufd);
}
+ free(str);
return ret;
}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index ec13362..e10aedc 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -126,7 +126,7 @@ extern const char *kernel_get_module_path(const char *module);
extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
int max_probe_points, bool force_add);
-extern int del_perf_probe_events(struct strlist *dellist);
+extern int del_perf_probe_events(struct strfilter *filter);
extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 11/25] perf probe: Accept filter argument for --funcs
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (10 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Masami Hiramatsu, David Ahern, Jiri Olsa,
Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
This allows the user to pass the filter pattern directly to the --funcs
option as below:
----
# ./perf probe -F *kmalloc
__kmalloc
devm_kmalloc
mempool_kmalloc
sg_kmalloc
sock_kmalloc
----
We previously needed to use the --filter option for that.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150505022950.23399.22435.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-probe.txt | 3 ++-
tools/perf/builtin-probe.c | 19 ++++++++++++++-----
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index d0feb8e..a272f2e 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -84,9 +84,10 @@ OPTIONS
variables.
-F::
---funcs::
+--funcs[=FILTER]::
Show available functions in given module or kernel. With -x/--exec,
can also list functions in a user space executable / shared library.
+ This also can accept a FILTER rule argument.
--filter=FILTER::
(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 1f41b4e..5a0e8f1 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -290,6 +290,17 @@ static int opt_show_vars(const struct option *opt __maybe_unused,
return ret;
}
#endif
+static int opt_show_funcs(const struct option *opt __maybe_unused,
+ const char *str, int unset)
+{
+ if (!unset)
+ params.show_funcs = true;
+
+ if (str)
+ return params_add_filter(str);
+
+ return 0;
+}
static int opt_set_filter(const struct option *opt __maybe_unused,
const char *str, int unset __maybe_unused)
@@ -399,8 +410,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
"Set how many probe points can be found for a probe."),
- OPT_BOOLEAN('F', "funcs", ¶ms.show_funcs,
- "Show potential probe-able functions."),
+ OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
+ "Show potential probe-able functions.",
+ opt_show_funcs, DEFAULT_FUNC_FILTER),
OPT_CALLBACK('\0', "filter", NULL,
"[!]FILTER", "Set a filter (with --vars/funcs only)\n"
"\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
@@ -472,9 +484,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
return ret;
}
if (params.show_funcs) {
- if (!params.filter)
- params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
- NULL);
ret = show_available_funcs(params.target, params.filter,
params.uprobes);
strfilter__delete(params.filter);
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 12/25] perf probe: Remove redundant cleanup of params.filter
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (11 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Masami Hiramatsu, David Ahern, Jiri Olsa,
Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Since params.filter will be released in cleanup_params, we don't need to
clear it in each command.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150505022952.23399.58072.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-probe.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 5a0e8f1..08c9481 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -477,8 +477,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
usage_with_options(probe_usage, options);
}
ret = show_perf_probe_events(params.filter);
- strfilter__delete(params.filter);
- params.filter = NULL;
if (ret < 0)
pr_err_with_code(" Error: Failed to show event list.", ret);
return ret;
@@ -486,8 +484,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (params.show_funcs) {
ret = show_available_funcs(params.target, params.filter,
params.uprobes);
- strfilter__delete(params.filter);
- params.filter = NULL;
if (ret < 0)
pr_err_with_code(" Error: Failed to show functions.", ret);
return ret;
@@ -511,8 +507,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
params.target,
params.filter,
params.show_ext_vars);
- strfilter__delete(params.filter);
- params.filter = NULL;
if (ret < 0)
pr_err_with_code(" Error: Failed to show vars.", ret);
return ret;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 13/25] perf probe: Cleanup and consolidate command parsers
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (12 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Masami Hiramatsu, David Ahern, Jiri Olsa,
Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
To simplify the 'perf probe' command code, consolidate some similar
functions and use command short-name for command classification, instead
of separate booleans.
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150505152257.18790.41548.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-probe.c | 110 +++++++++++++++++----------------------------
1 file changed, 42 insertions(+), 68 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 08c9481..53d475b 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -48,14 +48,10 @@
/* Session management structure */
static struct {
+ int command; /* Command short_name */
bool list_events;
bool force_add;
- bool show_lines;
- bool show_vars;
bool show_ext_vars;
- bool show_funcs;
- bool mod_events;
- bool del_events;
bool uprobes;
bool quiet;
bool target_used;
@@ -175,44 +171,11 @@ static int parse_probe_event_argv(int argc, const char **argv)
len += sprintf(&buf[len], "%s ", argv[i]);
}
- params.mod_events = true;
ret = parse_probe_event(buf);
free(buf);
return ret;
}
-static int opt_add_probe_event(const struct option *opt __maybe_unused,
- const char *str, int unset __maybe_unused)
-{
- if (str) {
- params.mod_events = true;
- return parse_probe_event(str);
- } else
- return 0;
-}
-
-static int opt_del_probe_event(const struct option *opt __maybe_unused,
- const char *str, int unset __maybe_unused)
-{
- if (str) {
- params.del_events = true;
- return params_add_filter(str);
- }
- return 0;
-}
-
-static int opt_list_probe_event(const struct option *opt __maybe_unused,
- const char *str, int unset)
-{
- if (!unset)
- params.list_events = true;
-
- if (str)
- return params_add_filter(str);
-
- return 0;
-}
-
static int opt_set_target(const struct option *opt, const char *str,
int unset __maybe_unused)
{
@@ -250,8 +213,10 @@ static int opt_set_target(const struct option *opt, const char *str,
return ret;
}
+/* Command option callbacks */
+
#ifdef HAVE_DWARF_SUPPORT
-static int opt_show_lines(const struct option *opt __maybe_unused,
+static int opt_show_lines(const struct option *opt,
const char *str, int unset __maybe_unused)
{
int ret = 0;
@@ -259,19 +224,19 @@ static int opt_show_lines(const struct option *opt __maybe_unused,
if (!str)
return 0;
- if (params.show_lines) {
+ if (params.command == 'L') {
pr_warning("Warning: more than one --line options are"
" detected. Only the first one is valid.\n");
return 0;
}
- params.show_lines = true;
+ params.command = opt->short_name;
ret = parse_line_range_desc(str, ¶ms.line_range);
return ret;
}
-static int opt_show_vars(const struct option *opt __maybe_unused,
+static int opt_show_vars(const struct option *opt,
const char *str, int unset __maybe_unused)
{
struct perf_probe_event *pev = ¶ms.events[params.nevents];
@@ -285,16 +250,27 @@ static int opt_show_vars(const struct option *opt __maybe_unused,
pr_err(" Error: '--vars' doesn't accept arguments.\n");
return -EINVAL;
}
- params.show_vars = true;
+ params.command = opt->short_name;
return ret;
}
#endif
-static int opt_show_funcs(const struct option *opt __maybe_unused,
- const char *str, int unset)
+static int opt_add_probe_event(const struct option *opt,
+ const char *str, int unset __maybe_unused)
+{
+ if (str) {
+ params.command = opt->short_name;
+ return parse_probe_event(str);
+ }
+
+ return 0;
+}
+
+static int opt_set_filter_with_command(const struct option *opt,
+ const char *str, int unset)
{
if (!unset)
- params.show_funcs = true;
+ params.command = opt->short_name;
if (str)
return params_add_filter(str);
@@ -360,10 +336,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN('q', "quiet", ¶ms.quiet,
"be quiet (do not show any mesages)"),
OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
- "list up probe events", opt_list_probe_event,
- DEFAULT_LIST_FILTER),
+ "list up probe events",
+ opt_set_filter_with_command, DEFAULT_LIST_FILTER),
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
- opt_del_probe_event),
+ opt_set_filter_with_command),
OPT_CALLBACK('a', "add", NULL,
#ifdef HAVE_DWARF_SUPPORT
"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
@@ -412,7 +388,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"Set how many probe points can be found for a probe."),
OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
"Show potential probe-able functions.",
- opt_show_funcs, DEFAULT_FUNC_FILTER),
+ opt_set_filter_with_command, DEFAULT_FUNC_FILTER),
OPT_CALLBACK('\0', "filter", NULL,
"[!]FILTER", "Set a filter (with --vars/funcs only)\n"
"\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
@@ -444,11 +420,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
pr_warning(" Error: '-' is not supported.\n");
usage_with_options(probe_usage, options);
}
+ if (params.command && params.command != 'a') {
+ pr_warning(" Error: another command except --add is set.\n");
+ usage_with_options(probe_usage, options);
+ }
ret = parse_probe_event_argv(argc, argv);
if (ret < 0) {
pr_err_with_code(" Error: Command Parse Error.", ret);
return ret;
}
+ params.command = 'a';
}
if (params.quiet) {
@@ -462,16 +443,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (params.max_probe_points == 0)
params.max_probe_points = MAX_PROBES;
- if ((!params.nevents && !params.del_events && !params.list_events &&
- !params.show_lines && !params.show_funcs))
- usage_with_options(probe_usage, options);
-
/*
* Only consider the user's kernel image path if given.
*/
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
- if (params.list_events) {
+ switch (params.command) {
+ case 'l':
if (params.uprobes) {
pr_warning(" Error: Don't use --list with --exec.\n");
usage_with_options(probe_usage, options);
@@ -480,24 +458,20 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (ret < 0)
pr_err_with_code(" Error: Failed to show event list.", ret);
return ret;
- }
- if (params.show_funcs) {
+ case 'F':
ret = show_available_funcs(params.target, params.filter,
params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show functions.", ret);
return ret;
- }
-
#ifdef HAVE_DWARF_SUPPORT
- if (params.show_lines) {
+ case 'L':
ret = show_line_range(¶ms.line_range, params.target,
params.uprobes);
if (ret < 0)
pr_err_with_code(" Error: Failed to show lines.", ret);
return ret;
- }
- if (params.show_vars) {
+ case 'V':
if (!params.filter)
params.filter = strfilter__new(DEFAULT_VAR_FILTER,
NULL);
@@ -510,18 +484,15 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (ret < 0)
pr_err_with_code(" Error: Failed to show vars.", ret);
return ret;
- }
#endif
-
- if (params.del_events) {
+ case 'd':
ret = del_perf_probe_events(params.filter);
if (ret < 0) {
pr_err_with_code(" Error: Failed to delete events.", ret);
return ret;
}
- }
-
- if (params.nevents) {
+ break;
+ case 'a':
/* Ensure the last given target is used */
if (params.target && !params.target_used) {
pr_warning(" Error: -x/-m must follow the probe definitions.\n");
@@ -535,6 +506,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
pr_err_with_code(" Error: Failed to add events.", ret);
return ret;
}
+ break;
+ default:
+ usage_with_options(probe_usage, options);
}
return 0;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 14/25] perf kmem: Show warning when trying to run stat without record
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Jiri Olsa, Joonsoo Kim,
Minchan Kim, Peter Zijlstra, linux-mm, Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Sometimes one can mistakenly run 'perf kmem stat' without running 'perf
kmem record' before or with a different configuration like recording
--slab and stat --page. Show a warning message like the one below to
inform the user:
# perf kmem stat --page --caller
No page allocation events found. Have you run 'perf kmem record --page'?
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Pekka Enberg <penberg@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Joonsoo Kim <js1304@gmail.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: linux-mm@kvack.org
Link: http://lkml.kernel.org/r/1430837572-31395-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-kmem.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 828b728..e628bf1 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1882,6 +1882,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
};
struct perf_session *session;
int ret = -1;
+ const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
perf_config(kmem_config, NULL);
argc = parse_options_subcommand(argc, argv, kmem_options,
@@ -1908,11 +1909,21 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
if (session == NULL)
return -1;
+ if (kmem_slab) {
+ if (!perf_evlist__find_tracepoint_by_name(session->evlist,
+ "kmem:kmalloc")) {
+ pr_err(errmsg, "slab", "slab");
+ return -1;
+ }
+ }
+
if (kmem_page) {
- struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+ struct perf_evsel *evsel;
- if (evsel == NULL || evsel->tp_format == NULL) {
- pr_err("invalid event found.. aborting\n");
+ evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
+ "kmem:mm_page_alloc");
+ if (evsel == NULL) {
+ pr_err(errmsg, "page", "page");
return -1;
}
--
2.1.0
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 14/25] perf kmem: Show warning when trying to run stat without record
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Jiri Olsa, Joonsoo Kim,
Minchan Kim, Peter Zijlstra, linux-mm, Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Sometimes one can mistakenly run 'perf kmem stat' without running 'perf
kmem record' before or with a different configuration like recording
--slab and stat --page. Show a warning message like the one below to
inform the user:
# perf kmem stat --page --caller
No page allocation events found. Have you run 'perf kmem record --page'?
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Pekka Enberg <penberg@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Joonsoo Kim <js1304@gmail.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: linux-mm@kvack.org
Link: http://lkml.kernel.org/r/1430837572-31395-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-kmem.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 828b728..e628bf1 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1882,6 +1882,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
};
struct perf_session *session;
int ret = -1;
+ const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
perf_config(kmem_config, NULL);
argc = parse_options_subcommand(argc, argv, kmem_options,
@@ -1908,11 +1909,21 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
if (session == NULL)
return -1;
+ if (kmem_slab) {
+ if (!perf_evlist__find_tracepoint_by_name(session->evlist,
+ "kmem:kmalloc")) {
+ pr_err(errmsg, "slab", "slab");
+ return -1;
+ }
+ }
+
if (kmem_page) {
- struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+ struct perf_evsel *evsel;
- if (evsel == NULL || evsel->tp_format == NULL) {
- pr_err("invalid event found.. aborting\n");
+ evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
+ "kmem:mm_page_alloc");
+ if (evsel == NULL) {
+ pr_err(errmsg, "page", "page");
return -1;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 15/25] perf tools: Move TUI-specific fields into unnamed union
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (14 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Since perf diff only supports stdio output, TUI fields are only accessed
from perf report (or perf top). So add a new unnamed union and move
struct hist_entry_tui and those TUI-specific fields.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/sort.h | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index de3303f..7f0c0a8 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -93,18 +93,24 @@ struct hist_entry {
s32 cpu;
u8 cpumode;
- struct hist_entry_diff diff;
-
/* We are added by hists__add_dummy_entry. */
bool dummy;
- /* XXX These two should move to some tree widget lib */
- u16 row_offset;
- u16 nr_rows;
-
bool init_have_children;
char level;
u8 filtered;
+ union {
+ /*
+ * Since perf diff only supports the stdio output, TUI
+ * fields are only accessed from perf report (or perf
+ * top). So make it an union to reduce memory usage.
+ */
+ struct hist_entry_diff diff;
+ struct /* for TUI */ {
+ u16 row_offset;
+ u16 nr_rows;
+ };
+ };
char *srcline;
struct symbol *parent;
struct rb_root sorted_chain;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 16/25] perf tools: Move init_have_children field to the unnamed union
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (15 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The init_have_children is used to init callchain info only for TUI. So
it'd be better to move it to the TUI-specific unnamed union member.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-3-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/sort.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7f0c0a8..4d923e6 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -96,7 +96,6 @@ struct hist_entry {
/* We are added by hists__add_dummy_entry. */
bool dummy;
- bool init_have_children;
char level;
u8 filtered;
union {
@@ -109,6 +108,7 @@ struct hist_entry {
struct /* for TUI */ {
u16 row_offset;
u16 nr_rows;
+ bool init_have_children;
};
};
char *srcline;
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 17/25] perf hists browser: Fix possible memory leak
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (16 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The options array saves strings for each popup menu item. The number of
items can be vary according to the currently selected item. So it can
leak some memory if it's exited from a small item. Fix it by freeing
all items when loop terminates.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-4-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 995b7a8..0972d47 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1424,7 +1424,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct hist_browser *browser = hist_browser__new(hists);
struct branch_info *bi;
struct pstack *fstack;
- char *options[16];
+#define MAX_OPTIONS 16
+ char *options[MAX_OPTIONS];
int nr_options = 0;
int key = -1;
char buf[64];
@@ -1691,7 +1692,8 @@ skip_annotation:
"Switch to another data file in PWD") > 0)
switch_data = nr_options++;
add_exit_option:
- options[nr_options++] = (char *)"Exit";
+ if (asprintf(&options[nr_options], "Exit") > 0)
+ nr_options++;
retry_popup_menu:
choice = ui__popup_menu(nr_options, options);
@@ -1812,7 +1814,7 @@ out_free_stack:
pstack__delete(fstack);
out:
hist_browser__delete(browser);
- free_popup_options(options, nr_options - 1);
+ free_popup_options(options, MAX_OPTIONS);
return key;
}
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 18/25] perf hists browser: Save hist_browser_timer pointer in hist_browser
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (17 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The struct hist_browser_timer is to carry perf-top related info
throughout the hist browser code. So it'd be better to keep in the
struct hist_browser. This is a preparation to later change.
Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-5-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 0972d47..0847623 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -25,6 +25,7 @@ struct hist_browser {
struct hists *hists;
struct hist_entry *he_selection;
struct map_symbol *selection;
+ struct hist_browser_timer *hbt;
int print_seq;
bool show_dso;
bool show_headers;
@@ -406,11 +407,11 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
"Or reduce the sampling frequency.");
}
-static int hist_browser__run(struct hist_browser *browser,
- struct hist_browser_timer *hbt)
+static int hist_browser__run(struct hist_browser *browser)
{
int key;
char title[160];
+ struct hist_browser_timer *hbt = browser->hbt;
int delay_secs = hbt ? hbt->refresh : 0;
browser->b.entries = &browser->hists->entries;
@@ -1195,7 +1196,8 @@ static int hist_browser__dump(struct hist_browser *browser)
return 0;
}
-static struct hist_browser *hist_browser__new(struct hists *hists)
+static struct hist_browser *hist_browser__new(struct hists *hists,
+ struct hist_browser_timer *hbt)
{
struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -1206,6 +1208,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
browser->b.seek = ui_browser__hists_seek;
browser->b.use_navkeypressed = true;
browser->show_headers = symbol_conf.show_hist_headers;
+ browser->hbt = hbt;
}
return browser;
@@ -1421,7 +1424,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct perf_session_env *env)
{
struct hists *hists = evsel__hists(evsel);
- struct hist_browser *browser = hist_browser__new(hists);
+ struct hist_browser *browser = hist_browser__new(hists, hbt);
struct branch_info *bi;
struct pstack *fstack;
#define MAX_OPTIONS 16
@@ -1499,7 +1502,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
nr_options = 0;
- key = hist_browser__run(browser, hbt);
+ key = hist_browser__run(browser);
if (browser->he_selection != NULL) {
thread = hist_browser__selected_thread(browser);
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 19/25] perf hists browser: Save pstack in the hist_browser
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (18 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The struct pstack is to save currently applied thread and/or dso filters
in the browser. So it'd be better to keep in the struct hist_browser.
This is a preparation to later change.
Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-6-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 0847623..26d5548 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -26,6 +26,7 @@ struct hist_browser {
struct hist_entry *he_selection;
struct map_symbol *selection;
struct hist_browser_timer *hbt;
+ struct pstack *pstack;
int print_seq;
bool show_dso;
bool show_headers;
@@ -1426,7 +1427,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct hists *hists = evsel__hists(evsel);
struct hist_browser *browser = hist_browser__new(hists, hbt);
struct branch_info *bi;
- struct pstack *fstack;
#define MAX_OPTIONS 16
char *options[MAX_OPTIONS];
int nr_options = 0;
@@ -1477,8 +1477,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
hist_browser__update_nr_entries(browser);
}
- fstack = pstack__new(2);
- if (fstack == NULL)
+ browser->pstack = pstack__new(2);
+ if (browser->pstack == NULL)
goto out;
ui_helpline__push(helpline);
@@ -1587,7 +1587,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
case K_LEFT: {
const void *top;
- if (pstack__empty(fstack)) {
+ if (pstack__empty(browser->pstack)) {
/*
* Go back to the perf_evsel_menu__run or other user
*/
@@ -1595,7 +1595,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto out_free_stack;
continue;
}
- top = pstack__pop(fstack);
+ top = pstack__pop(browser->pstack);
if (top == &browser->hists->dso_filter)
goto zoom_out_dso;
if (top == &browser->hists->thread_filter)
@@ -1753,7 +1753,7 @@ do_annotate:
else if (choice == zoom_dso) {
zoom_dso:
if (browser->hists->dso_filter) {
- pstack__remove(fstack, &browser->hists->dso_filter);
+ pstack__remove(browser->pstack, &browser->hists->dso_filter);
zoom_out_dso:
ui_helpline__pop();
browser->hists->dso_filter = NULL;
@@ -1765,14 +1765,14 @@ zoom_out_dso:
dso->kernel ? "the Kernel" : dso->short_name);
browser->hists->dso_filter = dso;
perf_hpp__set_elide(HISTC_DSO, true);
- pstack__push(fstack, &browser->hists->dso_filter);
+ pstack__push(browser->pstack, &browser->hists->dso_filter);
}
hists__filter_by_dso(hists);
hist_browser__reset(browser);
} else if (choice == zoom_thread) {
zoom_thread:
if (browser->hists->thread_filter) {
- pstack__remove(fstack, &browser->hists->thread_filter);
+ pstack__remove(browser->pstack, &browser->hists->thread_filter);
zoom_out_thread:
ui_helpline__pop();
thread__zput(browser->hists->thread_filter);
@@ -1783,7 +1783,7 @@ zoom_out_thread:
thread->tid);
browser->hists->thread_filter = thread__get(thread);
perf_hpp__set_elide(HISTC_THREAD, false);
- pstack__push(fstack, &browser->hists->thread_filter);
+ pstack__push(browser->pstack, &browser->hists->thread_filter);
}
hists__filter_by_thread(hists);
hist_browser__reset(browser);
@@ -1814,7 +1814,7 @@ do_data_switch:
}
}
out_free_stack:
- pstack__delete(fstack);
+ pstack__delete(browser->pstack);
out:
hist_browser__delete(browser);
free_popup_options(options, MAX_OPTIONS);
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 20/25] perf hists browser: Save perf_session_env in the hist_browser
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (19 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The perf_session_env is to save system informantion at the recording
time to be refered in the hist browser. So it'd be better to keep in
the struct hist_browser. This is a preparation to later change.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-7-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 26d5548..45704d6 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -27,6 +27,7 @@ struct hist_browser {
struct map_symbol *selection;
struct hist_browser_timer *hbt;
struct pstack *pstack;
+ struct perf_session_env *env;
int print_seq;
bool show_dso;
bool show_headers;
@@ -1198,7 +1199,8 @@ static int hist_browser__dump(struct hist_browser *browser)
}
static struct hist_browser *hist_browser__new(struct hists *hists,
- struct hist_browser_timer *hbt)
+ struct hist_browser_timer *hbt,
+ struct perf_session_env *env)
{
struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -1210,6 +1212,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists,
browser->b.use_navkeypressed = true;
browser->show_headers = symbol_conf.show_hist_headers;
browser->hbt = hbt;
+ browser->env = env;
}
return browser;
@@ -1425,7 +1428,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct perf_session_env *env)
{
struct hists *hists = evsel__hists(evsel);
- struct hist_browser *browser = hist_browser__new(hists, hbt);
+ struct hist_browser *browser = hist_browser__new(hists, hbt, env);
struct branch_info *bi;
#define MAX_OPTIONS 16
char *options[MAX_OPTIONS];
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 21/25] perf hists browser: Split popup menu actions
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (20 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Currently perf_evsel__hists_browse() function spins on a huge loop and
handles many key actions. Since it's hard to read and modify, let's
split it out into small helper functions.
This patch introduces do_XXX() functions which corresponds to each goto
label. This way we can call such functions both from key press actions
and popup menu actions.
No functional change intended.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-8-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 242 ++++++++++++++++++++++++++---------------
1 file changed, 156 insertions(+), 86 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 45704d6..7d88a1c 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1402,6 +1402,120 @@ close_file_and_continue:
return ret;
}
+static int
+do_annotate(struct hist_browser *browser, struct map_symbol *ms)
+{
+ struct perf_evsel *evsel;
+ struct annotation *notes;
+ struct hist_entry *he;
+ int err;
+
+ if (!objdump_path && perf_session_env__lookup_objdump(browser->env))
+ return 0;
+
+ notes = symbol__annotation(ms->sym);
+ if (!notes->src)
+ return 0;
+
+ evsel = hists_to_evsel(browser->hists);
+ err = map_symbol__tui_annotate(ms, evsel, browser->hbt);
+ he = hist_browser__selected_entry(browser);
+ /*
+ * offer option to annotate the other branch source or target
+ * (if they exists) when returning from annotate
+ */
+ if ((err == 'q' || err == CTRL('c')) && he->branch_info)
+ return 1;
+
+ ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
+ if (err)
+ ui_browser__handle_resize(&browser->b);
+ return 0;
+}
+
+static int
+do_zoom_thread(struct hist_browser *browser, struct thread *thread)
+{
+ if (browser->hists->thread_filter) {
+ pstack__remove(browser->pstack, &browser->hists->thread_filter);
+ perf_hpp__set_elide(HISTC_THREAD, false);
+ thread__zput(browser->hists->thread_filter);
+ ui_helpline__pop();
+ } else {
+ ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
+ thread->comm_set ? thread__comm_str(thread) : "",
+ thread->tid);
+ browser->hists->thread_filter = thread__get(thread);
+ perf_hpp__set_elide(HISTC_THREAD, false);
+ pstack__push(browser->pstack, &browser->hists->thread_filter);
+ }
+
+ hists__filter_by_thread(browser->hists);
+ hist_browser__reset(browser);
+ return 0;
+}
+
+static int
+do_zoom_dso(struct hist_browser *browser, struct dso *dso)
+{
+ if (browser->hists->dso_filter) {
+ pstack__remove(browser->pstack, &browser->hists->dso_filter);
+ perf_hpp__set_elide(HISTC_DSO, false);
+ browser->hists->dso_filter = NULL;
+ ui_helpline__pop();
+ } else {
+ if (dso == NULL)
+ return 0;
+ ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
+ dso->kernel ? "the Kernel" : dso->short_name);
+ browser->hists->dso_filter = dso;
+ perf_hpp__set_elide(HISTC_DSO, true);
+ pstack__push(browser->pstack, &browser->hists->dso_filter);
+ }
+
+ hists__filter_by_dso(browser->hists);
+ hist_browser__reset(browser);
+ return 0;
+}
+
+static int
+do_browse_map(struct hist_browser *browser __maybe_unused, struct map *map)
+{
+ map__browse(map);
+ return 0;
+}
+
+static int
+do_run_script(struct hist_browser *browser __maybe_unused,
+ struct thread *thread, struct symbol *sym)
+{
+ char script_opt[64];
+ memset(script_opt, 0, sizeof(script_opt));
+
+ if (thread) {
+ scnprintf(script_opt, sizeof(script_opt), " -c %s ",
+ thread__comm_str(thread));
+ } else if (sym) {
+ scnprintf(script_opt, sizeof(script_opt), " -S %s ",
+ sym->name);
+ }
+
+ script_browse(script_opt);
+ return 0;
+}
+
+static int
+do_switch_data(struct hist_browser *browser __maybe_unused, int key)
+{
+ if (switch_data_file()) {
+ ui__warning("Won't switch the data files due to\n"
+ "no valid data file get selected!\n");
+ return key;
+ }
+
+ return K_SWITCH_INPUT_DATA;
+}
+
static void hist_browser__update_nr_entries(struct hist_browser *hb)
{
u64 nr_entries = 0;
@@ -1435,7 +1549,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
int nr_options = 0;
int key = -1;
char buf[64];
- char script_opt[64];
int delay_secs = hbt ? hbt->refresh : 0;
struct perf_hpp_fmt *fmt;
@@ -1496,7 +1609,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
while (1) {
struct thread *thread = NULL;
- const struct dso *dso = NULL;
+ struct dso *dso = NULL;
+ struct map_symbol ms;
int choice = 0,
annotate = -2, zoom_dso = -2, zoom_thread = -2,
annotate_f = -2, annotate_t = -2, browse_map = -2;
@@ -1533,17 +1647,24 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
browser->selection->sym == NULL ||
browser->selection->map->dso->annotate_warned)
continue;
- goto do_annotate;
+
+ ms.map = browser->selection->map;
+ ms.sym = browser->selection->sym;
+
+ do_annotate(browser, &ms);
+ continue;
case 'P':
hist_browser__dump(browser);
continue;
case 'd':
- goto zoom_dso;
+ do_zoom_dso(browser, dso);
+ continue;
case 'V':
browser->show_dso = !browser->show_dso;
continue;
case 't':
- goto zoom_thread;
+ do_zoom_thread(browser, thread);
+ continue;
case '/':
if (ui_browser__input_window("Symbol to show",
"Please enter the name of symbol you want to see",
@@ -1556,11 +1677,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
continue;
case 'r':
if (is_report_browser(hbt))
- goto do_scripts;
+ do_run_script(browser, NULL, NULL);
continue;
case 's':
- if (is_report_browser(hbt))
- goto do_data_switch;
+ if (is_report_browser(hbt)) {
+ key = do_switch_data(browser, key);
+ if (key == K_SWITCH_INPUT_DATA)
+ goto out_free_stack;
+ }
continue;
case 'i':
/* env->arch is NULL for live-mode (i.e. perf top) */
@@ -1599,10 +1723,18 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
continue;
}
top = pstack__pop(browser->pstack);
- if (top == &browser->hists->dso_filter)
- goto zoom_out_dso;
- if (top == &browser->hists->thread_filter)
- goto zoom_out_thread;
+ if (top == &browser->hists->dso_filter) {
+ perf_hpp__set_elide(HISTC_DSO, false);
+ browser->hists->dso_filter = NULL;
+ hists__filter_by_dso(browser->hists);
+ }
+ if (top == &browser->hists->thread_filter) {
+ perf_hpp__set_elide(HISTC_THREAD, false);
+ thread__zput(browser->hists->thread_filter);
+ hists__filter_by_thread(browser->hists);
+ }
+ ui_helpline__pop();
+ hist_browser__reset(browser);
continue;
}
case K_ESC:
@@ -1713,12 +1845,6 @@ retry_popup_menu:
if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he;
- struct annotation *notes;
- struct map_symbol ms;
- int err;
-do_annotate:
- if (!objdump_path && perf_session_env__lookup_objdump(env))
- continue;
he = hist_browser__selected_entry(browser);
if (he == NULL)
@@ -1734,86 +1860,30 @@ do_annotate:
ms = *browser->selection;
}
- notes = symbol__annotation(ms.sym);
- if (!notes->src)
- continue;
-
- err = map_symbol__tui_annotate(&ms, evsel, hbt);
- /*
- * offer option to annotate the other branch source or target
- * (if they exists) when returning from annotate
- */
- if ((err == 'q' || err == CTRL('c'))
- && annotate_t != -2 && annotate_f != -2)
+ if (do_annotate(browser, &ms) == 1)
goto retry_popup_menu;
-
- ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
- if (err)
- ui_browser__handle_resize(&browser->b);
-
- } else if (choice == browse_map)
- map__browse(browser->selection->map);
- else if (choice == zoom_dso) {
-zoom_dso:
- if (browser->hists->dso_filter) {
- pstack__remove(browser->pstack, &browser->hists->dso_filter);
-zoom_out_dso:
- ui_helpline__pop();
- browser->hists->dso_filter = NULL;
- perf_hpp__set_elide(HISTC_DSO, false);
- } else {
- if (dso == NULL)
- continue;
- ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
- dso->kernel ? "the Kernel" : dso->short_name);
- browser->hists->dso_filter = dso;
- perf_hpp__set_elide(HISTC_DSO, true);
- pstack__push(browser->pstack, &browser->hists->dso_filter);
- }
- hists__filter_by_dso(hists);
- hist_browser__reset(browser);
+ } else if (choice == browse_map) {
+ do_browse_map(browser, browser->selection->map);
+ } else if (choice == zoom_dso) {
+ do_zoom_dso(browser, dso);
} else if (choice == zoom_thread) {
-zoom_thread:
- if (browser->hists->thread_filter) {
- pstack__remove(browser->pstack, &browser->hists->thread_filter);
-zoom_out_thread:
- ui_helpline__pop();
- thread__zput(browser->hists->thread_filter);
- perf_hpp__set_elide(HISTC_THREAD, false);
- } else {
- ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
- thread->comm_set ? thread__comm_str(thread) : "",
- thread->tid);
- browser->hists->thread_filter = thread__get(thread);
- perf_hpp__set_elide(HISTC_THREAD, false);
- pstack__push(browser->pstack, &browser->hists->thread_filter);
- }
- hists__filter_by_thread(hists);
- hist_browser__reset(browser);
+ do_zoom_thread(browser, thread);
}
/* perf scripts support */
else if (choice == scripts_all || choice == scripts_comm ||
choice == scripts_symbol) {
-do_scripts:
- memset(script_opt, 0, 64);
-
if (choice == scripts_comm)
- sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread));
-
+ do_run_script(browser, browser->he_selection->thread, NULL);
if (choice == scripts_symbol)
- sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
-
- script_browse(script_opt);
+ do_run_script(browser, NULL, browser->he_selection->ms.sym);
+ if (choice == scripts_all)
+ do_run_script(browser, NULL, NULL);
}
/* Switch to another data file */
else if (choice == switch_data) {
-do_data_switch:
- if (!switch_data_file()) {
- key = K_SWITCH_INPUT_DATA;
+ key = do_switch_data(browser, key);
+ if (key == K_SWITCH_INPUT_DATA)
break;
- } else
- ui__warning("Won't switch the data files due to\n"
- "no valid data file get selected!\n");
}
}
out_free_stack:
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 22/25] perf hists browser: Split popup menu actions - part 2
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (21 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Currently perf_evsel__hists_browse() function spins on a huge loop and
handles many key actions. Since it's hard to read and modify, let's
split it out into small helper functions.
The add_XXX_opt() functions are to register popup menu item on the
selected entry. When it adds an item, it also saves related data into
struct popup_action and returns 1 so that it can increase the number of
items (nr_options).
With this change, we can simplify the code just to call selected
callback function without considering various conditions. A callback
function named do_XXX is called with saved data when the item is
selected by user.
No functional change intended.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-9-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 354 +++++++++++++++++++++++++----------------
1 file changed, 214 insertions(+), 140 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7d88a1c..9bd7b38 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1402,8 +1402,16 @@ close_file_and_continue:
return ret;
}
+struct popup_action {
+ struct thread *thread;
+ struct dso *dso;
+ struct map_symbol ms;
+
+ int (*fn)(struct hist_browser *browser, struct popup_action *act);
+};
+
static int
-do_annotate(struct hist_browser *browser, struct map_symbol *ms)
+do_annotate(struct hist_browser *browser, struct popup_action *act)
{
struct perf_evsel *evsel;
struct annotation *notes;
@@ -1413,12 +1421,12 @@ do_annotate(struct hist_browser *browser, struct map_symbol *ms)
if (!objdump_path && perf_session_env__lookup_objdump(browser->env))
return 0;
- notes = symbol__annotation(ms->sym);
+ notes = symbol__annotation(act->ms.sym);
if (!notes->src)
return 0;
evsel = hists_to_evsel(browser->hists);
- err = map_symbol__tui_annotate(ms, evsel, browser->hbt);
+ err = map_symbol__tui_annotate(&act->ms, evsel, browser->hbt);
he = hist_browser__selected_entry(browser);
/*
* offer option to annotate the other branch source or target
@@ -1434,8 +1442,27 @@ do_annotate(struct hist_browser *browser, struct map_symbol *ms)
}
static int
-do_zoom_thread(struct hist_browser *browser, struct thread *thread)
+add_annotate_opt(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act, char **optstr,
+ struct map *map, struct symbol *sym)
{
+ if (sym == NULL || map->dso->annotate_warned)
+ return 0;
+
+ if (asprintf(optstr, "Annotate %s", sym->name) < 0)
+ return 0;
+
+ act->ms.map = map;
+ act->ms.sym = sym;
+ act->fn = do_annotate;
+ return 1;
+}
+
+static int
+do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
+{
+ struct thread *thread = act->thread;
+
if (browser->hists->thread_filter) {
pstack__remove(browser->pstack, &browser->hists->thread_filter);
perf_hpp__set_elide(HISTC_THREAD, false);
@@ -1456,8 +1483,28 @@ do_zoom_thread(struct hist_browser *browser, struct thread *thread)
}
static int
-do_zoom_dso(struct hist_browser *browser, struct dso *dso)
+add_thread_opt(struct hist_browser *browser, struct popup_action *act,
+ char **optstr, struct thread *thread)
+{
+ if (thread == NULL)
+ return 0;
+
+ if (asprintf(optstr, "Zoom %s %s(%d) thread",
+ browser->hists->thread_filter ? "out of" : "into",
+ thread->comm_set ? thread__comm_str(thread) : "",
+ thread->tid) < 0)
+ return 0;
+
+ act->thread = thread;
+ act->fn = do_zoom_thread;
+ return 1;
+}
+
+static int
+do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
{
+ struct dso *dso = act->dso;
+
if (browser->hists->dso_filter) {
pstack__remove(browser->pstack, &browser->hists->dso_filter);
perf_hpp__set_elide(HISTC_DSO, false);
@@ -1479,25 +1526,58 @@ do_zoom_dso(struct hist_browser *browser, struct dso *dso)
}
static int
-do_browse_map(struct hist_browser *browser __maybe_unused, struct map *map)
+add_dso_opt(struct hist_browser *browser, struct popup_action *act,
+ char **optstr, struct dso *dso)
{
- map__browse(map);
+ if (dso == NULL)
+ return 0;
+
+ if (asprintf(optstr, "Zoom %s %s DSO",
+ browser->hists->dso_filter ? "out of" : "into",
+ dso->kernel ? "the Kernel" : dso->short_name) < 0)
+ return 0;
+
+ act->dso = dso;
+ act->fn = do_zoom_dso;
+ return 1;
+}
+
+static int
+do_browse_map(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act)
+{
+ map__browse(act->ms.map);
return 0;
}
static int
+add_map_opt(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act, char **optstr, struct map *map)
+{
+ if (map == NULL)
+ return 0;
+
+ if (asprintf(optstr, "Browse map details") < 0)
+ return 0;
+
+ act->ms.map = map;
+ act->fn = do_browse_map;
+ return 1;
+}
+
+static int
do_run_script(struct hist_browser *browser __maybe_unused,
- struct thread *thread, struct symbol *sym)
+ struct popup_action *act)
{
char script_opt[64];
memset(script_opt, 0, sizeof(script_opt));
- if (thread) {
+ if (act->thread) {
scnprintf(script_opt, sizeof(script_opt), " -c %s ",
- thread__comm_str(thread));
- } else if (sym) {
+ thread__comm_str(act->thread));
+ } else if (act->ms.sym) {
scnprintf(script_opt, sizeof(script_opt), " -S %s ",
- sym->name);
+ act->ms.sym->name);
}
script_browse(script_opt);
@@ -1505,17 +1585,74 @@ do_run_script(struct hist_browser *browser __maybe_unused,
}
static int
-do_switch_data(struct hist_browser *browser __maybe_unused, int key)
+add_script_opt(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act, char **optstr,
+ struct thread *thread, struct symbol *sym)
+{
+ if (thread) {
+ if (asprintf(optstr, "Run scripts for samples of thread [%s]",
+ thread__comm_str(thread)) < 0)
+ return 0;
+ } else if (sym) {
+ if (asprintf(optstr, "Run scripts for samples of symbol [%s]",
+ sym->name) < 0)
+ return 0;
+ } else {
+ if (asprintf(optstr, "Run scripts for all samples") < 0)
+ return 0;
+ }
+
+ act->thread = thread;
+ act->ms.sym = sym;
+ act->fn = do_run_script;
+ return 1;
+}
+
+static int
+do_switch_data(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act __maybe_unused)
{
if (switch_data_file()) {
ui__warning("Won't switch the data files due to\n"
"no valid data file get selected!\n");
- return key;
+ return 0;
}
return K_SWITCH_INPUT_DATA;
}
+static int
+add_switch_opt(struct hist_browser *browser,
+ struct popup_action *act, char **optstr)
+{
+ if (!is_report_browser(browser->hbt))
+ return 0;
+
+ if (asprintf(optstr, "Switch to another data file in PWD") < 0)
+ return 0;
+
+ act->fn = do_switch_data;
+ return 1;
+}
+
+static int
+do_exit_browser(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act __maybe_unused)
+{
+ return 0;
+}
+
+static int
+add_exit_opt(struct hist_browser *browser __maybe_unused,
+ struct popup_action *act, char **optstr)
+{
+ if (asprintf(optstr, "Exit") < 0)
+ return 0;
+
+ act->fn = do_exit_browser;
+ return 1;
+}
+
static void hist_browser__update_nr_entries(struct hist_browser *hb)
{
u64 nr_entries = 0;
@@ -1546,6 +1683,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct branch_info *bi;
#define MAX_OPTIONS 16
char *options[MAX_OPTIONS];
+ struct popup_action actions[MAX_OPTIONS];
int nr_options = 0;
int key = -1;
char buf[64];
@@ -1600,6 +1738,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
ui_helpline__push(helpline);
memset(options, 0, sizeof(options));
+ memset(actions, 0, sizeof(actions));
perf_hpp__for_each_format(fmt)
perf_hpp__reset_width(fmt, hists);
@@ -1610,12 +1749,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
while (1) {
struct thread *thread = NULL;
struct dso *dso = NULL;
- struct map_symbol ms;
- int choice = 0,
- annotate = -2, zoom_dso = -2, zoom_thread = -2,
- annotate_f = -2, annotate_t = -2, browse_map = -2;
- int scripts_comm = -2, scripts_symbol = -2,
- scripts_all = -2, switch_data = -2;
+ int choice = 0;
nr_options = 0;
@@ -1648,22 +1782,23 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
browser->selection->map->dso->annotate_warned)
continue;
- ms.map = browser->selection->map;
- ms.sym = browser->selection->sym;
-
- do_annotate(browser, &ms);
+ actions->ms.map = browser->selection->map;
+ actions->ms.sym = browser->selection->sym;
+ do_annotate(browser, actions);
continue;
case 'P':
hist_browser__dump(browser);
continue;
case 'd':
- do_zoom_dso(browser, dso);
+ actions->dso = dso;
+ do_zoom_dso(browser, actions);
continue;
case 'V':
browser->show_dso = !browser->show_dso;
continue;
case 't':
- do_zoom_thread(browser, thread);
+ actions->thread = thread;
+ do_zoom_thread(browser, actions);
continue;
case '/':
if (ui_browser__input_window("Symbol to show",
@@ -1676,12 +1811,15 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
}
continue;
case 'r':
- if (is_report_browser(hbt))
- do_run_script(browser, NULL, NULL);
+ if (is_report_browser(hbt)) {
+ actions->thread = NULL;
+ actions->ms.sym = NULL;
+ do_run_script(browser, actions);
+ }
continue;
case 's':
if (is_report_browser(hbt)) {
- key = do_switch_data(browser, key);
+ key = do_switch_data(browser, actions);
if (key == K_SWITCH_INPUT_DATA)
goto out_free_stack;
}
@@ -1762,129 +1900,65 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (bi == NULL)
goto skip_annotation;
- if (bi->from.sym != NULL &&
- !bi->from.map->dso->annotate_warned &&
- asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) {
- annotate_f = nr_options++;
- }
-
- if (bi->to.sym != NULL &&
- !bi->to.map->dso->annotate_warned &&
- (bi->to.sym != bi->from.sym ||
- bi->to.map->dso != bi->from.map->dso) &&
- asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) {
- annotate_t = nr_options++;
- }
+ nr_options += add_annotate_opt(browser,
+ &actions[nr_options],
+ &options[nr_options],
+ bi->from.map,
+ bi->from.sym);
+ if (bi->to.sym != bi->from.sym)
+ nr_options += add_annotate_opt(browser,
+ &actions[nr_options],
+ &options[nr_options],
+ bi->to.map,
+ bi->to.sym);
} else {
- if (browser->selection->sym != NULL &&
- !browser->selection->map->dso->annotate_warned) {
- struct annotation *notes;
-
- notes = symbol__annotation(browser->selection->sym);
-
- if (notes->src &&
- asprintf(&options[nr_options], "Annotate %s",
- browser->selection->sym->name) > 0) {
- annotate = nr_options++;
- }
- }
+ nr_options += add_annotate_opt(browser,
+ &actions[nr_options],
+ &options[nr_options],
+ browser->selection->map,
+ browser->selection->sym);
}
skip_annotation:
- if (thread != NULL &&
- asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
- (browser->hists->thread_filter ? "out of" : "into"),
- (thread->comm_set ? thread__comm_str(thread) : ""),
- thread->tid) > 0)
- zoom_thread = nr_options++;
-
- if (dso != NULL &&
- asprintf(&options[nr_options], "Zoom %s %s DSO",
- (browser->hists->dso_filter ? "out of" : "into"),
- (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
- zoom_dso = nr_options++;
-
- if (browser->selection != NULL &&
- browser->selection->map != NULL &&
- asprintf(&options[nr_options], "Browse map details") > 0)
- browse_map = nr_options++;
+ nr_options += add_thread_opt(browser, &actions[nr_options],
+ &options[nr_options], thread);
+ nr_options += add_dso_opt(browser, &actions[nr_options],
+ &options[nr_options], dso);
+ nr_options += add_map_opt(browser, &actions[nr_options],
+ &options[nr_options],
+ browser->selection->map);
/* perf script support */
if (browser->he_selection) {
- struct symbol *sym;
-
- if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
- thread__comm_str(browser->he_selection->thread)) > 0)
- scripts_comm = nr_options++;
-
- sym = browser->he_selection->ms.sym;
- if (sym && sym->namelen &&
- asprintf(&options[nr_options], "Run scripts for samples of symbol [%s]",
- sym->name) > 0)
- scripts_symbol = nr_options++;
+ nr_options += add_script_opt(browser,
+ &actions[nr_options],
+ &options[nr_options],
+ thread, NULL);
+ nr_options += add_script_opt(browser,
+ &actions[nr_options],
+ &options[nr_options],
+ NULL, browser->selection->sym);
}
-
- if (asprintf(&options[nr_options], "Run scripts for all samples") > 0)
- scripts_all = nr_options++;
-
- if (is_report_browser(hbt) && asprintf(&options[nr_options],
- "Switch to another data file in PWD") > 0)
- switch_data = nr_options++;
+ nr_options += add_script_opt(browser, &actions[nr_options],
+ &options[nr_options], NULL, NULL);
+ nr_options += add_switch_opt(browser, &actions[nr_options],
+ &options[nr_options]);
add_exit_option:
- if (asprintf(&options[nr_options], "Exit") > 0)
- nr_options++;
-retry_popup_menu:
- choice = ui__popup_menu(nr_options, options);
+ nr_options += add_exit_opt(browser, &actions[nr_options],
+ &options[nr_options]);
- if (choice == nr_options - 1)
- break;
-
- if (choice == -1) {
- free_popup_options(options, nr_options - 1);
- continue;
- }
-
- if (choice == annotate || choice == annotate_t || choice == annotate_f) {
- struct hist_entry *he;
+ do {
+ struct popup_action *act;
- he = hist_browser__selected_entry(browser);
- if (he == NULL)
- continue;
+ choice = ui__popup_menu(nr_options, options);
+ if (choice == -1 || choice >= nr_options)
+ break;
- if (choice == annotate_f) {
- ms.map = he->branch_info->from.map;
- ms.sym = he->branch_info->from.sym;
- } else if (choice == annotate_t) {
- ms.map = he->branch_info->to.map;
- ms.sym = he->branch_info->to.sym;
- } else {
- ms = *browser->selection;
- }
+ act = &actions[choice];
+ key = act->fn(browser, act);
+ } while (key == 1);
- if (do_annotate(browser, &ms) == 1)
- goto retry_popup_menu;
- } else if (choice == browse_map) {
- do_browse_map(browser, browser->selection->map);
- } else if (choice == zoom_dso) {
- do_zoom_dso(browser, dso);
- } else if (choice == zoom_thread) {
- do_zoom_thread(browser, thread);
- }
- /* perf scripts support */
- else if (choice == scripts_all || choice == scripts_comm ||
- choice == scripts_symbol) {
- if (choice == scripts_comm)
- do_run_script(browser, browser->he_selection->thread, NULL);
- if (choice == scripts_symbol)
- do_run_script(browser, NULL, browser->he_selection->ms.sym);
- if (choice == scripts_all)
- do_run_script(browser, NULL, NULL);
- }
- /* Switch to another data file */
- else if (choice == switch_data) {
- key = do_switch_data(browser, key);
- if (key == K_SWITCH_INPUT_DATA)
- break;
- }
+ if (key == K_SWITCH_INPUT_DATA)
+ break;
}
out_free_stack:
pstack__delete(browser->pstack);
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 23/25] perf tools: Introduce pstack_peek()
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (22 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The pstack_peek() is to get the topmost entry without removing it.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429838133-14001-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/pstack.c | 7 +++++++
tools/perf/util/pstack.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index a126e6c..b234a6e 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -74,3 +74,10 @@ void *pstack__pop(struct pstack *pstack)
pstack->entries[pstack->top] = NULL;
return ret;
}
+
+void *pstack__peek(struct pstack *pstack)
+{
+ if (pstack->top == 0)
+ return NULL;
+ return pstack->entries[pstack->top - 1];
+}
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index c3cb658..ded7f2e 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -10,5 +10,6 @@ bool pstack__empty(const struct pstack *pstack);
void pstack__remove(struct pstack *pstack, void *key);
void pstack__push(struct pstack *pstack, void *key);
void *pstack__pop(struct pstack *pstack);
+void *pstack__peek(struct pstack *pstack);
#endif /* _PERF_PSTACK_ */
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 24/25] perf hists browser: Simplify zooming code using pstack_peek()
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (23 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
Now LEFT key press action can just use do_zoom_dso/thread() code to get
out of the current filter.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429838133-14001-2-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 9bd7b38..8733d57 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1860,19 +1860,17 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto out_free_stack;
continue;
}
- top = pstack__pop(browser->pstack);
+ top = pstack__peek(browser->pstack);
if (top == &browser->hists->dso_filter) {
- perf_hpp__set_elide(HISTC_DSO, false);
- browser->hists->dso_filter = NULL;
- hists__filter_by_dso(browser->hists);
- }
- if (top == &browser->hists->thread_filter) {
- perf_hpp__set_elide(HISTC_THREAD, false);
- thread__zput(browser->hists->thread_filter);
- hists__filter_by_thread(browser->hists);
+ /*
+ * No need to set actions->dso here since
+ * it's just to remove the current filter.
+ * Ditto for thread below.
+ */
+ do_zoom_dso(browser, actions);
}
- ui_helpline__pop();
- hist_browser__reset(browser);
+ if (top == &browser->hists->thread_filter)
+ do_zoom_thread(browser, actions);
continue;
}
case K_ESC:
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH 25/25] perf tools: Move TUI-specific fields out of map_symbol
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
` (24 preceding siblings ...)
(?)
@ 2015-05-05 21:32 ` Arnaldo Carvalho de Melo
-1 siblings, 0 replies; 43+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-05-05 21:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, David Ahern, Jiri Olsa,
Peter Zijlstra, Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@kernel.org>
The has_children and unfolded fields don't belong to the struct
map_symbol since they're used by the TUI only. Move those fields out of
map_symbol since the struct is also used by other places.
This will also help to compact the sizeof struct hist_entry.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429687101-4360-11-git-send-email-namhyung@kernel.org
Link: http://lkml.kernel.org/r/1430837746-5439-1-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/ui/browsers/hists.c | 79 +++++++++++++++++++++++++-----------------
tools/perf/util/callchain.h | 4 +++
tools/perf/util/hist.c | 2 +-
tools/perf/util/sort.h | 2 ++
tools/perf/util/symbol.h | 2 --
5 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 8733d57..f981cb8 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -63,7 +63,7 @@ static int hist_browser__get_folding(struct hist_browser *browser)
struct hist_entry *he =
rb_entry(nd, struct hist_entry, rb_node);
- if (he->ms.unfolded)
+ if (he->unfolded)
unfolded_rows += he->nr_rows;
}
return unfolded_rows;
@@ -139,24 +139,19 @@ static char tree__folded_sign(bool unfolded)
return unfolded ? '-' : '+';
}
-static char map_symbol__folded(const struct map_symbol *ms)
-{
- return ms->has_children ? tree__folded_sign(ms->unfolded) : ' ';
-}
-
static char hist_entry__folded(const struct hist_entry *he)
{
- return map_symbol__folded(&he->ms);
+ return he->has_children ? tree__folded_sign(he->unfolded) : ' ';
}
static char callchain_list__folded(const struct callchain_list *cl)
{
- return map_symbol__folded(&cl->ms);
+ return cl->has_children ? tree__folded_sign(cl->unfolded) : ' ';
}
-static void map_symbol__set_folding(struct map_symbol *ms, bool unfold)
+static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
{
- ms->unfolded = unfold ? ms->has_children : false;
+ cl->unfolded = unfold ? cl->has_children : false;
}
static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
@@ -192,7 +187,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
list_for_each_entry(chain, &node->val, list) {
++n;
- unfolded = chain->ms.unfolded;
+ unfolded = chain->unfolded;
}
if (unfolded)
@@ -214,15 +209,27 @@ static int callchain__count_rows(struct rb_root *chain)
return n;
}
-static bool map_symbol__toggle_fold(struct map_symbol *ms)
+static bool hist_entry__toggle_fold(struct hist_entry *he)
{
- if (!ms)
+ if (!he)
return false;
- if (!ms->has_children)
+ if (!he->has_children)
return false;
- ms->unfolded = !ms->unfolded;
+ he->unfolded = !he->unfolded;
+ return true;
+}
+
+static bool callchain_list__toggle_fold(struct callchain_list *cl)
+{
+ if (!cl)
+ return false;
+
+ if (!cl->has_children)
+ return false;
+
+ cl->unfolded = !cl->unfolded;
return true;
}
@@ -238,10 +245,10 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no
list_for_each_entry(chain, &child->val, list) {
if (first) {
first = false;
- chain->ms.has_children = chain->list.next != &child->val ||
+ chain->has_children = chain->list.next != &child->val ||
!RB_EMPTY_ROOT(&child->rb_root);
} else
- chain->ms.has_children = chain->list.next == &child->val &&
+ chain->has_children = chain->list.next == &child->val &&
!RB_EMPTY_ROOT(&child->rb_root);
}
@@ -255,11 +262,11 @@ static void callchain_node__init_have_children(struct callchain_node *node,
struct callchain_list *chain;
chain = list_entry(node->val.next, struct callchain_list, list);
- chain->ms.has_children = has_sibling;
+ chain->has_children = has_sibling;
if (!list_empty(&node->val)) {
chain = list_entry(node->val.prev, struct callchain_list, list);
- chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
+ chain->has_children = !RB_EMPTY_ROOT(&node->rb_root);
}
callchain_node__init_have_children_rb_tree(node);
@@ -279,7 +286,7 @@ static void callchain__init_have_children(struct rb_root *root)
static void hist_entry__init_have_children(struct hist_entry *he)
{
if (!he->init_have_children) {
- he->ms.has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
+ he->has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
callchain__init_have_children(&he->sorted_chain);
he->init_have_children = true;
}
@@ -287,14 +294,22 @@ static void hist_entry__init_have_children(struct hist_entry *he)
static bool hist_browser__toggle_fold(struct hist_browser *browser)
{
- if (map_symbol__toggle_fold(browser->selection)) {
- struct hist_entry *he = browser->he_selection;
+ struct hist_entry *he = browser->he_selection;
+ struct map_symbol *ms = browser->selection;
+ struct callchain_list *cl = container_of(ms, struct callchain_list, ms);
+ bool has_children;
+
+ if (ms == &he->ms)
+ has_children = hist_entry__toggle_fold(he);
+ else
+ has_children = callchain_list__toggle_fold(cl);
+ if (has_children) {
hist_entry__init_have_children(he);
browser->b.nr_entries -= he->nr_rows;
browser->nr_callchain_rows -= he->nr_rows;
- if (he->ms.unfolded)
+ if (he->unfolded)
he->nr_rows = callchain__count_rows(&he->sorted_chain);
else
he->nr_rows = 0;
@@ -321,8 +336,8 @@ static int callchain_node__set_folding_rb_tree(struct callchain_node *node, bool
list_for_each_entry(chain, &child->val, list) {
++n;
- map_symbol__set_folding(&chain->ms, unfold);
- has_children = chain->ms.has_children;
+ callchain_list__set_folding(chain, unfold);
+ has_children = chain->has_children;
}
if (has_children)
@@ -340,8 +355,8 @@ static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
list_for_each_entry(chain, &node->val, list) {
++n;
- map_symbol__set_folding(&chain->ms, unfold);
- has_children = chain->ms.has_children;
+ callchain_list__set_folding(chain, unfold);
+ has_children = chain->has_children;
}
if (has_children)
@@ -366,9 +381,9 @@ static int callchain__set_folding(struct rb_root *chain, bool unfold)
static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
{
hist_entry__init_have_children(he);
- map_symbol__set_folding(&he->ms, unfold);
+ he->unfolded = unfold ? he->has_children : false;
- if (he->ms.has_children) {
+ if (he->has_children) {
int n = callchain__set_folding(&he->sorted_chain, unfold);
he->nr_rows = unfold ? n : 0;
} else
@@ -1019,7 +1034,7 @@ do_offset:
if (offset > 0) {
do {
h = rb_entry(nd, struct hist_entry, rb_node);
- if (h->ms.unfolded) {
+ if (h->unfolded) {
u16 remaining = h->nr_rows - h->row_offset;
if (offset > remaining) {
offset -= remaining;
@@ -1040,7 +1055,7 @@ do_offset:
} else if (offset < 0) {
while (1) {
h = rb_entry(nd, struct hist_entry, rb_node);
- if (h->ms.unfolded) {
+ if (h->unfolded) {
if (first) {
if (-offset > h->row_offset) {
offset += h->row_offset;
@@ -1077,7 +1092,7 @@ do_offset:
* row_offset at its last entry.
*/
h = rb_entry(nd, struct hist_entry, rb_node);
- if (h->ms.unfolded)
+ if (h->unfolded)
h->row_offset = h->nr_rows;
break;
}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 6033a0a..679c2c6 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -72,6 +72,10 @@ extern struct callchain_param callchain_param;
struct callchain_list {
u64 ip;
struct map_symbol ms;
+ struct /* for TUI */ {
+ bool unfolded;
+ bool has_children;
+ };
char *srcline;
struct list_head list;
};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cc22b91..3387706 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1163,7 +1163,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
return;
/* force fold unfiltered entry for simplicity */
- h->ms.unfolded = false;
+ h->unfolded = false;
h->row_offset = 0;
h->nr_rows = 0;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 4d923e6..e97cd47 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -109,6 +109,8 @@ struct hist_entry {
u16 row_offset;
u16 nr_rows;
bool init_have_children;
+ bool unfolded;
+ bool has_children;
};
};
char *srcline;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 9096529..bef47ead 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -158,8 +158,6 @@ struct ref_reloc_sym {
struct map_symbol {
struct map *map;
struct symbol *sym;
- bool unfolded;
- bool has_children;
};
struct addr_map_symbol {
--
2.1.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [GIT PULL 00/25] perf/core improvements and fixes
2015-05-05 21:31 ` Arnaldo Carvalho de Melo
@ 2015-05-06 2:47 ` Ingo Molnar
-1 siblings, 0 replies; 43+ messages in thread
From: Ingo Molnar @ 2015-05-06 2:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Jiri Olsa, Joonsoo Kim, linux-mm, Masami Hiramatsu, Minchan Kim,
Namhyung Kim, Pekka Enberg, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
* Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Hi Ingo,
>
> Please consider applying, on top of previous requests,
>
> - Arnaldo
>
> The following changes since commit 0c160d495b5616e071bb4f873812e8f473128149:
>
> perf kmem: Add kmem.default config option (2015-05-04 13:34:48 -0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3
>
> for you to fetch changes up to 3698dab1c849c7e1cd440df4fca24baa1973d53b:
>
> perf tools: Move TUI-specific fields out of map_symbol (2015-05-05 18:13:24 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> User visible:
>
> - Improve --filter support for 'perf probe', allowing using its arguments
> on other commands, as --add, --del, etc (Masami Hiramatsu)
>
> - Show warning when running 'perf kmem stat' on a unsuitable perf.data file,
> i.e. one with events that are not the ones required for the stat variant
> used (Namhyung Kim).
>
> Infrastructure:
>
> - Auxtrace support patches, paving the way to support Intel PT and BTS (Adrian Hunter)
>
> - hists browser (top, report) refactorings (Namhyung Kim)
>
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>
> ----------------------------------------------------------------
> Adrian Hunter (9):
> perf report: Fix placement of itrace option in documentation
> perf tools: Add AUX area tracing index
> perf tools: Hit all build ids when AUX area tracing
> perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing
> perf auxtrace: Add option to synthesize events for transactions
> perf tools: Add support for PERF_RECORD_AUX
> perf tools: Add support for PERF_RECORD_ITRACE_START
> perf tools: Add AUX area tracing Snapshot Mode
> perf record: Add AUX area tracing Snapshot Mode support
>
> Masami Hiramatsu (4):
> perf probe: Allow to use filter on --del command
> perf probe: Accept filter argument for --funcs
> perf probe: Remove redundant cleanup of params.filter
> perf probe: Cleanup and consolidate command parsers
>
> Namhyung Kim (12):
> perf kmem: Show warning when trying to run stat without record
> perf tools: Move TUI-specific fields into unnamed union
> perf tools: Move init_have_children field to the unnamed union
> perf hists browser: Fix possible memory leak
> perf hists browser: Save hist_browser_timer pointer in hist_browser
> perf hists browser: Save pstack in the hist_browser
> perf hists browser: Save perf_session_env in the hist_browser
> perf hists browser: Split popup menu actions
> perf hists browser: Split popup menu actions - part 2
> perf tools: Introduce pstack_peek()
> perf hists browser: Simplify zooming code using pstack_peek()
> perf tools: Move TUI-specific fields out of map_symbol
>
> tools/perf/Documentation/perf-inject.txt | 9 +-
> tools/perf/Documentation/perf-probe.txt | 3 +-
> tools/perf/Documentation/perf-record.txt | 7 +
> tools/perf/Documentation/perf-report.txt | 15 +-
> tools/perf/Documentation/perf-script.txt | 9 +-
> tools/perf/Makefile.perf | 2 +
> tools/perf/builtin-buildid-list.c | 9 +
> tools/perf/builtin-inject.c | 78 +++-
> tools/perf/builtin-kmem.c | 17 +-
> tools/perf/builtin-probe.c | 133 +++----
> tools/perf/builtin-record.c | 172 ++++++++-
> tools/perf/config/Makefile | 5 +
> tools/perf/perf.h | 3 +
> tools/perf/tests/make | 4 +-
> tools/perf/ui/browsers/hists.c | 633 +++++++++++++++++++------------
> tools/perf/util/Build | 2 +-
> tools/perf/util/auxtrace.c | 305 ++++++++++++++-
> tools/perf/util/auxtrace.h | 217 +++++++++++
> tools/perf/util/callchain.h | 4 +
> tools/perf/util/event.c | 39 ++
> tools/perf/util/event.h | 24 ++
> tools/perf/util/header.c | 31 +-
> tools/perf/util/hist.c | 2 +-
> tools/perf/util/machine.c | 21 +
> tools/perf/util/machine.h | 4 +
> tools/perf/util/parse-options.h | 4 +
> tools/perf/util/probe-event.c | 102 ++---
> tools/perf/util/probe-event.h | 2 +-
> tools/perf/util/pstack.c | 7 +
> tools/perf/util/pstack.h | 1 +
> tools/perf/util/session.c | 32 ++
> tools/perf/util/session.h | 1 +
> tools/perf/util/sort.h | 22 +-
> tools/perf/util/symbol.h | 2 -
> tools/perf/util/tool.h | 2 +
> 35 files changed, 1455 insertions(+), 468 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [GIT PULL 00/25] perf/core improvements and fixes
@ 2015-05-06 2:47 ` Ingo Molnar
0 siblings, 0 replies; 43+ messages in thread
From: Ingo Molnar @ 2015-05-06 2:47 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Adrian Hunter, David Ahern, Frederic Weisbecker,
Jiri Olsa, Joonsoo Kim, linux-mm, Masami Hiramatsu, Minchan Kim,
Namhyung Kim, Pekka Enberg, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
* Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Hi Ingo,
>
> Please consider applying, on top of previous requests,
>
> - Arnaldo
>
> The following changes since commit 0c160d495b5616e071bb4f873812e8f473128149:
>
> perf kmem: Add kmem.default config option (2015-05-04 13:34:48 -0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-3
>
> for you to fetch changes up to 3698dab1c849c7e1cd440df4fca24baa1973d53b:
>
> perf tools: Move TUI-specific fields out of map_symbol (2015-05-05 18:13:24 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> User visible:
>
> - Improve --filter support for 'perf probe', allowing using its arguments
> on other commands, as --add, --del, etc (Masami Hiramatsu)
>
> - Show warning when running 'perf kmem stat' on a unsuitable perf.data file,
> i.e. one with events that are not the ones required for the stat variant
> used (Namhyung Kim).
>
> Infrastructure:
>
> - Auxtrace support patches, paving the way to support Intel PT and BTS (Adrian Hunter)
>
> - hists browser (top, report) refactorings (Namhyung Kim)
>
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>
> ----------------------------------------------------------------
> Adrian Hunter (9):
> perf report: Fix placement of itrace option in documentation
> perf tools: Add AUX area tracing index
> perf tools: Hit all build ids when AUX area tracing
> perf tools: Add build option NO_AUXTRACE to exclude AUX area tracing
> perf auxtrace: Add option to synthesize events for transactions
> perf tools: Add support for PERF_RECORD_AUX
> perf tools: Add support for PERF_RECORD_ITRACE_START
> perf tools: Add AUX area tracing Snapshot Mode
> perf record: Add AUX area tracing Snapshot Mode support
>
> Masami Hiramatsu (4):
> perf probe: Allow to use filter on --del command
> perf probe: Accept filter argument for --funcs
> perf probe: Remove redundant cleanup of params.filter
> perf probe: Cleanup and consolidate command parsers
>
> Namhyung Kim (12):
> perf kmem: Show warning when trying to run stat without record
> perf tools: Move TUI-specific fields into unnamed union
> perf tools: Move init_have_children field to the unnamed union
> perf hists browser: Fix possible memory leak
> perf hists browser: Save hist_browser_timer pointer in hist_browser
> perf hists browser: Save pstack in the hist_browser
> perf hists browser: Save perf_session_env in the hist_browser
> perf hists browser: Split popup menu actions
> perf hists browser: Split popup menu actions - part 2
> perf tools: Introduce pstack_peek()
> perf hists browser: Simplify zooming code using pstack_peek()
> perf tools: Move TUI-specific fields out of map_symbol
>
> tools/perf/Documentation/perf-inject.txt | 9 +-
> tools/perf/Documentation/perf-probe.txt | 3 +-
> tools/perf/Documentation/perf-record.txt | 7 +
> tools/perf/Documentation/perf-report.txt | 15 +-
> tools/perf/Documentation/perf-script.txt | 9 +-
> tools/perf/Makefile.perf | 2 +
> tools/perf/builtin-buildid-list.c | 9 +
> tools/perf/builtin-inject.c | 78 +++-
> tools/perf/builtin-kmem.c | 17 +-
> tools/perf/builtin-probe.c | 133 +++----
> tools/perf/builtin-record.c | 172 ++++++++-
> tools/perf/config/Makefile | 5 +
> tools/perf/perf.h | 3 +
> tools/perf/tests/make | 4 +-
> tools/perf/ui/browsers/hists.c | 633 +++++++++++++++++++------------
> tools/perf/util/Build | 2 +-
> tools/perf/util/auxtrace.c | 305 ++++++++++++++-
> tools/perf/util/auxtrace.h | 217 +++++++++++
> tools/perf/util/callchain.h | 4 +
> tools/perf/util/event.c | 39 ++
> tools/perf/util/event.h | 24 ++
> tools/perf/util/header.c | 31 +-
> tools/perf/util/hist.c | 2 +-
> tools/perf/util/machine.c | 21 +
> tools/perf/util/machine.h | 4 +
> tools/perf/util/parse-options.h | 4 +
> tools/perf/util/probe-event.c | 102 ++---
> tools/perf/util/probe-event.h | 2 +-
> tools/perf/util/pstack.c | 7 +
> tools/perf/util/pstack.h | 1 +
> tools/perf/util/session.c | 32 ++
> tools/perf/util/session.h | 1 +
> tools/perf/util/sort.h | 22 +-
> tools/perf/util/symbol.h | 2 -
> tools/perf/util/tool.h | 2 +
> 35 files changed, 1455 insertions(+), 468 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo
^ permalink raw reply [flat|nested] 43+ messages in thread