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>
This commit is contained in:
David Carrillo-Cisneros
2017-07-17 21:25:48 -07:00
committed by Arnaldo Carvalho de Melo
parent 114f709e01
commit e9def1b2e7
12 changed files with 141 additions and 3 deletions

View File

@@ -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)
{