Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1671598 > unrolled thread
| Started by | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| First post | 2017-06-21 12:30 +0200 |
| Last post | 2017-07-01 11:00 +0200 |
| Articles | 7 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Adrian Hunter <adrian.hunter@intel.com> - 2017-06-21 12:30 +0200
Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Arnaldo Carvalho de Melo <acme@kernel.org> - 2017-06-21 16:00 +0200
Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Adrian Hunter <adrian.hunter@intel.com> - 2017-06-21 18:50 +0200
Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Arnaldo Carvalho de Melo <acme@kernel.org> - 2017-06-21 19:30 +0200
Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Adrian Hunter <adrian.hunter@intel.com> - 2017-06-21 22:30 +0200
Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events Arnaldo Carvalho de Melo <acme@kernel.org> - 2017-06-22 17:10 +0200
[tip:perf/core] perf script: Add 'synth' event type for synthesized events tip-bot for Adrian Hunter <tipbot@zytor.com> - 2017-07-01 11:00 +0200
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2017-06-21 12:30 +0200 |
| Subject | [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tUL3A-4SB-23@gated-at.bofh.it> |
Instruction trace decoders such as Intel PT may have additional information
recorded in the trace. For example, Intel PT has power information and a
there is a new instruction 'ptwrite' that can write a value into a PTWRITE
trace packet. Such information may be associated with an IP and so can be
treated as a sample (PERF_RECORD_SAMPLE). Custom data can be incorporated
in the sample as raw_data (PERF_SAMPLE_RAW). However a means of identifying
the raw data format is needed. That will be done by synthesizing an
attribute for it. So add an attribute type for custom synthesized events.
Different synthesized events will be identified by the attribute 'config'.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
Changes in V3:
Re-base on Arnaldo's perf/core branch
tools/perf/builtin-script.c | 74 +++++++++++++++++++++++++++++++++++----------
tools/perf/util/event.h | 3 ++
2 files changed, 61 insertions(+), 16 deletions(-)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4bce7d8679cb..2999e7e425f6 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -119,6 +119,11 @@ struct output_option {
{.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
};
+enum {
+ OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
+ OUTPUT_TYPE_MAX
+};
+
/* default set to maintain compatibility with current format */
static struct {
bool user_set;
@@ -126,7 +131,7 @@ struct output_option {
unsigned int print_ip_opts;
u64 fields;
u64 invalid_fields;
-} output[PERF_TYPE_MAX] = {
+} output[OUTPUT_TYPE_MAX] = {
[PERF_TYPE_HARDWARE] = {
.user_set = false,
@@ -184,12 +189,43 @@ struct output_option {
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
},
+
+ [OUTPUT_TYPE_SYNTH] = {
+ .user_set = false,
+
+ .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+ PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+ PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+ PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
+
+ .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
+ },
};
+static inline int output_type(unsigned int type)
+{
+ switch (type) {
+ case PERF_TYPE_SYNTH:
+ return OUTPUT_TYPE_SYNTH;
+ default:
+ return type;
+ }
+}
+
+static inline unsigned int attr_type(unsigned int type)
+{
+ switch (type) {
+ case OUTPUT_TYPE_SYNTH:
+ return PERF_TYPE_SYNTH;
+ default:
+ return type;
+ }
+}
+
static bool output_set_by_user(void)
{
int j;
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
if (output[j].user_set)
return true;
}
@@ -210,7 +246,7 @@ static const char *output_field2str(enum perf_output_field field)
return str;
}
-#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
+#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
u64 sample_type, const char *sample_msg,
@@ -218,7 +254,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
bool allow_user_set)
{
struct perf_event_attr *attr = &evsel->attr;
- int type = attr->type;
+ int type = output_type(attr->type);
const char *evname;
if (attr->sample_type & sample_type)
@@ -348,7 +384,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
static void set_print_ip_opts(struct perf_event_attr *attr)
{
- unsigned int type = attr->type;
+ unsigned int type = output_type(attr->type);
output[type].print_ip_opts = 0;
if (PRINT_FIELD(IP))
@@ -376,14 +412,15 @@ static int perf_session__check_output_opt(struct perf_session *session)
unsigned int j;
struct perf_evsel *evsel;
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
- evsel = perf_session__find_first_evtype(session, j);
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
+ evsel = perf_session__find_first_evtype(session, attr_type(j));
/*
* even if fields is set to 0 (ie., show nothing) event must
* exist if user explicitly includes it on the command line
*/
- if (!evsel && output[j].user_set && !output[j].wildcard_set) {
+ if (!evsel && output[j].user_set && !output[j].wildcard_set &&
+ j != OUTPUT_TYPE_SYNTH) {
pr_err("%s events do not exist. "
"Remove corresponding -F option to proceed.\n",
event_type(j));
@@ -989,6 +1026,7 @@ static void print_sample_bts(struct perf_sample *sample,
struct machine *machine)
{
struct perf_event_attr *attr = &evsel->attr;
+ unsigned int type = output_type(attr->type);
bool print_srcline_last = false;
if (PRINT_FIELD(CALLINDENT))
@@ -996,7 +1034,7 @@ static void print_sample_bts(struct perf_sample *sample,
/* print branch_from information */
if (PRINT_FIELD(IP)) {
- unsigned int print_opts = output[attr->type].print_ip_opts;
+ unsigned int print_opts = output[type].print_ip_opts;
struct callchain_cursor *cursor = NULL;
if (symbol_conf.use_callchain && sample->callchain &&
@@ -1019,7 +1057,7 @@ static void print_sample_bts(struct perf_sample *sample,
/* print branch_to information */
if (PRINT_FIELD(ADDR) ||
((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
- !output[attr->type].user_set)) {
+ !output[type].user_set)) {
printf(" => ");
print_sample_addr(sample, thread, attr);
}
@@ -1215,8 +1253,9 @@ static void process_event(struct perf_script *script,
{
struct thread *thread = al->thread;
struct perf_event_attr *attr = &evsel->attr;
+ unsigned int type = output_type(attr->type);
- if (output[attr->type].fields == 0)
+ if (output[type].fields == 0)
return;
print_sample_start(sample, thread, evsel);
@@ -1263,7 +1302,7 @@ static void process_event(struct perf_script *script,
cursor = &callchain_cursor;
putchar(cursor ? '\n' : ' ');
- sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
+ sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout);
}
if (PRINT_FIELD(IREGS))
@@ -1410,7 +1449,8 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
evlist = *pevlist;
evsel = perf_evlist__last(*pevlist);
- if (evsel->attr.type >= PERF_TYPE_MAX)
+ if (evsel->attr.type >= PERF_TYPE_MAX &&
+ evsel->attr.type != PERF_TYPE_SYNTH)
return 0;
evlist__for_each_entry(evlist, pos) {
@@ -1835,6 +1875,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
type = PERF_TYPE_RAW;
else if (!strcmp(str, "break"))
type = PERF_TYPE_BREAKPOINT;
+ else if (!strcmp(str, "synth"))
+ type = OUTPUT_TYPE_SYNTH;
else {
fprintf(stderr, "Invalid event type in field string.\n");
rc = -EINVAL;
@@ -1865,7 +1907,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
if (output_set_by_user())
pr_warning("Overriding previous field request for all events.\n");
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
output[j].fields = 0;
output[j].user_set = true;
output[j].wildcard_set = true;
@@ -1908,7 +1950,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
/* add user option to all events types for
* which it is valid
*/
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
if (output[j].invalid_fields & all_output_options[i].field) {
pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
all_output_options[i].str, event_type(j));
@@ -2560,7 +2602,7 @@ int cmd_script(int argc, const char **argv)
OPT_CALLBACK('F', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. "
"+field to add and -field to remove."
- "Valid types: hw,sw,trace,raw. "
+ "Valid types: hw,sw,trace,raw,synth. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
"bpf-output,callindent,insn,insnlen,brstackinsn",
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7c3fa1c8cbcd..4162e72eb1b0 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -252,6 +252,9 @@ enum auxtrace_error_type {
PERF_AUXTRACE_ERROR_MAX
};
+/* Attribute type for custom synthesized events */
+#define PERF_TYPE_SYNTH 3000000000
+
/*
* The kernel collects the number of events it couldn't send in a stretch and
* when possible sends this number in a PERF_RECORD_LOST event. The number of
--
1.9.1
[toc] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2017-06-21 16:00 +0200 |
| Subject | Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tUOkP-6Mr-29@gated-at.bofh.it> |
| In reply to | #1671598 |
Em Wed, Jun 21, 2017 at 01:17:19PM +0300, Adrian Hunter escreveu:
> +++ b/tools/perf/util/event.h
> @@ -252,6 +252,9 @@ enum auxtrace_error_type {
> PERF_AUXTRACE_ERROR_MAX
> };
> +/* Attribute type for custom synthesized events */
> +#define PERF_TYPE_SYNTH 3000000000
Why don't you make it PERF_TYPE_MAX and bump PERF_TYPE_MAX by one? I.e.
this way we have what can be in attr.type in a nice enumeration, can
validate it more easily (attr.type < PERF_TYPE_MAX) and will not need to
do those conversions to/from OUTPUT_TYPE_/PERF_TYPE_).
Peter: now its not the PERF_RECORD_ namespace that userspaces want a
chunk of, its PERF_TYPE_, which so far has been pretty stable, grabing
_one_ for event synthesizing things like Intel PT (and ARM's coresight,
I think) directly at include/uapi/linux/perf_event.h's perf_type_id enum
looks cleaner, no?
- Arnaldo
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2017-06-21 18:50 +0200 |
| Subject | Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tUQZj-aB-1@gated-at.bofh.it> |
| In reply to | #1671691 |
On 06/21/2017 04:51 PM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jun 21, 2017 at 01:17:19PM +0300, Adrian Hunter escreveu:
>> +++ b/tools/perf/util/event.h
>> @@ -252,6 +252,9 @@ enum auxtrace_error_type {
>> PERF_AUXTRACE_ERROR_MAX
>> };
>
>> +/* Attribute type for custom synthesized events */
>> +#define PERF_TYPE_SYNTH 3000000000
>
> Why don't you make it PERF_TYPE_MAX and bump PERF_TYPE_MAX by one? I.e.
> this way we have what can be in attr.type in a nice enumeration, can
> validate it more easily (attr.type < PERF_TYPE_MAX) and will not need to
> do those conversions to/from OUTPUT_TYPE_/PERF_TYPE_).
PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently
perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation
to INT_MAX.
> Peter: now its not the PERF_RECORD_ namespace that userspaces want a
> chunk of, its PERF_TYPE_, which so far has been pretty stable, grabing
> _one_ for event synthesizing things like Intel PT (and ARM's coresight,
> I think) directly at include/uapi/linux/perf_event.h's perf_type_id enum
> looks cleaner, no?
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2017-06-21 19:30 +0200 |
| Subject | Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tURC2-HR-13@gated-at.bofh.it> |
| In reply to | #1671791 |
Em Wed, Jun 21, 2017 at 07:41:04PM +0300, Adrian Hunter escreveu:
> On 06/21/2017 04:51 PM, Arnaldo Carvalho de Melo wrote:
> > Em Wed, Jun 21, 2017 at 01:17:19PM +0300, Adrian Hunter escreveu:
> >> +++ b/tools/perf/util/event.h
> >> @@ -252,6 +252,9 @@ enum auxtrace_error_type {
> >> PERF_AUXTRACE_ERROR_MAX
> >> };
> >
> >> +/* Attribute type for custom synthesized events */
> >> +#define PERF_TYPE_SYNTH 3000000000
> >
> > Why don't you make it PERF_TYPE_MAX and bump PERF_TYPE_MAX by one? I.e.
> > this way we have what can be in attr.type in a nice enumeration, can
> > validate it more easily (attr.type < PERF_TYPE_MAX) and will not need to
> > do those conversions to/from OUTPUT_TYPE_/PERF_TYPE_).
> PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently
> perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation
> to INT_MAX.
Oh, forgot about that, guess a comment right beside PERF_TYPE_MAX is in
demand :-\
So why not:
/*
* PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently
* perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation
* to INT_MAX.
*/
#define PERF_TYPE_SYNTH (INT_MAX + 1L)
I.e. wouldn't be some arbitrarily huge value, but one right after what
was defined as the area for the dynamicly allocated PERF_TYPE_
"namespace" for PMUs, right?
> > Peter: now its not the PERF_RECORD_ namespace that userspaces want a
> > chunk of, its PERF_TYPE_, which so far has been pretty stable, grabing
> > _one_ for event synthesizing things like Intel PT (and ARM's coresight,
> > I think) directly at include/uapi/linux/perf_event.h's perf_type_id enum
> > looks cleaner, no?
- Arnaldo
[toc] | [prev] | [next] | [standalone]
| From | Adrian Hunter <adrian.hunter@intel.com> |
|---|---|
| Date | 2017-06-21 22:30 +0200 |
| Subject | Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tUUqd-2L1-3@gated-at.bofh.it> |
| In reply to | #1671834 |
On 06/21/2017 08:29 PM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jun 21, 2017 at 07:41:04PM +0300, Adrian Hunter escreveu:
>> On 06/21/2017 04:51 PM, Arnaldo Carvalho de Melo wrote:
>>> Em Wed, Jun 21, 2017 at 01:17:19PM +0300, Adrian Hunter escreveu:
>>>> +++ b/tools/perf/util/event.h
>>>> @@ -252,6 +252,9 @@ enum auxtrace_error_type {
>>>> PERF_AUXTRACE_ERROR_MAX
>>>> };
>>>
>>>> +/* Attribute type for custom synthesized events */
>>>> +#define PERF_TYPE_SYNTH 3000000000
>>>
>>> Why don't you make it PERF_TYPE_MAX and bump PERF_TYPE_MAX by one? I.e.
>>> this way we have what can be in attr.type in a nice enumeration, can
>>> validate it more easily (attr.type < PERF_TYPE_MAX) and will not need to
>>> do those conversions to/from OUTPUT_TYPE_/PERF_TYPE_).
>
>> PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently
>> perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation
>> to INT_MAX.
>
> Oh, forgot about that, guess a comment right beside PERF_TYPE_MAX is in
> demand :-\
>
> So why not:
>
> /*
> * PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently
> * perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation
> * to INT_MAX.
> */
> #define PERF_TYPE_SYNTH (INT_MAX + 1L)
>
> I.e. wouldn't be some arbitrarily huge value, but one right after what
> was defined as the area for the dynamicly allocated PERF_TYPE_
> "namespace" for PMUs, right?
That seems fine. Pedantically it should be (INT_MAX + 1U) otherwise it will
be negative on a 32-bit system.
>
>>> Peter: now its not the PERF_RECORD_ namespace that userspaces want a
>>> chunk of, its PERF_TYPE_, which so far has been pretty stable, grabing
>>> _one_ for event synthesizing things like Intel PT (and ARM's coresight,
>>> I think) directly at include/uapi/linux/perf_event.h's perf_type_id enum
>>> looks cleaner, no?
>
> - Arnaldo
>
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2017-06-22 17:10 +0200 |
| Subject | Re: [PATCH V3 20/37] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tVbU7-6qX-33@gated-at.bofh.it> |
| In reply to | #1672006 |
Em Wed, Jun 21, 2017 at 11:20:03PM +0300, Adrian Hunter escreveu: > On 06/21/2017 08:29 PM, Arnaldo Carvalho de Melo wrote: > > Em Wed, Jun 21, 2017 at 07:41:04PM +0300, Adrian Hunter escreveu: > >> PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently > >> perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation > >> to INT_MAX. > > Oh, forgot about that, guess a comment right beside PERF_TYPE_MAX is in > > demand :-\ > > So why not: > > /* > > * PERF_TYPE_ is dynamically allocated above PERF_TYPE_MAX for PMUs. Presently > > * perf_pmu_register() calls idr_alloc() with end=0 which limits the allocation > > * to INT_MAX. > > */ > > #define PERF_TYPE_SYNTH (INT_MAX + 1L) > > I.e. wouldn't be some arbitrarily huge value, but one right after what > > was defined as the area for the dynamicly allocated PERF_TYPE_ > > "namespace" for PMUs, right? > That seems fine. Pedantically it should be (INT_MAX + 1U) otherwise it will > be negative on a 32-bit system. oh, not pedantic at all, thanks for the fix, will update your patch and continue from there, Ingo already pulled everything up to this point, btw. - Arnaldo
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Adrian Hunter <tipbot@zytor.com> |
|---|---|
| Date | 2017-07-01 11:00 +0200 |
| Subject | [tip:perf/core] perf script: Add 'synth' event type for synthesized events |
| Message-ID | <tYmpZ-P8-55@gated-at.bofh.it> |
| In reply to | #1671598 |
Commit-ID: 1405720d4f2669e5ebaed192bd727aca74f64732
Gitweb: http://git.kernel.org/tip/1405720d4f2669e5ebaed192bd727aca74f64732
Author: Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Wed, 21 Jun 2017 13:17:19 +0300
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 27 Jun 2017 12:03:09 -0300
perf script: Add 'synth' event type for synthesized events
Instruction trace decoders such as Intel PT may have additional information
recorded in the trace. For example, Intel PT has power information and a
there is a new instruction 'ptwrite' that can write a value into a PTWRITE
trace packet.
Such information may be associated with an IP and so can be treated as a
sample (PERF_RECORD_SAMPLE). Custom data can be incorporated in the
sample as raw_data (PERF_SAMPLE_RAW).
However a means of identifying the raw data format is needed. That will
be done by synthesizing an attribute for it.
So add an attribute type for custom synthesized events. Different
synthesized events will be identified by the attribute 'config'.
Committer notes:
Start those PERF_TYPE_ after the PMU range, i.e. after (INT_MAX + 1U),
i.e. after perf_pmu_register() -> idr_alloc(end=0).
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/1498040239-32418-1-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-script.c | 74 +++++++++++++++++++++++++++++++++++----------
tools/perf/util/event.h | 3 ++
2 files changed, 61 insertions(+), 16 deletions(-)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4bce7d8..2999e7e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -119,6 +119,11 @@ struct output_option {
{.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
};
+enum {
+ OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX,
+ OUTPUT_TYPE_MAX
+};
+
/* default set to maintain compatibility with current format */
static struct {
bool user_set;
@@ -126,7 +131,7 @@ static struct {
unsigned int print_ip_opts;
u64 fields;
u64 invalid_fields;
-} output[PERF_TYPE_MAX] = {
+} output[OUTPUT_TYPE_MAX] = {
[PERF_TYPE_HARDWARE] = {
.user_set = false,
@@ -184,12 +189,43 @@ static struct {
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
},
+
+ [OUTPUT_TYPE_SYNTH] = {
+ .user_set = false,
+
+ .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+ PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+ PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+ PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
+
+ .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
+ },
};
+static inline int output_type(unsigned int type)
+{
+ switch (type) {
+ case PERF_TYPE_SYNTH:
+ return OUTPUT_TYPE_SYNTH;
+ default:
+ return type;
+ }
+}
+
+static inline unsigned int attr_type(unsigned int type)
+{
+ switch (type) {
+ case OUTPUT_TYPE_SYNTH:
+ return PERF_TYPE_SYNTH;
+ default:
+ return type;
+ }
+}
+
static bool output_set_by_user(void)
{
int j;
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
if (output[j].user_set)
return true;
}
@@ -210,7 +246,7 @@ static const char *output_field2str(enum perf_output_field field)
return str;
}
-#define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x)
+#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x)
static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
u64 sample_type, const char *sample_msg,
@@ -218,7 +254,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel,
bool allow_user_set)
{
struct perf_event_attr *attr = &evsel->attr;
- int type = attr->type;
+ int type = output_type(attr->type);
const char *evname;
if (attr->sample_type & sample_type)
@@ -348,7 +384,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
static void set_print_ip_opts(struct perf_event_attr *attr)
{
- unsigned int type = attr->type;
+ unsigned int type = output_type(attr->type);
output[type].print_ip_opts = 0;
if (PRINT_FIELD(IP))
@@ -376,14 +412,15 @@ static int perf_session__check_output_opt(struct perf_session *session)
unsigned int j;
struct perf_evsel *evsel;
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
- evsel = perf_session__find_first_evtype(session, j);
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
+ evsel = perf_session__find_first_evtype(session, attr_type(j));
/*
* even if fields is set to 0 (ie., show nothing) event must
* exist if user explicitly includes it on the command line
*/
- if (!evsel && output[j].user_set && !output[j].wildcard_set) {
+ if (!evsel && output[j].user_set && !output[j].wildcard_set &&
+ j != OUTPUT_TYPE_SYNTH) {
pr_err("%s events do not exist. "
"Remove corresponding -F option to proceed.\n",
event_type(j));
@@ -989,6 +1026,7 @@ static void print_sample_bts(struct perf_sample *sample,
struct machine *machine)
{
struct perf_event_attr *attr = &evsel->attr;
+ unsigned int type = output_type(attr->type);
bool print_srcline_last = false;
if (PRINT_FIELD(CALLINDENT))
@@ -996,7 +1034,7 @@ static void print_sample_bts(struct perf_sample *sample,
/* print branch_from information */
if (PRINT_FIELD(IP)) {
- unsigned int print_opts = output[attr->type].print_ip_opts;
+ unsigned int print_opts = output[type].print_ip_opts;
struct callchain_cursor *cursor = NULL;
if (symbol_conf.use_callchain && sample->callchain &&
@@ -1019,7 +1057,7 @@ static void print_sample_bts(struct perf_sample *sample,
/* print branch_to information */
if (PRINT_FIELD(ADDR) ||
((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
- !output[attr->type].user_set)) {
+ !output[type].user_set)) {
printf(" => ");
print_sample_addr(sample, thread, attr);
}
@@ -1215,8 +1253,9 @@ static void process_event(struct perf_script *script,
{
struct thread *thread = al->thread;
struct perf_event_attr *attr = &evsel->attr;
+ unsigned int type = output_type(attr->type);
- if (output[attr->type].fields == 0)
+ if (output[type].fields == 0)
return;
print_sample_start(sample, thread, evsel);
@@ -1263,7 +1302,7 @@ static void process_event(struct perf_script *script,
cursor = &callchain_cursor;
putchar(cursor ? '\n' : ' ');
- sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
+ sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout);
}
if (PRINT_FIELD(IREGS))
@@ -1410,7 +1449,8 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
evlist = *pevlist;
evsel = perf_evlist__last(*pevlist);
- if (evsel->attr.type >= PERF_TYPE_MAX)
+ if (evsel->attr.type >= PERF_TYPE_MAX &&
+ evsel->attr.type != PERF_TYPE_SYNTH)
return 0;
evlist__for_each_entry(evlist, pos) {
@@ -1835,6 +1875,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
type = PERF_TYPE_RAW;
else if (!strcmp(str, "break"))
type = PERF_TYPE_BREAKPOINT;
+ else if (!strcmp(str, "synth"))
+ type = OUTPUT_TYPE_SYNTH;
else {
fprintf(stderr, "Invalid event type in field string.\n");
rc = -EINVAL;
@@ -1865,7 +1907,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
if (output_set_by_user())
pr_warning("Overriding previous field request for all events.\n");
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
output[j].fields = 0;
output[j].user_set = true;
output[j].wildcard_set = true;
@@ -1908,7 +1950,7 @@ parse:
/* add user option to all events types for
* which it is valid
*/
- for (j = 0; j < PERF_TYPE_MAX; ++j) {
+ for (j = 0; j < OUTPUT_TYPE_MAX; ++j) {
if (output[j].invalid_fields & all_output_options[i].field) {
pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
all_output_options[i].str, event_type(j));
@@ -2560,7 +2602,7 @@ int cmd_script(int argc, const char **argv)
OPT_CALLBACK('F', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. "
"+field to add and -field to remove."
- "Valid types: hw,sw,trace,raw. "
+ "Valid types: hw,sw,trace,raw,synth. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
"bpf-output,callindent,insn,insnlen,brstackinsn",
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7c3fa1c..855733c 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -252,6 +252,9 @@ enum auxtrace_error_type {
PERF_AUXTRACE_ERROR_MAX
};
+/* Attribute type for custom synthesized events */
+#define PERF_TYPE_SYNTH (INT_MAX + 1U)
+
/*
* The kernel collects the number of events it couldn't send in a stretch and
* when possible sends this number in a PERF_RECORD_LOST event. The number of
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web