diff options
author | David Carrillo-Cisneros <davidcc@google.com> | 2017-07-18 07:25:48 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-07-19 05:14:36 +0300 |
commit | e9def1b2e74e3d2134133f70d2a84c242446bbe7 (patch) | |
tree | 89a38bc201cadb7ab9220a128372c80adcdb6cab /tools/perf/util/header.c | |
parent | 114f709e01e62760a6d03de1358188293dfefdda (diff) | |
download | linux-e9def1b2e74e3d2134133f70d2a84c242446bbe7.tar.xz |
perf tools: Add feature header record to pipe-mode
Add header record types to pipe-mode, reusing the functions
used in file-mode and leveraging the new struct feat_fd.
For alignment, check that synthesized events don't exceed
pagesize.
Add the perf_event__synthesize_feature event call back to
process the new header records.
Before this patch:
$ perf record -o - -e cycles sleep 1 | perf report --stdio --header
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.000 MB - ]
...
After this patch:
$ perf record -o - -e cycles sleep 1 | perf report --stdio --header
# ========
# captured on: Mon May 22 16:33:43 2017
# ========
#
# hostname : my_hostname
# os release : 4.11.0-dbx-up_perf
# perf version : 4.11.rc6.g6277c80
# arch : x86_64
# nrcpus online : 72
# nrcpus avail : 72
# cpudesc : Intel(R) Xeon(R) CPU E5-2696 v3 @ 2.30GHz
# cpuid : GenuineIntel,6,63,2
# total memory : 263457192 kB
# cmdline : /root/perf record -o - -e cycles -c 100000 sleep 1
# HEADER_CPU_TOPOLOGY info available, use -I to display
# HEADER_NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: intel_bts = 6, uncore_imc_4 = 22, uncore_sbox_1 = 47, uncore_cbox_5 = 33, uncore_ha_0 = 16, uncore_cbox
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.000 MB - ]
...
Support added for the subcommands: report, inject, annotate and script.
Signed-off-by: David Carrillo-Cisneros <davidcc@google.com>
Acked-by: David Ahern <dsahern@gmail.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Turner <pjt@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Simon Que <sque@chromium.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/20170718042549.145161-16-davidcc@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 0fdbf7554ea3..2e6036d3e584 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -35,6 +35,7 @@ #include "data.h" #include <api/fs/fs.h> #include "asm/bug.h" +#include "tool.h" #include "sane_ctype.h" @@ -2982,6 +2983,103 @@ int perf_event__synthesize_attr(struct perf_tool *tool, return err; } +int perf_event__synthesize_features(struct perf_tool *tool, + struct perf_session *session, + struct perf_evlist *evlist, + perf_event__handler_t process) +{ + struct perf_header *header = &session->header; + struct feat_fd ff; + struct feature_event *fe; + size_t sz, sz_hdr; + int feat, ret; + + sz_hdr = sizeof(fe->header); + sz = sizeof(union perf_event); + /* get a nice alignment */ + sz = PERF_ALIGN(sz, page_size); + + memset(&ff, 0, sizeof(ff)); + + ff.buf = malloc(sz); + if (!ff.buf) + return -ENOMEM; + + ff.size = sz - sz_hdr; + + for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { + if (!feat_ops[feat].synthesize) { + pr_debug("No record header feature for header :%d\n", feat); + continue; + } + + ff.offset = sizeof(*fe); + + ret = feat_ops[feat].write(&ff, evlist); + if (ret || ff.offset <= (ssize_t)sizeof(*fe)) { + pr_debug("Error writing feature\n"); + continue; + } + /* ff.buf may have changed due to realloc in do_write() */ + fe = ff.buf; + memset(fe, 0, sizeof(*fe)); + + fe->feat_id = feat; + fe->header.type = PERF_RECORD_HEADER_FEATURE; + fe->header.size = ff.offset; + + ret = process(tool, ff.buf, NULL, NULL); + if (ret) { + free(ff.buf); + return ret; + } + } + free(ff.buf); + return 0; +} + +int perf_event__process_feature(struct perf_tool *tool, + union perf_event *event, + struct perf_session *session __maybe_unused) +{ + struct feat_fd ff = { .fd = 0 }; + struct feature_event *fe = (struct feature_event *)event; + int type = fe->header.type; + u64 feat = fe->feat_id; + + if (type < 0 || type >= PERF_RECORD_HEADER_MAX) { + pr_warning("invalid record type %d in pipe-mode\n", type); + return 0; + } + if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) { + pr_warning("invalid record type %d in pipe-mode\n", type); + return -1; + } + + if (!feat_ops[feat].process) + return 0; + + ff.buf = (void *)fe->data; + ff.size = event->header.size - sizeof(event->header); + ff.ph = &session->header; + + if (feat_ops[feat].process(&ff, NULL)) + return -1; + + if (!feat_ops[feat].print || !tool->show_feat_hdr) + return 0; + + if (!feat_ops[feat].full_only || + tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) { + feat_ops[feat].print(&ff, stdout); + } else { + fprintf(stdout, "# %s info available, use -I to display\n", + feat_ops[feat].name); + } + + return 0; +} + static struct event_update_event * event_update_event__new(size_t size, u64 type, u64 id) { |