perf tools: some fixes and tweaks
Adrian Hunter
reviewerv4 cover perf tools: some fixes and tweaks
Hi
Here are some fixes and tweaks to perf tools (version 4).
I have added kernel support for matching sample types via PERF_SAMPLE_IDENTIFIER. perf tools support for that required first fixing some other things.
Changes in V4:
perf tools: fix parse_events_terms() freeing local variable on error path
Dropped - covered by David Ahern
perf tools: struct thread has a tid not a pid
Added ack by David Ahern
perf tools: add pid to struct thread
Remove unused function
perf tools: fix missing increment in sample parsing
New patch
perf tools: tidy up sample parsing overflow checking
New patch
perf tools: remove unnecessary callchain validation
New patch
perf tools: remove references to struct ip_event
New patch
perf tools: move struct ip_event
New patch
perf: make events stream always parsable
New patch
perf tools: add support for PERF_SAMPLE_IDENTFIER
New patch
Changes in V3:
perf tools: add pid to struct thread
Split into 2 patches
perf tools: fix ppid in thread__fork()
Dropped for now
Changes in V2:
perf tools: fix missing tool parameter
Fixed one extra occurrence
perf tools: fix parse_events_terms() freeing local variable on error path
Made "freeing" code into a new function
perf tools: validate perf event header size
Corrected byte-swapping
perf tools: allow non-matching sample types
Added comments
Fixed id_pos calculation
id_pos/is_pos updated whenever sample_type changes Removed perf_evlist__sample_type()
Added __perf_evlist__combined_sample_type()
Added perf_evlist__combined_sample_type()
Added perf_evlist__make_sample_types_compatible()
Added ack's to patches acked by Jiri Olsa
Adrian Hunter (21):
perf tools: remove unused parameter
perf tools: fix missing tool parameter
perf tools: fix missing 'finished_round'
perf tools: fix parse_events_terms() segfault on error path perf tools: fix new_term() missing free on error path perf tools: add const specifier to perf_pmu__find name parameter perf tools: tidy duplicated munmap code
perf tools: validate perf event header size
perf tools: add debug prints
perf tools: fix symbol_conf.nr_events
perf tools: allow non-matching sample types
perf tools: struct thread has a tid not a pid
perf tools: add pid to struct thread
perf tools: change "machine" functions to set thread pid perf tools: fix missing increment in sample parsing perf tools: tidy up sample parsing overflow checking perf tools: remove unnecessary callchain validation perf tools: remove references to struct ip_event
perf tools: move struct ip_event
perf: make events stream always parsable
perf tools: add support for PERF_SAMPLE_IDENTFIER
include/uapi/linux/perf_event.h | 3 +- kernel/events/core.c | 11 +- tools/perf/builtin-inject.c | 44 ++++--- tools/perf/builtin-kmem.c | 4 +- tools/perf/builtin-mem.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-sched.c | 12 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-top.c | 10 +- tools/perf/builtin-trace.c | 4 +- tools/perf/tests/hists_link.c | 27 ++++- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/ui/browsers/hists.c | 6 +- tools/perf/util/build-id.c | 6 +- tools/perf/util/callchain.c | 8 -- tools/perf/util/callchain.h | 5 - tools/perf/util/event.c | 6 +- tools/perf/util/event.h | 30 +++-- tools/perf/util/evlist.c | 251 +++++++++++++++++++++++++++++++++++---- tools/perf/util/evlist.h | 9 +- tools/perf/util/evsel.c | 256 +++++++++++++++++++++++++++++++++------- tools/perf/util/evsel.h | 13 +- tools/perf/util/header.c | 8 +- tools/perf/util/header.h | 6 +- tools/perf/util/machine.c | 47 +++++--- tools/perf/util/machine.h | 6 +- tools/perf/util/parse-events.c | 4 +- tools/perf/util/pmu.c | 14 +-- tools/perf/util/pmu.h | 2 +- tools/perf/util/session.c | 58 ++++----- tools/perf/util/sort.c | 6 +- tools/perf/util/thread.c | 11 +- tools/perf/util/thread.h | 5 +- tools/perf/util/tool.h | 9 +- 34 files changed, 658 insertions(+), 231 deletions(-)
Regards
Adrian
Adrian Hunter
reviewerPATCH v4 1/21 perf tools: remove unused parameter
'machine' is unused in 'perf_event__repipe_synth()' and some callers pass NULL anyway. So remove it.
--- tools/perf/builtin-inject.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
tools/perf/builtin-inject.c +9 -10
@@ -38,8 +38,7 @@ struct event_entry { };static int perf_event__repipe_synth (struct perf_tool *tool, -union perf_event *event, -struct machine *machine__maybe_unused ) +union perf_event *event) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);uint32_t size;
@@ -65,20 +64,20 @@ static int perf_event__repipe_op2_synth(struct perf_tool *tool,struct perf_session *session __maybe_unused) { -return perf_event__repipe_synth (tool, event,NULL ); +return perf_event__repipe_synth (tool, event); }static int perf_event__repipe_event_type_synth (struct perf_tool *tool,union perf_event *event) { -return perf_event__repipe_synth (tool, event,NULL ); +return perf_event__repipe_synth (tool, event); }static int perf_event__repipe_tracing_data_synth (union perf_event *event,struct perf_session *session__maybe_unused ) { -return perf_event__repipe_synth (NULL , event,NULL ); +return perf_event__repipe_synth (NULL , event); } static int perf_event__repipe_attr(union perf_event *event,
@@ -89,15 +88,15 @@ static int perf_event__repipe_attr(union perf_event *event,if (ret)return ret; -return perf_event__repipe_synth (NULL , event,NULL ); +return perf_event__repipe_synth (NULL , event); }static int perf_event__repipe (struct perf_tool *tool,union perf_event *event,struct perf_sample *sample__maybe_unused , -struct machine *machine) +struct machine *machine__maybe_unused ) { -return perf_event__repipe_synth (tool, event, machine); +return perf_event__repipe_synth (tool, event); } typedef int (*inject_handler)(struct perf_tool *tool,
@@ -119,7 +118,7 @@ static int perf_event__repipe_sample(struct perf_tool *tool,build_id__mark_dso_hit (tool, event, sample, evsel, machine); -return perf_event__repipe_synth (tool, event, machine); +return perf_event__repipe_synth (tool, event); } static int perf_event__repipe_mmap(struct perf_tool *tool,
@@ -153,7 +152,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event, {int err; -perf_event__repipe_synth (NULL , event,NULL ); +perf_event__repipe_synth (NULL , event); err =perf_event__process_tracing_data (event, session);return err;
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf inject: Remove unused parameter
perf inject: Remove unused parameter
Commit-ID: 63c2c9f8f24378ebf46d4a9d542863bb733ef05c Gitweb: http://git.kernel.org/tip/63c2c9f8f24378ebf46d4a9d542863bb733ef05c Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:20 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:52:47 -0300
perf inject: Remove unused parameter
The 'machine' parameter is unused in 'perf_event__repipe_synth()' and some callers pass NULL anyway. So remove it.
--- tools/perf/builtin-inject.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
tools/perf/builtin-inject.c +9 -10
@@ -38,8 +38,7 @@ struct event_entry { };static int perf_event__repipe_synth (struct perf_tool *tool, -union perf_event *event, -struct machine *machine__maybe_unused ) +union perf_event *event) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);uint32_t size;
@@ -65,20 +64,20 @@ static int perf_event__repipe_op2_synth(struct perf_tool *tool,struct perf_session *session __maybe_unused) { -return perf_event__repipe_synth (tool, event,NULL ); +return perf_event__repipe_synth (tool, event); }static int perf_event__repipe_event_type_synth (struct perf_tool *tool,union perf_event *event) { -return perf_event__repipe_synth (tool, event,NULL ); +return perf_event__repipe_synth (tool, event); }static int perf_event__repipe_tracing_data_synth (union perf_event *event,struct perf_session *session__maybe_unused ) { -return perf_event__repipe_synth (NULL , event,NULL ); +return perf_event__repipe_synth (NULL , event); } static int perf_event__repipe_attr(union perf_event *event,
@@ -89,15 +88,15 @@ static int perf_event__repipe_attr(union perf_event *event,if (ret)return ret; -return perf_event__repipe_synth (NULL , event,NULL ); +return perf_event__repipe_synth (NULL , event); }static int perf_event__repipe (struct perf_tool *tool,union perf_event *event,struct perf_sample *sample__maybe_unused , -struct machine *machine) +struct machine *machine__maybe_unused ) { -return perf_event__repipe_synth (tool, event, machine); +return perf_event__repipe_synth (tool, event); } typedef int (*inject_handler)(struct perf_tool *tool,
@@ -119,7 +118,7 @@ static int perf_event__repipe_sample(struct perf_tool *tool,build_id__mark_dso_hit (tool, event, sample, evsel, machine); -return perf_event__repipe_synth (tool, event, machine); +return perf_event__repipe_synth (tool, event); } static int perf_event__repipe_mmap(struct perf_tool *tool,
@@ -153,7 +152,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event, {int err; -perf_event__repipe_synth (NULL , event,NULL ); +perf_event__repipe_synth (NULL , event); err =perf_event__process_tracing_data (event, session);return err;
Adrian Hunter
reviewerPATCH v4 2/21 perf tools: fix missing tool parameter
In reply to Adrian Hunterperf inject expects to get a reference to 'struct perf_inject' from its 'tool' member. For that to work, 'tool' needs to be a parameter of all tool callbacks. Make it so.
--- tools/perf/builtin-inject.c | 26 +++++++++++--------------- tools/perf/util/header.c | 6 ++++-- tools/perf/util/header.h | 6 ++++-- tools/perf/util/session.c | 11 +++++++---- tools/perf/util/tool.h | 9 ++++----- 5 files changed, 30 insertions(+), 28 deletions(-)
tools/perf/builtin-inject.c +11 -15
@@ -73,22 +73,17 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -static int perf_event__repipe_tracing_data_synth (union perf_event *event, -struct perf_session *session -__maybe_unused ) -{ -return perf_event__repipe_synth (NULL , event); -} - -static int perf_event__repipe_attr (union perf_event *event, -struct perf_evlist **pevlist__maybe_unused ) +static int perf_event__repipe_attr (struct perf_tool *tool, +union perf_event *event, +struct perf_evlist **pevlist) {int ret; - ret =perf_event__process_attr (event, pevlist); + + ret =perf_event__process_attr (tool, event, pevlist);if (ret)return ret; -return perf_event__repipe_synth (NULL , event); +return perf_event__repipe_synth (tool, event); } static int perf_event__repipe(struct perf_tool *tool,
@@ -147,13 +142,14 @@ static int perf_event__repipe_fork(struct perf_tool *tool,return err; } -static int perf_event__repipe_tracing_data (union perf_event *event, +static int perf_event__repipe_tracing_data (struct perf_tool *tool, +union perf_event *event,struct perf_session *session) {int err; -perf_event__repipe_synth (NULL , event); - err =perf_event__process_tracing_data (event, session); +perf_event__repipe_synth (tool, event); + err =perf_event__process_tracing_data (tool, event, session);return err; }
@@ -407,7 +403,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .unthrottle = perf_event__repipe, .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, - .tracing_data = perf_event__repipe_tracing_data_synth, + .tracing_data = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-",
tools/perf/util/header.c +4 -2
@@ -2922,7 +2922,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,return err; } -int perf_event__process_attr (union perf_event *event, +int perf_event__process_attr (struct perf_tool *tool__maybe_unused , +union perf_event *event,struct perf_evlist **pevlist) {u32 i, ids, n_ids;
@@ -3063,7 +3064,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,return aligned_size; } -int perf_event__process_tracing_data (union perf_event *event, +int perf_event__process_tracing_data (struct perf_tool *tool__maybe_unused , +union perf_event *event,struct perf_session *session) {ssize_t size_read, padding, size = event->tracing_data.size;
tools/perf/util/header.h +4 -2
@@ -130,7 +130,8 @@ int perf_event__synthesize_attr(struct perf_tool *tool,int perf_event__synthesize_attrs (struct perf_tool *tool,struct perf_session *session,perf_event__handler_t process); -int perf_event__process_attr (union perf_event *event,struct perf_evlist **pevlist); +int perf_event__process_attr (struct perf_tool *tool,union perf_event *event, +struct perf_evlist **pevlist); int perf_event__synthesize_event_type(struct perf_tool *tool, u64 event_id, char *name,
@@ -145,7 +146,8 @@ int perf_event__process_event_type(struct perf_tool *tool,int perf_event__synthesize_tracing_data (struct perf_tool *tool,int fd,struct perf_evlist *evlist,perf_event__handler_t process); -int perf_event__process_tracing_data (union perf_event *event, +int perf_event__process_tracing_data (struct perf_tool *tool, +union perf_event *event,struct perf_session *session); int perf_event__synthesize_build_id(struct perf_tool *tool,
tools/perf/util/session.c +7 -4
@@ -193,7 +193,9 @@ void perf_session__delete(struct perf_session *self)vdso__exit (); } -static int process_event_synth_tracing_data_stub (union perf_event *event +static int process_event_synth_tracing_data_stub (struct perf_tool *tool +__maybe_unused , +union perf_event *event__maybe_unused ,struct perf_session *session__maybe_unused )
@@ -202,7 +204,8 @@ static int process_event_synth_tracing_data_stub(union perf_event *eventreturn 0 ; } -static int process_event_synth_attr_stub (union perf_event *event__maybe_unused , +static int process_event_synth_attr_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused ,struct perf_evlist **pevlist__maybe_unused ) {
@@ -921,7 +924,7 @@ static int perf_session__process_user_event(struct perf_session *session, union/* These events are processed right away */ switch (event->header.type) {case PERF_RECORD_HEADER_ATTR : - err = tool->attr (event, &session->evlist); + err = tool->attr (tool, event, &session->evlist);if (err ==0 )perf_session__set_id_hdr_size (session);return err;
@@ -930,7 +933,7 @@ static int perf_session__process_user_event(struct perf_session *session, unioncase PERF_RECORD_HEADER_TRACING_DATA :/* setup for reading amidst mmap */ lseek (session->fd, file_offset,SEEK_SET ); -return tool->tracing_data (event, session); +return tool->tracing_data (tool, event, session);case PERF_RECORD_HEADER_BUILD_ID :return tool->build_id (tool, event, session);case PERF_RECORD_FINISHED_ROUND :
tools/perf/util/tool.h +4 -5
@@ -18,12 +18,11 @@ typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,typedef int (*event_op )(struct perf_tool *tool,union perf_event *event,struct perf_sample *sample,struct machine *machine); -typedef int (*event_attr_op )(union perf_event *event, +typedef int (*event_attr_op )(struct perf_tool *tool, +union perf_event *event,struct perf_evlist **pevlist); -typedef int (*event_simple_op )(struct perf_tool *tool,union perf_event *event); -typedef int (*event_synth_op )(union perf_event *event, -struct perf_session *session); +typedef int (*event_simple_op )(struct perf_tool *tool,union perf_event *event);typedef int (*event_op2 )(struct perf_tool *tool,union perf_event *event,struct perf_session *session);
@@ -39,7 +38,7 @@ struct perf_tool { throttle, unthrottle;event_attr_op attr; -event_synth_op tracing_data; +event_op2 tracing_data;event_simple_op event_type;event_op2 finished_round, build_id;
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Fix missing tool parameter
perf tools: Fix missing tool parameter
Commit-ID: 47c3d1091cb68e727b840efd6fa3709d5b1ddfc2 Gitweb: http://git.kernel.org/tip/47c3d1091cb68e727b840efd6fa3709d5b1ddfc2 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:21 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:52:49 -0300
perf tools: Fix missing tool parameter
The 'inject' command expects to get a reference to 'struct perf_inject' from its 'tool' member. For that to work, 'tool' needs to be a parameter of all tool callbacks. Make it so.
--- tools/perf/builtin-inject.c | 26 +++++++++++--------------- tools/perf/util/header.c | 6 ++++-- tools/perf/util/header.h | 6 ++++-- tools/perf/util/session.c | 11 +++++++---- tools/perf/util/tool.h | 9 ++++----- 5 files changed, 30 insertions(+), 28 deletions(-)
tools/perf/builtin-inject.c +11 -15
@@ -73,22 +73,17 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -static int perf_event__repipe_tracing_data_synth (union perf_event *event, -struct perf_session *session -__maybe_unused ) -{ -return perf_event__repipe_synth (NULL , event); -} - -static int perf_event__repipe_attr (union perf_event *event, -struct perf_evlist **pevlist__maybe_unused ) +static int perf_event__repipe_attr (struct perf_tool *tool, +union perf_event *event, +struct perf_evlist **pevlist) {int ret; - ret =perf_event__process_attr (event, pevlist); + + ret =perf_event__process_attr (tool, event, pevlist);if (ret)return ret; -return perf_event__repipe_synth (NULL , event); +return perf_event__repipe_synth (tool, event); } static int perf_event__repipe(struct perf_tool *tool,
@@ -147,13 +142,14 @@ static int perf_event__repipe_fork(struct perf_tool *tool,return err; } -static int perf_event__repipe_tracing_data (union perf_event *event, +static int perf_event__repipe_tracing_data (struct perf_tool *tool, +union perf_event *event,struct perf_session *session) {int err; -perf_event__repipe_synth (NULL , event); - err =perf_event__process_tracing_data (event, session); +perf_event__repipe_synth (tool, event); + err =perf_event__process_tracing_data (tool, event, session);return err; }
@@ -407,7 +403,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .unthrottle = perf_event__repipe, .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, - .tracing_data = perf_event__repipe_tracing_data_synth, + .tracing_data = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-",
tools/perf/util/header.c +4 -2
@@ -2922,7 +2922,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,return err; } -int perf_event__process_attr (union perf_event *event, +int perf_event__process_attr (struct perf_tool *tool__maybe_unused , +union perf_event *event,struct perf_evlist **pevlist) {u32 i, ids, n_ids;
@@ -3065,7 +3066,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,return aligned_size; } -int perf_event__process_tracing_data (union perf_event *event, +int perf_event__process_tracing_data (struct perf_tool *tool__maybe_unused , +union perf_event *event,struct perf_session *session) {ssize_t size_read, padding, size = event->tracing_data.size;
tools/perf/util/header.h +4 -2
@@ -130,7 +130,8 @@ int perf_event__synthesize_attr(struct perf_tool *tool,int perf_event__synthesize_attrs (struct perf_tool *tool,struct perf_session *session,perf_event__handler_t process); -int perf_event__process_attr (union perf_event *event,struct perf_evlist **pevlist); +int perf_event__process_attr (struct perf_tool *tool,union perf_event *event, +struct perf_evlist **pevlist); int perf_event__synthesize_event_type(struct perf_tool *tool, u64 event_id, char *name,
@@ -145,7 +146,8 @@ int perf_event__process_event_type(struct perf_tool *tool,int perf_event__synthesize_tracing_data (struct perf_tool *tool,int fd,struct perf_evlist *evlist,perf_event__handler_t process); -int perf_event__process_tracing_data (union perf_event *event, +int perf_event__process_tracing_data (struct perf_tool *tool, +union perf_event *event,struct perf_session *session); int perf_event__synthesize_build_id(struct perf_tool *tool,
tools/perf/util/session.c +7 -4
@@ -193,7 +193,9 @@ void perf_session__delete(struct perf_session *self)vdso__exit (); } -static int process_event_synth_tracing_data_stub (union perf_event *event +static int process_event_synth_tracing_data_stub (struct perf_tool *tool +__maybe_unused , +union perf_event *event__maybe_unused ,struct perf_session *session__maybe_unused )
@@ -202,7 +204,8 @@ static int process_event_synth_tracing_data_stub(union perf_event *eventreturn 0 ; } -static int process_event_synth_attr_stub (union perf_event *event__maybe_unused , +static int process_event_synth_attr_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused ,struct perf_evlist **pevlist__maybe_unused ) {
@@ -921,7 +924,7 @@ static int perf_session__process_user_event(struct perf_session *session, union/* These events are processed right away */ switch (event->header.type) {case PERF_RECORD_HEADER_ATTR : - err = tool->attr (event, &session->evlist); + err = tool->attr (tool, event, &session->evlist);if (err ==0 )perf_session__set_id_hdr_size (session);return err;
@@ -930,7 +933,7 @@ static int perf_session__process_user_event(struct perf_session *session, unioncase PERF_RECORD_HEADER_TRACING_DATA :/* setup for reading amidst mmap */ lseek (session->fd, file_offset,SEEK_SET ); -return tool->tracing_data (event, session); +return tool->tracing_data (tool, event, session);case PERF_RECORD_HEADER_BUILD_ID :return tool->build_id (tool, event, session);case PERF_RECORD_FINISHED_ROUND :
tools/perf/util/tool.h +4 -5
@@ -18,12 +18,11 @@ typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,typedef int (*event_op )(struct perf_tool *tool,union perf_event *event,struct perf_sample *sample,struct machine *machine); -typedef int (*event_attr_op )(union perf_event *event, +typedef int (*event_attr_op )(struct perf_tool *tool, +union perf_event *event,struct perf_evlist **pevlist); -typedef int (*event_simple_op )(struct perf_tool *tool,union perf_event *event); -typedef int (*event_synth_op )(union perf_event *event, -struct perf_session *session); +typedef int (*event_simple_op )(struct perf_tool *tool,union perf_event *event);typedef int (*event_op2 )(struct perf_tool *tool,union perf_event *event,struct perf_session *session);
@@ -39,7 +38,7 @@ struct perf_tool { throttle, unthrottle;event_attr_op attr; -event_synth_op tracing_data; +event_op2 tracing_data;event_simple_op event_type;event_op2 finished_round, build_id;
Adrian Hunter
reviewerPATCH v4 3/21 perf tools: fix missing 'finished_round'
In reply to Adrian HunterBy default, perf inject should "repipe" all events including 'finished_round'.
--- tools/perf/builtin-inject.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-inject.c +1 -0
@@ -404,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, .tracing_data = perf_event__repipe_op2_synth, + .finished_round = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-",
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf inject: Add missing 'finished_round'
perf inject: Add missing 'finished_round'
Commit-ID: a609bda78203a21fb0e78b9d5b4ab911678e4ebb Gitweb: http://git.kernel.org/tip/a609bda78203a21fb0e78b9d5b4ab911678e4ebb Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:22 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:52:50 -0300
perf inject: Add missing 'finished_round'
By default, perf inject should "repipe" all events including 'finished_round'.
--- tools/perf/builtin-inject.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-inject.c +1 -0
@@ -404,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, .tracing_data = perf_event__repipe_op2_synth, + .finished_round = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-",
Adrian Hunter
reviewerPATCH v4 4/21 perf tools: fix parse_events_terms() segfault on error path
In reply to Adrian HunterOn the error path, 'data.terms' may not have been
initialised.
--- tools/perf/util/parse-events.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +2 -1
@@ -883,7 +883,8 @@ int parse_events_terms(struct list_head *terms, const char *str)return 0 ; } -parse_events__free_terms (data.terms); +if (data.terms) +parse_events__free_terms (data.terms);return ret; }
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/urgent] perf tools: Fix parse_events_terms() segfault on error path
perf tools: Fix parse_events_terms() segfault on error path
Commit-ID: b2c34fde048f3c85ef0716a8cdabbe46ac67d1e6 Gitweb: http://git.kernel.org/tip/b2c34fde048f3c85ef0716a8cdabbe46ac67d1e6 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:23 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 8 Jul 2013 17:45:41 -0300
perf tools: Fix parse_events_terms() segfault on error path
On the error path, 'data.terms' may not have been initialised.
--- tools/perf/util/parse-events.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +2 -1
@@ -860,7 +860,8 @@ int parse_events_terms(struct list_head *terms, const char *str)return 0 ; } -parse_events__free_terms (data.terms); +if (data.terms) +parse_events__free_terms (data.terms);return ret; }
Adrian Hunter
reviewerPATCH v4 5/21 perf tools: fix new_term() missing free on error path
In reply to Adrian HunterOn the error path, newly allocated 'term' must be freed.
--- tools/perf/util/parse-events.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/parse-events.c +1 -0
@@ -1207,6 +1207,7 @@ static int new_term(struct parse_events_term **_term, int type_val, term->val.str = str;break ;default : +free (term);return -EINVAL ; }
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/urgent] perf tools: Fix new_term() missing free on error path
perf tools: Fix new_term() missing free on error path
Commit-ID: 4be8be6b430611def94bcd583b7b302d197a9520 Gitweb: http://git.kernel.org/tip/4be8be6b430611def94bcd583b7b302d197a9520 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:24 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 8 Jul 2013 17:45:56 -0300
perf tools: Fix new_term() missing free on error path
On the error path, newly allocated 'term' must be freed.
--- tools/perf/util/parse-events.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/parse-events.c +1 -0
@@ -1184,6 +1184,7 @@ static int new_term(struct parse_events_term **_term, int type_val, term->val.str = str;break ;default : +free (term);return -EINVAL ; }
Adrian Hunter
reviewerPATCH v4 6/21 perf tools: add const specifier to perf_pmu__find name parameter
In reply to Adrian HunterThe name parameter is constant, declare it so.
--- tools/perf/util/pmu.c | 14 +++++++------- tools/perf/util/pmu.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/util/pmu.c +7 -7
@@ -73,7 +73,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head)* located at: * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. */ -static int pmu_format (char *name,struct list_head *format) +static int pmu_format (const char *name,struct list_head *format) {struct stat st;char path[PATH_MAX ];
@@ -162,7 +162,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)* Reading the pmu event aliases definition, which should be located at: * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. */ -static int pmu_aliases (char *name,struct list_head *head) +static int pmu_aliases (const char *name,struct list_head *head) {struct stat st;char path[PATH_MAX ];
@@ -208,7 +208,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,* located at: * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. */ -static int pmu_type (char *name,__u32 *type) +static int pmu_type (const char *name,__u32 *type) {struct stat st;char path[PATH_MAX ];
@@ -266,7 +266,7 @@ static void pmu_read_sysfs(void)closedir (dir); } -static struct cpu_map *pmu_cpumask (char *name) +static struct cpu_map *pmu_cpumask (const char *name) {struct stat st;char path[PATH_MAX ];
@@ -293,7 +293,7 @@ static struct cpu_map *pmu_cpumask(char *name)return cpus; } -static struct perf_pmu *pmu_lookup (char *name) +static struct perf_pmu *pmu_lookup (const char *name) {struct perf_pmu *pmu;LIST_HEAD (format);
@@ -330,7 +330,7 @@ static struct perf_pmu *pmu_lookup(char *name)return pmu; } -static struct perf_pmu *pmu_find (char *name) +static struct perf_pmu *pmu_find (const char *name) {struct perf_pmu *pmu;
@@ -356,7 +356,7 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)return NULL ; } -struct perf_pmu *perf_pmu__find (char *name) +struct perf_pmu *perf_pmu__find (const char *name) {struct perf_pmu *pmu;
tools/perf/util/pmu.h +1 -1
@@ -21,7 +21,7 @@ struct perf_pmu {struct list_head list; }; -struct perf_pmu *perf_pmu__find (char *name); +struct perf_pmu *perf_pmu__find (const char *name);int perf_pmu__config (struct perf_pmu *pmu,struct perf_event_attr *attr,struct list_head *head_terms); int perf_pmu__config_terms(struct list_head *formats,
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Add const specifier to perf_pmu__find name parameter
perf tools: Add const specifier to perf_pmu__find name parameter
Commit-ID: b6b96fb48f75d62858b39baf13c83c4504642f15 Gitweb: http://git.kernel.org/tip/b6b96fb48f75d62858b39baf13c83c4504642f15 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:25 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:52:52 -0300
perf tools: Add const specifier to perf_pmu__find name parameter
The name parameter is constant, declare it so.
--- tools/perf/util/pmu.c | 14 +++++++------- tools/perf/util/pmu.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/util/pmu.c +7 -7
@@ -73,7 +73,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head)* located at: * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. */ -static int pmu_format (char *name,struct list_head *format) +static int pmu_format (const char *name,struct list_head *format) {struct stat st;char path[PATH_MAX ];
@@ -162,7 +162,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)* Reading the pmu event aliases definition, which should be located at: * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. */ -static int pmu_aliases (char *name,struct list_head *head) +static int pmu_aliases (const char *name,struct list_head *head) {struct stat st;char path[PATH_MAX ];
@@ -208,7 +208,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,* located at: * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. */ -static int pmu_type (char *name,__u32 *type) +static int pmu_type (const char *name,__u32 *type) {struct stat st;char path[PATH_MAX ];
@@ -266,7 +266,7 @@ static void pmu_read_sysfs(void)closedir (dir); } -static struct cpu_map *pmu_cpumask (char *name) +static struct cpu_map *pmu_cpumask (const char *name) {struct stat st;char path[PATH_MAX ];
@@ -293,7 +293,7 @@ static struct cpu_map *pmu_cpumask(char *name)return cpus; } -static struct perf_pmu *pmu_lookup (char *name) +static struct perf_pmu *pmu_lookup (const char *name) {struct perf_pmu *pmu;LIST_HEAD (format);
@@ -330,7 +330,7 @@ static struct perf_pmu *pmu_lookup(char *name)return pmu; } -static struct perf_pmu *pmu_find (char *name) +static struct perf_pmu *pmu_find (const char *name) {struct perf_pmu *pmu;
@@ -356,7 +356,7 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)return NULL ; } -struct perf_pmu *perf_pmu__find (char *name) +struct perf_pmu *perf_pmu__find (const char *name) {struct perf_pmu *pmu;
tools/perf/util/pmu.h +1 -1
@@ -21,7 +21,7 @@ struct perf_pmu {struct list_head list; }; -struct perf_pmu *perf_pmu__find (char *name); +struct perf_pmu *perf_pmu__find (const char *name);int perf_pmu__config (struct perf_pmu *pmu,struct perf_event_attr *attr,struct list_head *head_terms); int perf_pmu__config_terms(struct list_head *formats,
Adrian Hunter
reviewerPATCH v4 7/21 perf tools: tidy duplicated munmap code
In reply to Adrian HunterThe same lines of code are used in three places.
Make it a new function '__perf_evlist__munmap()'.
--- tools/perf/util/evlist.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-)
tools/perf/util/evlist.c +14 -18
@@ -403,16 +403,20 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)return event; } +static void __perf_evlist__munmap (struct perf_evlist *evlist,int idx) +{ +if (evlist->mmap[idx].base !=NULL ) { +munmap (evlist->mmap[idx].base, evlist->mmap_len); + evlist->mmap[idx].base =NULL ; + } +} +void perf_evlist__munmap (struct perf_evlist *evlist) {int i; -for (i =0 ; i < evlist->nr_mmaps; i++) { -if (evlist->mmap[i].base !=NULL ) { -munmap (evlist->mmap[i].base, evlist->mmap_len); - evlist->mmap[i].base =NULL ; - } - } +for (i =0 ; i < evlist->nr_mmaps; i++) +__perf_evlist__munmap (evlist, i);free (evlist->mmap); evlist->mmap =NULL ;
@@ -477,12 +481,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mreturn 0 ; out_unmap: -for (cpu =0 ; cpu < nr_cpus; cpu++) { -if (evlist->mmap[cpu].base !=NULL ) { -munmap (evlist->mmap[cpu].base, evlist->mmap_len); - evlist->mmap[cpu].base =NULL ; - } - } +for (cpu =0 ; cpu < nr_cpus; cpu++) +__perf_evlist__munmap (evlist, cpu);return -1 ; }
@@ -517,12 +517,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, inreturn 0 ; out_unmap: -for (thread =0 ; thread < nr_threads; thread++) { -if (evlist->mmap[thread].base !=NULL ) { -munmap (evlist->mmap[thread].base, evlist->mmap_len); - evlist->mmap[thread].base =NULL ; - } - } +for (thread =0 ; thread < nr_threads; thread++) +__perf_evlist__munmap (evlist, thread);return -1 ; }
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf evlist: Tidy duplicated munmap code
perf evlist: Tidy duplicated munmap code
Commit-ID: 93edcbd91d888c7530c7fc749176fc935b8e2287 Gitweb: http://git.kernel.org/tip/93edcbd91d888c7530c7fc749176fc935b8e2287 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:26 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:52:54 -0300
perf evlist: Tidy duplicated munmap code
The same lines of code are used in three places. Make it a new function '__perf_evlist__munmap()'.
--- tools/perf/util/evlist.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-)
tools/perf/util/evlist.c +14 -18
@@ -403,16 +403,20 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)return event; } +static void __perf_evlist__munmap (struct perf_evlist *evlist,int idx) +{ +if (evlist->mmap[idx].base !=NULL ) { +munmap (evlist->mmap[idx].base, evlist->mmap_len); + evlist->mmap[idx].base =NULL ; + } +} +void perf_evlist__munmap (struct perf_evlist *evlist) {int i; -for (i =0 ; i < evlist->nr_mmaps; i++) { -if (evlist->mmap[i].base !=NULL ) { -munmap (evlist->mmap[i].base, evlist->mmap_len); - evlist->mmap[i].base =NULL ; - } - } +for (i =0 ; i < evlist->nr_mmaps; i++) +__perf_evlist__munmap (evlist, i);free (evlist->mmap); evlist->mmap =NULL ;
@@ -477,12 +481,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mreturn 0 ; out_unmap: -for (cpu =0 ; cpu < nr_cpus; cpu++) { -if (evlist->mmap[cpu].base !=NULL ) { -munmap (evlist->mmap[cpu].base, evlist->mmap_len); - evlist->mmap[cpu].base =NULL ; - } - } +for (cpu =0 ; cpu < nr_cpus; cpu++) +__perf_evlist__munmap (evlist, cpu);return -1 ; }
@@ -517,12 +517,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, inreturn 0 ; out_unmap: -for (thread =0 ; thread < nr_threads; thread++) { -if (evlist->mmap[thread].base !=NULL ) { -munmap (evlist->mmap[thread].base, evlist->mmap_len); - evlist->mmap[thread].base =NULL ; - } - } +for (thread =0 ; thread < nr_threads; thread++) +__perf_evlist__munmap (evlist, thread);return -1 ; }
Adrian Hunter
reviewerPATCH v4 8/21 perf tools: validate perf event header size
In reply to Adrian Hunter'size' includes the header so must be at least 'sizeof(struct perf_event_header)'. Error out immediately if that is not the case. Also don't byte-swap the header until it is actually "fetched" from the mmap region.
--- tools/perf/util/session.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
tools/perf/util/session.c +10 -4
@@ -1094,8 +1094,10 @@ more:perf_event_header__bswap (&event->header); size = event->header.size; -if (size ==0 ) - size =8 ; +if (size <sizeof (struct perf_event_header )) { +pr_err ("bad event header size\n" ); + goto out_err; + }if (size > cur_size) {void *new =realloc (buf, size);
@@ -1164,8 +1166,12 @@ fetch_mmaped_event(struct perf_session *session,if (session->header.needs_swap)perf_event_header__bswap (&event->header); -if (head + event->header.size > mmap_size) +if (head + event->header.size > mmap_size) { +/* We're not fetching the event so swap back again */ +if (session->header.needs_swap) +perf_event_header__bswap (&event->header);return NULL ; + }return event; }
@@ -1245,7 +1251,7 @@ more: size = event->header.size; -if (size ==0 || +if (size <sizeof (struct perf_event_header ) ||perf_session__process_event (session, event, tool, file_pos) <0 ) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", file_offset + head, event->header.size,
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: Validate perf event header size
perf tools: Validate perf event header size
Commit-ID: 27389d7823f573be8eaff32fb4abe564e181eb71 Gitweb: http://git.kernel.org/tip/27389d7823f573be8eaff32fb4abe564e181eb71 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:27 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:53:48 -0300
perf tools: Validate perf event header size
The 'size' variable includes the header so must be at least 'sizeof(struct perf_event_header)'. Error out immediately if that is not the case. Also don't byte-swap the header until it is actually "fetched" from the mmap region.
--- tools/perf/util/session.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
tools/perf/util/session.c +10 -4
@@ -1094,8 +1094,10 @@ more:perf_event_header__bswap (&event->header); size = event->header.size; -if (size ==0 ) - size =8 ; +if (size <sizeof (struct perf_event_header )) { +pr_err ("bad event header size\n" ); + goto out_err; + }if (size > cur_size) {void *new =realloc (buf, size);
@@ -1164,8 +1166,12 @@ fetch_mmaped_event(struct perf_session *session,if (session->header.needs_swap)perf_event_header__bswap (&event->header); -if (head + event->header.size > mmap_size) +if (head + event->header.size > mmap_size) { +/* We're not fetching the event so swap back again */ +if (session->header.needs_swap) +perf_event_header__bswap (&event->header);return NULL ; + }return event; }
@@ -1245,7 +1251,7 @@ more: size = event->header.size; -if (size ==0 || +if (size <sizeof (struct perf_event_header ) ||perf_session__process_event (session, event, tool, file_pos) <0 ) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", file_offset + head, event->header.size,
Adrian Hunter
reviewerPATCH v4 9/21 perf tools: add debug prints
In reply to Adrian HunterIt is useful to see the arguments to perf_event_open and whether the perf events ring buffer was mmapped per-cpu or per-thread. That information will now be displayed when verbose is 2 i.e option -vv
--- tools/perf/util/evlist.c | 3 +++ tools/perf/util/evsel.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)
tools/perf/util/evlist.c +3 -0
@@ -14,6 +14,7 @@#include "target.h" #include "evlist.h" #include "evsel.h" +#include "debug.h" #include <unistd.h> #include "parse-events.h"
@@ -454,6 +455,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mint nr_cpus =cpu_map__nr (evlist->cpus);int nr_threads =thread_map__nr (evlist->threads); +pr_debug2 ("perf event ring buffer mmapped per cpu\n" );for (cpu =0 ; cpu < nr_cpus; cpu++) {int output =-1 ;
@@ -492,6 +494,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, inint thread;int nr_threads =thread_map__nr (evlist->threads); +pr_debug2 ("perf event ring buffer mmapped per thread\n" );for (thread =0 ; thread < nr_threads; thread++) {int output =-1 ;
tools/perf/util/evsel.c +52 -0
76 lines not on this page · raw message
Signature · 1 line
1.7.11.7
Re: [PATCH V4 09/21] perf tools: add debug prints
Em Thu, Jul 04, 2013 at 04:20:28PM +0300, Adrian Hunter escreveu:
Quoted 53 lines
It is useful to see the arguments to
perf_event_openand whether the perf events ring buffer was mmapped per-cpu or per-thread. That information will now be displayed when verbose is 2 i.e option -vvSigned-off-by Adrian Hunter <[email protected]>Acked-by Jiri Olsa <[email protected]>--- tools/perf/util/evlist.c | 3 +++ tools/perf/util/evsel.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)tools/perf/util/evlist.c +3
-0@@ -14,6 +14,7 @@#include "target.h" #include "evlist.h" #include "evsel.h" +#include "debug.h" #include <unistd.h> #include "parse-events.h" @@ -454,6 +455,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mint nr_cpus =cpu_map__nr (evlist->cpus);int nr_threads =thread_map__nr (evlist->threads); +pr_debug2 ("perf event ring buffer mmapped per cpu\n" );for (cpu =0 ; cpu < nr_cpus; cpu++) {int output =-1 ;@@ -492,6 +494,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, inint thread;int nr_threads =thread_map__nr (evlist->threads); +pr_debug2 ("perf event ring buffer mmapped per thread\n" );for (thread =0 ; thread < nr_threads; thread++) {int output =-1 ;tools/perf/util/evsel.c +1
-0@@ -21,6 +21,7 @@#include "thread_map.h" #include "target.h" #include "perf_regs.h" +#include "debug.h" static struct { bool sample_id_all;
tools/perf/util/evsel.c static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) · line 822
Quoted 5 lines
tools/perf/util/evsel.c +2
-0@@ -817,6 +818,54 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)return fd; } +static void show_attr (struct perf_event_attr *attr) +{
These things have been done usually as:
size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
Take a look at dso__fprintf() for instance, and grep for __fprintf on tools/perf for other examples.
And then you can do just one test of (verbose >= 2) to call this function.
Quoted 68 lines
tools/perf/util/evsel.c +49
-0+pr_debug2 ("------------------------------------------------------------\n" ); +pr_debug2 ("perf_event_attr:\n" ); +pr_debug2 (" type %u\n" , attr->type); +pr_debug2 (" size %u\n" , attr->size); +pr_debug2 (" config %#" PRIx64"\n" , (uint64_t )attr->config); +pr_debug2 (" sample_period %" PRIu64"\n" , (uint64_t )attr->sample_period); +pr_debug2 (" sample_freq %" PRIu64"\n" , (uint64_t )attr->sample_freq); +pr_debug2 (" sample_type %#" PRIx64"\n" , (uint64_t )attr->sample_type); +pr_debug2 (" read_format %#" PRIx64"\n" , (uint64_t )attr->read_format); + +pr_debug2 (" disabled %u " , attr->disabled); +pr_debug2 ("inherit %u\n" , attr->inherit); +pr_debug2 (" pinned %u " , attr->pinned); +pr_debug2 ("exclusive %u\n" , attr->exclusive); +pr_debug2 (" exclude_user %u " , attr->exclude_user); +pr_debug2 ("exclude_kernel %u\n" , attr->exclude_kernel); +pr_debug2 (" exclude_hv %u " , attr->exclude_hv); +pr_debug2 ("exclude_idle %u\n" , attr->exclude_idle); +pr_debug2 (" mmap %u " , attr->mmap); +pr_debug2 ("comm %u\n" , attr->comm); +pr_debug2 (" freq %u " , attr->freq); +pr_debug2 ("inherit_stat %u\n" , attr->inherit_stat); +pr_debug2 (" enable_on_exec %u " , attr->enable_on_exec); +pr_debug2 ("task %u\n" , attr->task); +pr_debug2 (" watermark %u " , attr->watermark); +pr_debug2 ("precise_ip %u\n" , attr->precise_ip); +pr_debug2 (" mmap_data %u " , attr->mmap_data); +pr_debug2 ("sample_id_all %u\n" , attr->sample_id_all); +pr_debug2 (" exclude_host %u " , attr->exclude_host); +pr_debug2 ("exclude_guest %u\n" , attr->exclude_guest); +pr_debug2 (" excl.callchain.kern %u " , attr->exclude_callchain_kernel); +pr_debug2 ("excl.callchain.user %u\n" , attr->exclude_callchain_user); + +pr_debug2 (" wakeup_events %u\n" , attr->wakeup_events); +pr_debug2 (" wakeup_watermark %u\n" , attr->wakeup_watermark); +pr_debug2 (" bp_type %#x\n" , attr->bp_type); +pr_debug2 (" bp_addr %#" PRIx64"\n" , (uint64_t )attr->bp_addr); +pr_debug2 (" config1 %#" PRIx64"\n" , (uint64_t )attr->config1); +pr_debug2 (" bp_len %" PRIu64"\n" , (uint64_t )attr->bp_len); +pr_debug2 (" config2 %#" PRIx64"\n" , (uint64_t )attr->config2); +pr_debug2 (" branch_sample_type %#" PRIx64"\n" , (uint64_t )attr->branch_sample_type); +pr_debug2 (" sample_regs_user %#" PRIx64"\n" , (uint64_t )attr->sample_regs_user); +pr_debug2 (" sample_stack_user %u\n" , attr->sample_stack_user); +pr_debug2 ("------------------------------------------------------------\n" ); +} +static int __perf_evsel__open (struct perf_evsel *evsel,struct cpu_map *cpus,struct thread_map *threads) {@@ -840,6 +889,7 @@ retry_sample_id:if (perf_missing_features.sample_id_all) evsel->attr.sample_id_all =0 ; +show_attr (&evsel->attr);for (cpu =0 ; cpu < cpus->nr; cpu++) {for (thread =0 ; thread < threads->nr; thread++) {@@ -850,6 +900,8 @@ retry_sample_id: group_fd =get_group_fd (evsel, cpu, thread); +pr_debug2 ("perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n" , + pid, cpus->map[cpu], group_fd, flags); FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, pid, cpus->map[cpu],Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 10/21 perf tools: fix symbol_conf.nr_events
In reply to Adrian Huntersymbol_conf.nr_events must be updated when processing attribute events.
--- tools/perf/util/header.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/header.c +2 -0
@@ -2957,6 +2957,8 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,perf_evlist__id_add (evlist, evsel,0 , i, event->attr.id[i]); } + symbol_conf.nr_events = evlist->nr_entries; +return 0 ; }
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/urgent] perf tools: Update symbol_conf.nr_events when processing attribute events
perf tools: Update symbol_conf.nr_events when processing attribute events
Commit-ID: 7e0d6fc90fc6f9faea63a2b67233ae767903573c Gitweb: http://git.kernel.org/tip/7e0d6fc90fc6f9faea63a2b67233ae767903573c Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:29 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 8 Jul 2013 17:46:39 -0300
perf tools: Update symbol_conf.nr_events when processing attribute events
--- tools/perf/util/header.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/header.c +2 -0
@@ -2956,6 +2956,8 @@ int perf_event__process_attr(union perf_event *event,perf_evlist__id_add (evlist, evsel,0 , i, event->attr.id[i]); } + symbol_conf.nr_events = evlist->nr_entries; +return 0 ; }
Adrian Hunter
reviewerPATCH v4 11/21 perf tools: allow non-matching sample types
In reply to Adrian HunterSample types need not be identical to determine the sample id from the event. Only the position of the sample id needs to be the same.
Compatible sample types are ones in which the bits defined by PERF_COMPAT_MASK are the same. 'perf_evlist__config()' forces sample types to be compatible on that basis.
--- tools/perf/builtin-report.c | 2 +- tools/perf/util/event.h | 14 +++++ tools/perf/util/evlist.c | 135 ++++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/evlist.h | 8 ++- tools/perf/util/evsel.c | 64 ++++++++++++++++++++- tools/perf/util/evsel.h | 10 ++++ tools/perf/util/session.c | 8 ++- 7 files changed, 230 insertions(+), 11 deletions(-)
tools/perf/builtin-report.c +1 -1
@@ -367,7 +367,7 @@ static int process_read_event(struct perf_tool *tool,static int perf_report__setup_sample_type (struct perf_report *rep) {struct perf_session *self = rep->session; -u64 sample_type =perf_evlist__sample_type (self->evlist); +u64 sample_type =perf_evlist__combined_sample_type (self->evlist);if (!self->fd_pipe && !(sample_type &PERF_SAMPLE_CALLCHAIN )) {if (sort__has_parent) {
tools/perf/util/event.h +14 -0
@@ -65,6 +65,20 @@ struct read_event { PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) +/* +* Events have compatible sample types if the following bits all have the same +* value. This is because the order of sample members is fixed. For sample +* events the order is: PERF_SAMPLE_IP, PERF_SAMPLE_TID, PERF_SAMPLE_TIME, +* PERF_SAMPLE_ADDR, PERF_SAMPLE_ID. For non-sample events the sample members +* are accessed in reverse order. The order is: PERF_SAMPLE_ID, +* PERF_SAMPLE_STREAM_ID, PERF_SAMPLE_CPU. +*/ +#define PERF_COMPAT_MASK \ + (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ + PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ + PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ + PERF_SAMPLE_CPU) +struct sample_event {struct perf_event_header header;u64 array[];
tools/perf/util/evlist.c +130 -5
186 lines not on this page · raw message
tools/perf/util/evlist.h +7 -1
@@ -32,11 +32,15 @@ struct perf_evlist {int nr_fds;int nr_mmaps;int mmap_len; +int id_pos; +int is_pos; +u64 combined_sample_type;struct {int cork_fd;pid_t pid; } workload;bool overwrite; +bool matching_sample_types;struct perf_mmap *mmap;struct pollfd *pollfd;struct thread_map *threads;
@@ -83,6 +87,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);int perf_evlist__open (struct perf_evlist *evlist);void perf_evlist__close (struct perf_evlist *evlist); +void perf_evlist__make_sample_types_compatible (struct perf_evlist *evlist);void perf_evlist__config (struct perf_evlist *evlist,struct perf_record_opts *opts);
@@ -118,7 +123,8 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist);void __perf_evlist__set_leader (struct list_head *list);void perf_evlist__set_leader (struct perf_evlist *evlist); -u64 perf_evlist__sample_type (struct perf_evlist *evlist); +u64 __perf_evlist__combined_sample_type (struct perf_evlist *evlist); +u64 perf_evlist__combined_sample_type (struct perf_evlist *evlist);bool perf_evlist__sample_id_all (struct perf_evlist *evlist);u16 perf_evlist__id_hdr_size (struct perf_evlist *evlist);
tools/perf/util/evsel.c +63 -1
94 lines not on this page · raw message
tools/perf/util/evsel.h +10 -0
@@ -45,6 +45,11 @@ struct perf_sample_id {* @name - Can be set to retain the original event name passed by the user, * so that when showing results in tools such as 'perf stat', we * show the name used, not some alias. +* @id_pos: the position of the event id (PERF_SAMPLE_ID) in a sample event +* i.e. in the array of struct sample_event +* @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID) +* in a non-sample event i.e. if sample_id_all is used there is an id +* sample appended to non-sample events */ struct perf_evsel {struct list_head node;
@@ -71,6 +76,8 @@ struct perf_evsel { } handler;struct cpu_map *cpus;unsigned int sample_size; +int id_pos; +int is_pos;bool supported;bool needs_swap;/* parse modifier helper */
@@ -100,6 +107,9 @@ void perf_evsel__delete(struct perf_evsel *evsel);void perf_evsel__config (struct perf_evsel *evsel,struct perf_record_opts *opts); +int __perf_evsel__sample_size (u64 sample_type); +void perf_evsel__calc_id_pos (struct perf_evsel *evsel); +bool perf_evsel__is_cache_op_valid (u8 type,u8 op);#define PERF_EVSEL__MAX_ALIASES 8
tools/perf/util/session.c +5 -3
@@ -743,7 +743,7 @@ static void perf_session__print_tstamp(struct perf_session *session,union perf_event *event, struct perf_sample *sample) { - u64 sample_type = perf_evlist__sample_type(session->evlist); + u64 sample_type = __perf_evlist__combined_sample_type(session->evlist);if (event->header.type !=PERF_RECORD_SAMPLE && !perf_evlist__sample_id_all (session->evlist)) {
@@ -902,7 +902,7 @@ static int perf_session__preprocess_sample(struct perf_session *session, union perf_event *event, struct perf_sample *sample) {if (event->header.type !=PERF_RECORD_SAMPLE || - !(perf_evlist__sample_type (session->evlist) &PERF_SAMPLE_CALLCHAIN )) + !sample->callchain)return 0 ;if (!ip_callchain__valid (sample->callchain, event)) {
@@ -1304,7 +1304,9 @@ int perf_session__process_events(struct perf_session *self,bool perf_session__has_traces (struct perf_session *session,const char *msg) { -if (!(perf_evlist__sample_type (session->evlist) &PERF_SAMPLE_RAW )) { +u64 sample_type =perf_evlist__combined_sample_type (session->evlist); + +if (!(sample_type &PERF_SAMPLE_RAW )) {pr_err ("No trace sample to read. Did you call 'perf %s'?\n" , msg);return false; }
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 12/21 perf tools: struct thread has a tid not a pid
In reply to Adrian HunterAs evident from 'machine__process_fork_event()' and 'machine__process_exit_event()' the 'pid' member of struct thread is actually the tid.
Rename 'pid' to 'tid' in struct thread accordingly.
--- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-sched.c | 12 ++++++------ tools/perf/builtin-trace.c | 4 ++-- tools/perf/ui/browsers/hists.c | 6 +++--- tools/perf/util/event.c | 2 +- tools/perf/util/machine.c | 20 ++++++++++---------- tools/perf/util/machine.h | 4 ++-- tools/perf/util/sort.c | 6 +++--- tools/perf/util/thread.c | 10 +++++----- tools/perf/util/thread.h | 4 ++-- 10 files changed, 35 insertions(+), 35 deletions(-)
tools/perf/builtin-kmem.c +1 -1
@@ -313,7 +313,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,return -1 ; } -dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->pid); +dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->tid);if (evsel->handler.func !=NULL ) {tracepoint_handler f = evsel->handler.func;
tools/perf/builtin-sched.c +6 -6
@@ -1075,7 +1075,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,if (!atoms) {if (thread_atoms_insert (sched, migrant))return -1 ; -register_pid (sched, migrant->pid, migrant->comm); +register_pid (sched, migrant->tid, migrant->comm); atoms =thread_atoms_search (&sched->atom_root, migrant, &sched->cmp_pid);if (!atoms) {pr_err ("migration-event: Internal tree error" );
@@ -1115,7 +1115,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_ sched->all_runtime += work_list->total_runtime; sched->all_count += work_list->nb_atoms; - ret =printf (" %s:%d " , work_list->thread->comm, work_list->thread->pid); + ret =printf (" %s:%d " , work_list->thread->comm, work_list->thread->tid);for (i =0 ; i <24 - ret; i++)printf (" " );
@@ -1131,9 +1131,9 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_static int pid_cmp (struct work_atoms *l,struct work_atoms *r) { -if (l->thread->pid < r->thread->pid) +if (l->thread->tid < r->thread->tid)return -1 ; -if (l->thread->pid > r->thread->pid) +if (l->thread->tid > r->thread->tid)return 1 ;return 0 ;
@@ -1321,7 +1321,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,printf ("*" );if (sched->curr_thread[cpu]) { -if (sched->curr_thread[cpu]->pid) +if (sched->curr_thread[cpu]->tid)printf ("%2s " , sched->curr_thread[cpu]->shortname);else printf (". " );
@@ -1332,7 +1332,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,printf (" %12.6f secs " , (double )timestamp/1e9 );if (new_shortname) {printf ("%s => %s:%d\n" , - sched_in->shortname, sched_in->comm, sched_in->pid); + sched_in->shortname, sched_in->comm, sched_in->tid); }else {printf ("\n" ); }
tools/perf/builtin-trace.c +2 -2
@@ -142,7 +142,7 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre printed +=fprintf_duration (duration, fp);if (trace->multiple_threads) - printed +=fprintf (fp,"%d " , thread->pid); + printed +=fprintf (fp,"%d " , thread->tid);return printed; }
@@ -593,7 +593,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) color =PERF_COLOR_YELLOW ; printed +=color_fprintf (fp, color,"%20s" , thread->comm); - printed +=fprintf (fp," - %-5d :%11lu [" , thread->pid, ttrace->nr_events); + printed +=fprintf (fp," - %-5d :%11lu [" , thread->tid, ttrace->nr_events); printed +=color_fprintf (fp, color,"%5.1f%%" , ratio); printed +=fprintf (fp," ] %10.3f ms\n" , ttrace->runtime_ms); }
tools/perf/ui/browsers/hists.c +3 -3
@@ -1256,7 +1256,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, printed +=scnprintf (bf + printed, size - printed,", Thread: %s(%d)" , (thread->comm_set ? thread->comm :"" ), - thread->pid); + thread->tid);if (dso) printed +=scnprintf (bf + printed, size - printed,", DSO: %s" , dso->short_name);
@@ -1579,7 +1579,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,asprintf (&options[nr_options],"Zoom %s %s(%d) thread" , (browser->hists->thread_filter ?"out of" :"into" ), (thread->comm_set ? thread->comm :"" ), - thread->pid) > 0) + thread->tid) > 0) zoom_thread = nr_options++; if (dso != NULL &&
@@ -1702,7 +1702,7 @@ zoom_out_thread: }else {ui_helpline__fpush ("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"" , thread->comm_set ? thread->comm :"" , - thread->pid); + thread->tid); browser->hists->thread_filter = thread; sort_thread.elide = true;pstack__push (fstack, &browser->hists->thread_filter);
tools/perf/util/event.c +1 -1
@@ -686,7 +686,7 @@ int perf_event__preprocess_sample(const union perf_event *event, !strlist__has_entry(symbol_conf.comm_list, thread->comm)) goto out_filtered; -dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->pid); +dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->tid);/* * Have we already created the kernel maps for this machine? *
tools/perf/util/machine.c +10 -10
@@ -233,7 +233,7 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)return ; } -static struct thread *__machine__findnew_thread (struct machine *machine,pid_t pid, +static struct thread *__machine__findnew_thread (struct machine *machine,pid_t tid,bool create) {struct rb_node **p = &machine->threads.rb_node;
@@ -241,23 +241,23 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pstruct thread *th;/* -* Font-end cache - PID lookups come in blocks, +* Front-end cache - TID lookups come in blocks, * so most of the time we dont have to look up * the full rbtree: */ -if (machine->last_match && machine->last_match->pid == pid) +if (machine->last_match && machine->last_match->tid == tid)return machine->last_match;while (*p !=NULL ) { parent = *p; th = rb_entry(parent, struct thread, rb_node); -if (th->pid == pid) { +if (th->tid == tid) { machine->last_match = th;return th; } -if (pid < th->pid) +if (tid < th->tid) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -266,7 +266,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pif (!create)return NULL ; - th =thread__new (pid); + th =thread__new (tid);if (th !=NULL ) {rb_link_node (&th->rb_node, parent, p);rb_insert_color (&th->rb_node, &machine->threads);
@@ -276,14 +276,14 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t preturn th; } -struct thread *machine__findnew_thread (struct machine *machine,pid_t pid) +struct thread *machine__findnew_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, pid, true); +return __machine__findnew_thread (machine, tid, true); } -struct thread *machine__find_thread (struct machine *machine,pid_t pid) +struct thread *machine__find_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, pid, false); +return __machine__findnew_thread (machine, tid, false); }int machine__process_comm_event (struct machine *machine,union perf_event *event)
tools/perf/util/machine.h +2 -2
@@ -36,7 +36,7 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)return machine->vmlinux_maps[type]; } -struct thread *machine__find_thread (struct machine *machine,pid_t pid); +struct thread *machine__find_thread (struct machine *machine,pid_t tid);int machine__process_comm_event (struct machine *machine,union perf_event *event);int machine__process_exit_event (struct machine *machine,union perf_event *event);
@@ -99,7 +99,7 @@ static inline bool machine__is_host(struct machine *machine)return machine ? machine->pid ==HOST_KERNEL_ID : false; } -struct thread *machine__findnew_thread (struct machine *machine,pid_t pid); +struct thread *machine__findnew_thread (struct machine *machine,pid_t tid);size_t machine__fprintf (struct machine *machine,FILE *fp);
tools/perf/util/sort.c +3 -3
@@ -55,14 +55,14 @@ static int64_t cmp_null(void *l, void *r)static int64_t sort__thread_cmp (struct hist_entry *left,struct hist_entry *right) { -return right->thread->pid - left->thread->pid; +return right->thread->tid - left->thread->tid; }static int hist_entry__thread_snprintf (struct hist_entry *self,char *bf,size_t size,unsigned int width) {return repsep_snprintf (bf, size,"%*s:%5d" , width -6 , - self->thread->comm ?:"" , self->thread->pid); + self->thread->comm ?:"" , self->thread->tid); }struct sort_entry sort_thread = {
@@ -77,7 +77,7 @@ struct sort_entry sort_thread = {static int64_t sort__comm_cmp (struct hist_entry *left,struct hist_entry *right) { -return right->thread->pid - left->thread->pid; +return right->thread->tid - left->thread->tid; } static int64_t
tools/perf/util/thread.c +5 -5
@@ -7,17 +7,17 @@#include "util.h" #include "debug.h" -struct thread *thread__new (pid_t pid) +struct thread *thread__new (pid_t tid) {struct thread *self =zalloc (sizeof (*self));if (self !=NULL ) {map_groups__init (&self->mg); - self->pid = pid; + self->tid = tid; self->ppid =-1 ; self->comm =malloc (32 );if (self->comm) -snprintf (self->comm,32 ,":%d" , self->pid); +snprintf (self->comm,32 ,":%d" , self->tid); }return self;
@@ -57,7 +57,7 @@ int thread__comm_len(struct thread *self)size_t thread__fprintf (struct thread *thread,FILE *fp) { -return fprintf (fp,"Thread %d %s\n" , thread->pid, thread->comm) + +return fprintf (fp,"Thread %d %s\n" , thread->tid, thread->comm) +map_groups__fprintf (&thread->mg, verbose, fp); }
@@ -84,7 +84,7 @@ int thread__fork(struct thread *self, struct thread *parent)if (map_groups__clone (&self->mg, &parent->mg, i) <0 )return -ENOMEM ; - self->ppid = parent->pid; + self->ppid = parent->tid;return 0 ; }
tools/perf/util/thread.h +2 -2
@@ -12,7 +12,7 @@ struct thread {struct list_head node; };struct map_groups mg; -pid_t pid; +pid_t tid;pid_t ppid;char shortname[3 ];bool comm_set;
@@ -24,7 +24,7 @@ struct thread {struct machine ; -struct thread *thread__new (pid_t pid); +struct thread *thread__new (pid_t tid);void thread__delete (struct thread *self);int thread__set_comm (struct thread *self,const char *comm);
Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/core] perf tools: struct thread has a tid not a pid
perf tools: struct thread has a tid not a pid
Commit-ID: 380512345e13c3af64e59627f1b993c4faa94a84 Gitweb: http://git.kernel.org/tip/380512345e13c3af64e59627f1b993c4faa94a84 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:31 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 12 Jul 2013 13:53:50 -0300
perf tools: struct thread has a tid not a pid
As evident from 'machine__process_fork_event()' and 'machine__process_exit_event()' the 'pid' member of struct thread is actually the tid.
Rename 'pid' to 'tid' in struct thread accordingly.
--- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-sched.c | 12 ++++++------ tools/perf/builtin-trace.c | 4 ++-- tools/perf/ui/browsers/hists.c | 6 +++--- tools/perf/util/event.c | 2 +- tools/perf/util/machine.c | 20 ++++++++++---------- tools/perf/util/machine.h | 4 ++-- tools/perf/util/sort.c | 6 +++--- tools/perf/util/thread.c | 10 +++++----- tools/perf/util/thread.h | 4 ++-- 10 files changed, 35 insertions(+), 35 deletions(-)
tools/perf/builtin-kmem.c +1 -1
@@ -313,7 +313,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,return -1 ; } -dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->pid); +dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->tid);if (evsel->handler.func !=NULL ) {tracepoint_handler f = evsel->handler.func;
tools/perf/builtin-sched.c +6 -6
@@ -1075,7 +1075,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,if (!atoms) {if (thread_atoms_insert (sched, migrant))return -1 ; -register_pid (sched, migrant->pid, migrant->comm); +register_pid (sched, migrant->tid, migrant->comm); atoms =thread_atoms_search (&sched->atom_root, migrant, &sched->cmp_pid);if (!atoms) {pr_err ("migration-event: Internal tree error" );
@@ -1115,7 +1115,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_ sched->all_runtime += work_list->total_runtime; sched->all_count += work_list->nb_atoms; - ret =printf (" %s:%d " , work_list->thread->comm, work_list->thread->pid); + ret =printf (" %s:%d " , work_list->thread->comm, work_list->thread->tid);for (i =0 ; i <24 - ret; i++)printf (" " );
@@ -1131,9 +1131,9 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_static int pid_cmp (struct work_atoms *l,struct work_atoms *r) { -if (l->thread->pid < r->thread->pid) +if (l->thread->tid < r->thread->tid)return -1 ; -if (l->thread->pid > r->thread->pid) +if (l->thread->tid > r->thread->tid)return 1 ;return 0 ;
@@ -1321,7 +1321,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,printf ("*" );if (sched->curr_thread[cpu]) { -if (sched->curr_thread[cpu]->pid) +if (sched->curr_thread[cpu]->tid)printf ("%2s " , sched->curr_thread[cpu]->shortname);else printf (". " );
@@ -1332,7 +1332,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,printf (" %12.6f secs " , (double )timestamp/1e9 );if (new_shortname) {printf ("%s => %s:%d\n" , - sched_in->shortname, sched_in->comm, sched_in->pid); + sched_in->shortname, sched_in->comm, sched_in->tid); }else {printf ("\n" ); }
tools/perf/builtin-trace.c +2 -2
@@ -142,7 +142,7 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre printed +=fprintf_duration (duration, fp);if (trace->multiple_threads) - printed +=fprintf (fp,"%d " , thread->pid); + printed +=fprintf (fp,"%d " , thread->tid);return printed; }
@@ -593,7 +593,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) color =PERF_COLOR_YELLOW ; printed +=color_fprintf (fp, color,"%20s" , thread->comm); - printed +=fprintf (fp," - %-5d :%11lu [" , thread->pid, ttrace->nr_events); + printed +=fprintf (fp," - %-5d :%11lu [" , thread->tid, ttrace->nr_events); printed +=color_fprintf (fp, color,"%5.1f%%" , ratio); printed +=fprintf (fp," ] %10.3f ms\n" , ttrace->runtime_ms); }
tools/perf/ui/browsers/hists.c +3 -3
@@ -1256,7 +1256,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, printed +=scnprintf (bf + printed, size - printed,", Thread: %s(%d)" , (thread->comm_set ? thread->comm :"" ), - thread->pid); + thread->tid);if (dso) printed +=scnprintf (bf + printed, size - printed,", DSO: %s" , dso->short_name);
@@ -1579,7 +1579,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,asprintf (&options[nr_options],"Zoom %s %s(%d) thread" , (browser->hists->thread_filter ?"out of" :"into" ), (thread->comm_set ? thread->comm :"" ), - thread->pid) > 0) + thread->tid) > 0) zoom_thread = nr_options++; if (dso != NULL &&
@@ -1702,7 +1702,7 @@ zoom_out_thread: }else {ui_helpline__fpush ("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"" , thread->comm_set ? thread->comm :"" , - thread->pid); + thread->tid); browser->hists->thread_filter = thread; sort_thread.elide = true;pstack__push (fstack, &browser->hists->thread_filter);
tools/perf/util/event.c +1 -1
@@ -686,7 +686,7 @@ int perf_event__preprocess_sample(const union perf_event *event, !strlist__has_entry(symbol_conf.comm_list, thread->comm)) goto out_filtered; -dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->pid); +dump_printf (" ... thread: %s:%d\n" , thread->comm, thread->tid);/* * Have we already created the kernel maps for this machine? *
tools/perf/util/machine.c +10 -10
@@ -233,7 +233,7 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)return ; } -static struct thread *__machine__findnew_thread (struct machine *machine,pid_t pid, +static struct thread *__machine__findnew_thread (struct machine *machine,pid_t tid,bool create) {struct rb_node **p = &machine->threads.rb_node;
@@ -241,23 +241,23 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pstruct thread *th;/* -* Font-end cache - PID lookups come in blocks, +* Front-end cache - TID lookups come in blocks, * so most of the time we dont have to look up * the full rbtree: */ -if (machine->last_match && machine->last_match->pid == pid) +if (machine->last_match && machine->last_match->tid == tid)return machine->last_match;while (*p !=NULL ) { parent = *p; th = rb_entry(parent, struct thread, rb_node); -if (th->pid == pid) { +if (th->tid == tid) { machine->last_match = th;return th; } -if (pid < th->pid) +if (tid < th->tid) p = &(*p)->rb_left;else p = &(*p)->rb_right;
@@ -266,7 +266,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pif (!create)return NULL ; - th =thread__new (pid); + th =thread__new (tid);if (th !=NULL ) {rb_link_node (&th->rb_node, parent, p);rb_insert_color (&th->rb_node, &machine->threads);
@@ -276,14 +276,14 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t preturn th; } -struct thread *machine__findnew_thread (struct machine *machine,pid_t pid) +struct thread *machine__findnew_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, pid, true); +return __machine__findnew_thread (machine, tid, true); } -struct thread *machine__find_thread (struct machine *machine,pid_t pid) +struct thread *machine__find_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, pid, false); +return __machine__findnew_thread (machine, tid, false); }int machine__process_comm_event (struct machine *machine,union perf_event *event)
tools/perf/util/machine.h +2 -2
@@ -36,7 +36,7 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)return machine->vmlinux_maps[type]; } -struct thread *machine__find_thread (struct machine *machine,pid_t pid); +struct thread *machine__find_thread (struct machine *machine,pid_t tid);int machine__process_comm_event (struct machine *machine,union perf_event *event);int machine__process_exit_event (struct machine *machine,union perf_event *event);
@@ -99,7 +99,7 @@ static inline bool machine__is_host(struct machine *machine)return machine ? machine->pid ==HOST_KERNEL_ID : false; } -struct thread *machine__findnew_thread (struct machine *machine,pid_t pid); +struct thread *machine__findnew_thread (struct machine *machine,pid_t tid);size_t machine__fprintf (struct machine *machine,FILE *fp);
tools/perf/util/sort.c +3 -3
@@ -55,14 +55,14 @@ static int64_t cmp_null(void *l, void *r)static int64_t sort__thread_cmp (struct hist_entry *left,struct hist_entry *right) { -return right->thread->pid - left->thread->pid; +return right->thread->tid - left->thread->tid; }static int hist_entry__thread_snprintf (struct hist_entry *self,char *bf,size_t size,unsigned int width) {return repsep_snprintf (bf, size,"%*s:%5d" , width -6 , - self->thread->comm ?:"" , self->thread->pid); + self->thread->comm ?:"" , self->thread->tid); }struct sort_entry sort_thread = {
@@ -77,7 +77,7 @@ struct sort_entry sort_thread = {static int64_t sort__comm_cmp (struct hist_entry *left,struct hist_entry *right) { -return right->thread->pid - left->thread->pid; +return right->thread->tid - left->thread->tid; } static int64_t
tools/perf/util/thread.c +5 -5
@@ -7,17 +7,17 @@#include "util.h" #include "debug.h" -struct thread *thread__new (pid_t pid) +struct thread *thread__new (pid_t tid) {struct thread *self =zalloc (sizeof (*self));if (self !=NULL ) {map_groups__init (&self->mg); - self->pid = pid; + self->tid = tid; self->ppid =-1 ; self->comm =malloc (32 );if (self->comm) -snprintf (self->comm,32 ,":%d" , self->pid); +snprintf (self->comm,32 ,":%d" , self->tid); }return self;
@@ -57,7 +57,7 @@ int thread__comm_len(struct thread *self)size_t thread__fprintf (struct thread *thread,FILE *fp) { -return fprintf (fp,"Thread %d %s\n" , thread->pid, thread->comm) + +return fprintf (fp,"Thread %d %s\n" , thread->tid, thread->comm) +map_groups__fprintf (&thread->mg, verbose, fp); }
@@ -84,7 +84,7 @@ int thread__fork(struct thread *self, struct thread *parent)if (map_groups__clone (&self->mg, &parent->mg, i) <0 )return -ENOMEM ; - self->ppid = parent->pid; + self->ppid = parent->tid;return 0 ; }
tools/perf/util/thread.h +2 -2
@@ -12,7 +12,7 @@ struct thread {struct list_head node; };struct map_groups mg; -pid_t pid; +pid_t tid;pid_t ppid;char shortname[3 ];bool comm_set;
@@ -24,7 +24,7 @@ struct thread {struct machine ; -struct thread *thread__new (pid_t pid); +struct thread *thread__new (pid_t tid);void thread__delete (struct thread *self);int thread__set_comm (struct thread *self,const char *comm);
Adrian Hunter
reviewerPATCH v4 13/21 perf tools: add pid to struct thread
In reply to Adrian HunterRecord pid on struct thread. The member is named 'pid_' to avoid confusion with the 'tid' member which was previously named 'pid'.
--- tools/perf/util/machine.c | 16 +++++++++++----- tools/perf/util/thread.c | 3 ++- tools/perf/util/thread.h | 3 ++- 3 files changed, 15 insertions(+), 7 deletions(-)
tools/perf/util/machine.c +11 -5
@@ -233,7 +233,8 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)return ; } -static struct thread *__machine__findnew_thread (struct machine *machine,pid_t tid, +static struct thread *__machine__findnew_thread (struct machine *machine, +pid_t pid,pid_t tid,bool create) {struct rb_node **p = &machine->threads.rb_node;
@@ -245,8 +246,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t t* so most of the time we dont have to look up * the full rbtree: */ -if (machine->last_match && machine->last_match->tid == tid) +if (machine->last_match && machine->last_match->tid == tid) { +if (pid && !machine->last_match->pid_) + machine->last_match->pid_ = pid;return machine->last_match; + }while (*p !=NULL ) { parent = *p;
@@ -254,6 +258,8 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tif (th->tid == tid) { machine->last_match = th; +if (pid && !th->pid_) + th->pid_ = pid;return th; }
@@ -266,7 +272,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tif (!create)return NULL ; - th =thread__new (tid); + th =thread__new (pid, tid);if (th !=NULL ) {rb_link_node (&th->rb_node, parent, p);rb_insert_color (&th->rb_node, &machine->threads);
@@ -278,12 +284,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tstruct thread *machine__findnew_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, tid, true); +return __machine__findnew_thread (machine,0 , tid, true); }struct thread *machine__find_thread (struct machine *machine,pid_t tid) { -return __machine__findnew_thread (machine, tid, false); +return __machine__findnew_thread (machine,0 , tid, false); }int machine__process_comm_event (struct machine *machine,union perf_event *event)
tools/perf/util/thread.c +2 -1
@@ -7,12 +7,13 @@#include "util.h" #include "debug.h" -struct thread *thread__new (pid_t tid) +struct thread *thread__new (pid_t pid,pid_t tid) {struct thread *self =zalloc (sizeof (*self));if (self !=NULL ) {map_groups__init (&self->mg); + self->pid_ = pid; self->tid = tid; self->ppid =-1 ; self->comm =malloc (32 );
tools/perf/util/thread.h +2 -1
@@ -12,6 +12,7 @@ struct thread {struct list_head node; };struct map_groups mg; +pid_t pid_;/* Not all tools update this */ pid_t tid;pid_t ppid;char shortname[3 ];
@@ -24,7 +25,7 @@ struct thread {struct machine ; -struct thread *thread__new (pid_t tid); +struct thread *thread__new (pid_t pid,pid_t tid);void thread__delete (struct thread *self);int thread__set_comm (struct thread *self,const char *comm);
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 14/21 perf tools: change "machine" functions to set thread pid
In reply to Adrian HunterTypically tracking events such as mmap events, comm events, fork events and exit events, are processed by "machine" functions. Change these functions to put pid in the new pid_ member of struct thread.
--- tools/perf/util/machine.c | 21 +++++++++++++++++---- tools/perf/util/machine.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-)
tools/perf/util/machine.c +17 -4
@@ -287,6 +287,12 @@ struct thread *machine__findnew_thread(struct machine *machine, pid_t tid)return __machine__findnew_thread (machine,0 , tid, true); } +struct thread *machine__findnew_thread_ex (struct machine *machine,pid_t pid, +pid_t tid) +{ +return __machine__findnew_thread (machine, pid, tid, true); +} +struct thread *machine__find_thread (struct machine *machine,pid_t tid) {return __machine__findnew_thread (machine,0 , tid, false);
@@ -294,7 +300,9 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)int machine__process_comm_event (struct machine *machine,union perf_event *event) { -struct thread *thread =machine__findnew_thread (machine, event->comm.tid); +struct thread *thread =machine__findnew_thread_ex (machine, + event->comm.pid, + event->comm.tid);if (dump_trace)perf_event__fprintf_comm (event, stdout);
@@ -975,7 +983,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *eventreturn 0 ; } - thread =machine__findnew_thread (machine, event->mmap.pid); + thread =machine__findnew_thread_ex (machine, event->mmap.pid, + event->mmap.pid);if (thread ==NULL ) goto out_problem;
@@ -1002,8 +1011,12 @@ out_problem:int machine__process_fork_event (struct machine *machine,union perf_event *event) { -struct thread *thread =machine__findnew_thread (machine, event->fork.tid); -struct thread *parent =machine__findnew_thread (machine, event->fork.ptid); +struct thread *thread =machine__findnew_thread_ex (machine, + event->fork.pid, + event->fork.tid); +struct thread *parent =machine__findnew_thread_ex (machine, + event->fork.ppid, + event->fork.ptid);if (dump_trace)perf_event__fprintf_task (event, stdout);
tools/perf/util/machine.h +2 -0
@@ -100,6 +100,8 @@ static inline bool machine__is_host(struct machine *machine) }struct thread *machine__findnew_thread (struct machine *machine,pid_t tid); +struct thread *machine__findnew_thread_ex (struct machine *machine,pid_t pid, +pid_t tid);size_t machine__fprintf (struct machine *machine,FILE *fp);
Signature · 1 line
1.7.11.7
Re: [PATCH V4 14/21] perf tools: change "machine" functions to set thread pid
Quoted 11 lines · Adrian Hunter
Typically tracking events such as mmap events, comm events, fork events and exit events, are processed by "machine" functions. Change these functions to put pid in the new
pid_member of struct thread.Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/util/machine.c | 21 +++++++++++++++++---- tools/perf/util/machine.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-)
---8<---
Quoted 6 lines
tools/perf/util/machine.h +0
-0
tools/perf/util/machine.h static inline bool machine__is_host(struct machine *machine) · line 107
Quoted 8 lines
tools/perf/util/machine.h +2
-0@@ -100,6 +100,8 @@ static inline bool machine__is_host(struct machine *machine) }struct thread *machine__findnew_thread (struct machine *machine,pid_t tid); +struct thread *machine__findnew_thread_ex (struct machine *machine,pid_t pid, +pid_t tid);size_t machine__fprintf (struct machine *machine,FILE *fp);
Why do you want to add a new API for this? Why not just fix findnew_thread and find_thread to take the pid argument? We don't need 2 apis that do the same thing.
David
Adrian Hunter
reviewerPATCH v4 15/21 perf tools: fix missing increment in sample parsing
In reply to Adrian HunterThe final sample format bit used to be PERF_SAMPLE_STACK_USER which neglected to do a final increment of the array pointer. The result is that the following parsing might start at the wrong place.
--- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evsel.c +1 -1
@@ -1284,7 +1284,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, }else { data->user_stack.data = (char *)array; array += size /sizeof (*array); - data->user_stack.size = *array; + data->user_stack.size = *array++; } }
Signature · 1 line
1.7.11.7
Re: [PATCH V4 15/21] perf tools: fix missing increment in sample parsing
Em Thu, Jul 04, 2013 at 04:20:34PM +0300, Adrian Hunter escreveu:
Quoted 4 lines
The final sample format bit used to be
PERF_SAMPLE_STACK_USERwhich neglected to do a final increment of the array pointer. The result is that the following parsing might start at the wrong place.
One 'perf test' entry that would ask for these features and then check that the result obtained is what is expected would come in handy here :-\
- Arnaldo
Quoted 20 lines
Signed-off-by Adrian Hunter <[email protected]>--- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)tools/perf/util/evsel.c +1
-1@@ -1284,7 +1284,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, }else { data->user_stack.data = (char *)array; array += size /sizeof (*array); - data->user_stack.size = *array; + data->user_stack.size = *array++; } }Signature · 1 line
1.7.11.7
tip-bot for Adrian Hunter
merge bot[tip:perf/urgent] perf evsel: Fix missing increment in sample parsing
In reply to Adrian Hunterperf evsel: Fix missing increment in sample parsing
Commit-ID: 54bd269205c188967d565f1f5552b13d08ca1be0 Gitweb: http://git.kernel.org/tip/54bd269205c188967d565f1f5552b13d08ca1be0 Author: Adrian Hunter <[email protected]> AuthorDate: Thu, 4 Jul 2013 16:20:34 +0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 8 Jul 2013 17:47:13 -0300
perf evsel: Fix missing increment in sample parsing
The final sample format bit used to be PERF_SAMPLE_STACK_USER which neglected to do a final increment of the array pointer. The result is that the following parsing might start at the wrong place.
--- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evsel.c +1 -1
@@ -1170,7 +1170,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, }else { data->user_stack.data = (char *)array; array += size /sizeof (*array); - data->user_stack.size = *array; + data->user_stack.size = *array++; } }
Adrian Hunter
reviewerPATCH v4 16/21 perf tools: tidy up sample parsing overflow checking
In reply to Adrian HunterThe size of data retrieved from a sample event must be validated to ensure it does not go past the end of the event. That was being done sporadically and without considering integer overflows.
--- tools/perf/util/evsel.c | 101 ++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 38 deletions(-)
tools/perf/util/evsel.c +63 -38
@@ -1108,24 +1108,38 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,return 0 ; } -static bool sample_overlap (const union perf_event *event, -const void *offset,u64 size) +static inline bool overflow_one (const void *endp,const void *offset) { -const void *base = event; - -if (offset + size > base + event->header.size) -return true; +return offset +sizeof (u64) > endp; +} -return false; +static inline bool overflow (const void *endp,u16 max_size,const void *offset, +u64 size) +{ +return size > max_size || offset + size > endp; } +#define OVERFLOW_CHECK_ONE (offset) \ + do { \ + if (overflow_one(endp, (offset))) \ + return -EFAULT; \ + } while (0) + +#define OVERFLOW_CHECK (offset, size) \ + do { \ + if (overflow(endp, max_size, (offset), (size))) \ + return -EFAULT; \ + } while (0) +int perf_evsel__parse_sample (struct perf_evsel *evsel,union perf_event *event,struct perf_sample *data) {u64 type = evsel->attr.sample_type; -u64 regs_user = evsel->attr.sample_regs_user;bool swapped = evsel->needs_swap;const u64 *array; +u16 max_size = event->header.size; +const void *endp = (void *)event + max_size; +u64 sz;/* * used for cross-endian analysis. See git commit 65014ab3
@@ -1147,6 +1161,11 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array = event->sample.array; +/* +* sample_size is based on PERF_SAMPLE_MASK which includes up to +* PERF_SAMPLE_PERIOD. After that overflow_one() or overflow() must be +* used to check the format does not go past the end of the event. +*/ if (evsel->sample_size +sizeof (event->header) > event->header.size)return -EFAULT ;
@@ -1215,20 +1234,19 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, }if (type &PERF_SAMPLE_CALLCHAIN ) { -if (sample_overlap (event, array,sizeof (data->callchain->nr))) -return -EFAULT ; - - data->callchain = (struct ip_callchain *)array; +const u64 max_callchain_nr =UINT64_MAX /sizeof (u64); -if (sample_overlap (event, array, data->callchain->nr)) +OVERFLOW_CHECK_ONE (array); + data->callchain = (struct ip_callchain *)array++; +if (data->callchain->nr > max_callchain_nr)return -EFAULT ; - - array +=1 + data->callchain->nr; + sz = data->callchain->nr *sizeof (u64); +OVERFLOW_CHECK (array, sz); + array = (void *)array + sz; }if (type &PERF_SAMPLE_RAW ) { -const u64 *pdata; - +OVERFLOW_CHECK_ONE (array); u.val64 = *array;if (WARN_ONCE (swapped,"Endianness of raw data not corrected!\n" )) {
@@ -1237,65 +1255,72 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, u.val32[0 ] =bswap_32 (u.val32[0 ]); u.val32[1 ] =bswap_32 (u.val32[1 ]); } - -if (sample_overlap (event, array,sizeof (u32))) -return -EFAULT ; - data->raw_size = u.val32[0 ]; - pdata = (void *) array +sizeof (u32); + array = (void *)array +sizeof (u32); -if (sample_overlap (event, pdata, data->raw_size)) -return -EFAULT ; - - data->raw_data = (void *) pdata; - - array = (void *)array + data->raw_size +sizeof (u32); +OVERFLOW_CHECK (array, data->raw_size); + data->raw_data = (void *)array; + array = (void *)array + data->raw_size; }if (type &PERF_SAMPLE_BRANCH_STACK ) { -u64 sz; +const u64 max_branch_nr =UINT64_MAX /sizeof (struct branch_entry ); - data->branch_stack = (struct branch_stack *)array; - array++;/* nr */ +OVERFLOW_CHECK_ONE (array); + data->branch_stack = (struct branch_stack *)array++; +if (data->branch_stack->nr > max_branch_nr) +return -EFAULT ; sz = data->branch_stack->nr *sizeof (struct branch_entry ); - sz /=sizeof (u64); - array += sz; +OVERFLOW_CHECK (array, sz); + array = (void *)array + sz; }if (type &PERF_SAMPLE_REGS_USER ) { +u64 avail; +/* First u64 tells us if we have any regs in sample. */ -u64 avail = *array++; +OVERFLOW_CHECK_ONE (array); + avail = *array++;if (avail) { +u64 regs_user = evsel->attr.sample_regs_user; + + sz =hweight_long (regs_user) *sizeof (u64); +OVERFLOW_CHECK (array, sz); data->user_regs.regs = (u64 *)array; - array +=hweight_long (regs_user); + array = (void *)array + sz; } }if (type &PERF_SAMPLE_STACK_USER ) { -u64 size = *array++; +OVERFLOW_CHECK_ONE (array); + sz = *array++; data->user_stack.offset = ((char *)(array -1 ) - (char *) event); -if (!size) { +if (!sz) { data->user_stack.size =0 ; }else { +OVERFLOW_CHECK (array, sz); data->user_stack.data = (char *)array; - array += size /sizeof (*array); + array = (void *)array + sz; +OVERFLOW_CHECK_ONE (array); data->user_stack.size = *array++; } } data->weight =0 ;if (type &PERF_SAMPLE_WEIGHT ) { +OVERFLOW_CHECK_ONE (array); data->weight = *array; array++; } data->data_src =PERF_MEM_DATA_SRC_NONE ;if (type &PERF_SAMPLE_DATA_SRC ) { +OVERFLOW_CHECK_ONE (array); data->data_src = *array; array++; }
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 17/21 perf tools: remove unnecessary callchain validation
In reply to Adrian HunterNow that the sample parsing correctly checks data sizes there is no reason for it to be done again for callchains.
--- tools/perf/util/callchain.c | 8 -------- tools/perf/util/callchain.h | 5 ----- tools/perf/util/session.c | 20 -------------------- 3 files changed, 33 deletions(-)
tools/perf/util/callchain.c +0 -8
@@ -20,14 +20,6 @@ __threadstruct callchain_cursor callchain_cursor; -bool ip_callchain__valid (struct ip_callchain *chain, -const union perf_event *event) -{ -unsigned int chain_size = event->header.size; - chain_size -= (unsigned long )&event->ip.__more_data - (unsigned long )event; -return chain->nr *sizeof (u64) <= chain_size; -} -#define chain_for_each_child (child, parent) \ list_for_each_entry(child, &parent->children, siblings)
tools/perf/util/callchain.h +0 -5
@@ -103,11 +103,6 @@ int callchain_append(struct callchain_root *root,int callchain_merge (struct callchain_cursor *cursor,struct callchain_root *dst,struct callchain_root *src); -struct ip_callchain ; -union perf_event ; - -bool ip_callchain__valid (struct ip_callchain *chain, -const union perf_event *event);/* * Initialize a cursor before adding entries inside, but keep * the previously allocated entries as a cache.
tools/perf/util/session.c +0 -20
@@ -898,22 +898,6 @@ static int perf_session_deliver_event(struct perf_session *session, } } -static int perf_session__preprocess_sample (struct perf_session *session, -union perf_event *event,struct perf_sample *sample) -{ -if (event->header.type !=PERF_RECORD_SAMPLE || - !sample->callchain) -return 0 ; - -if (!ip_callchain__valid (sample->callchain, event)) { -pr_debug ("call-chain problem with event, skipping it.\n" ); - ++session->stats.nr_invalid_chains; - session->stats.total_invalid_chains += sample->period; -return -EINVAL ; - } -return 0 ; -} -static int perf_session__process_user_event (struct perf_session *session,union perf_event *event,struct perf_tool *tool,u64 file_offset) {
@@ -978,10 +962,6 @@ static int perf_session__process_event(struct perf_session *session,if (ret)return ret; -/* Preprocess sample records - precheck callchains */ -if (perf_session__preprocess_sample (session, event, &sample)) -return 0 ; -if (tool->ordered_samples) { ret =perf_session_queue_event (session, event, &sample, file_offset);
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 18/21 perf tools: remove references to struct ip_event
In reply to Adrian Hunterstruct ip_event assumes fixeed positions for ip, pid and tid. That is no longer true with the addition of PERF_SAMPLE_IDENTIFIER. The information is anyway in struct sample, so use that instead.
--- tools/perf/builtin-inject.c | 4 ++-- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-mem.c | 2 +- tools/perf/builtin-script.c | 2 +- tools/perf/builtin-top.c | 10 +++++----- tools/perf/tests/hists_link.c | 4 ++++ tools/perf/util/build-id.c | 6 +++--- tools/perf/util/event.c | 4 ++-- tools/perf/util/evsel.c | 4 ++-- tools/perf/util/session.c | 7 ++++--- 10 files changed, 25 insertions(+), 20 deletions(-)
tools/perf/builtin-inject.c +2 -2
@@ -204,7 +204,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ; - thread =machine__findnew_thread (machine, event->ip.pid); + thread =machine__findnew_thread (machine, sample->pid);if (thread ==NULL ) {pr_err ("problem processing %d event, skipping it.\n" , event->header.type);
@@ -212,7 +212,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, }thread__find_addr_map (thread, machine, cpumode,MAP__FUNCTION , - event->ip.ip, &al); + sample->ip, &al);if (al.map !=NULL ) {if (!al.map->dso->hit) {
tools/perf/builtin-kmem.c +1 -1
@@ -305,7 +305,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,struct perf_evsel *evsel, struct machine *machine) { - struct thread *thread = machine__findnew_thread(machine, event->ip.pid); + struct thread *thread = machine__findnew_thread(machine, sample->pid);if (thread ==NULL ) { pr_debug("problem processing %d event, skipping it.\n",
tools/perf/builtin-mem.c +1 -1
@@ -96,7 +96,7 @@ dump_raw_samples(struct perf_tool *tool, symbol_conf.field_sep, sample->tid, symbol_conf.field_sep, - event->ip.ip, + sample->ip, symbol_conf.field_sep, sample->addr, symbol_conf.field_sep,
tools/perf/builtin-script.c +1 -1
@@ -479,7 +479,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, struct machine *machine) {struct addr_location al; -struct thread *thread =machine__findnew_thread (machine, event->ip.tid); +struct thread *thread =machine__findnew_thread (machine, sample->tid);if (thread ==NULL ) { pr_debug("problem processing %d event, skipping it.\n",
tools/perf/builtin-top.c +5 -5
@@ -690,7 +690,7 @@ static void perf_event__process_sample(struct perf_tool *tool, { struct perf_top *top = container_of(tool, struct perf_top, tool);struct symbol *parent =NULL ; -u64 ip = event->ip.ip; +u64 ip = sample->ip;struct addr_location al;int err;
@@ -700,10 +700,10 @@ static void perf_event__process_sample(struct perf_tool *tool,if (!seen) seen =intlist__new (NULL ); -if (!intlist__has_entry (seen, event->ip.pid)) { +if (!intlist__has_entry (seen, sample->pid)) {pr_err ("Can't find guest [%d]'s kernel information\n" , - event->ip.pid); -intlist__add (seen, event->ip.pid); + sample->pid); +intlist__add (seen, sample->pid); }return ; }
@@ -839,7 +839,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)break ;case PERF_RECORD_MISC_GUEST_KERNEL : ++top->guest_kernel_samples; - machine =perf_session__find_machine (session, event->ip.pid); + machine =perf_session__find_machine (session, sample.pid);break ;case PERF_RECORD_MISC_GUEST_USER : ++top->guest_us_samples;
tools/perf/tests/hists_link.c +4 -0
@@ -219,6 +219,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) }, }; + sample.pid = ip_event.ip.pid; + sample.ip = ip_event.ip.ip;if (perf_event__preprocess_sample (&event, machine, &al, &sample,0 ) <0 ) goto out;
@@ -243,6 +245,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) }, }; + sample.pid = ip_event.ip.pid; + sample.ip = ip_event.ip.ip;if (perf_event__preprocess_sample (&event, machine, &al, &sample,0 ) <0 ) goto out;
tools/perf/util/build-id.c +3 -3
@@ -18,13 +18,13 @@int build_id__mark_dso_hit (struct perf_tool *tool__maybe_unused ,union perf_event *event, -struct perf_sample *sample__maybe_unused , +struct perf_sample *sample,struct perf_evsel *evsel__maybe_unused ,struct machine *machine) {struct addr_location al;u8 cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ; -struct thread *thread =machine__findnew_thread (machine, event->ip.pid); +struct thread *thread =machine__findnew_thread (machine, sample->pid);if (thread ==NULL ) { pr_err("problem processing %d event, skipping it.\n",
@@ -33,7 +33,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, }thread__find_addr_map (thread, machine, cpumode,MAP__FUNCTION , - event->ip.ip, &al); + sample->ip, &al);if (al.map !=NULL ) al.map->dso->hit =1 ;
tools/perf/util/event.c +2 -2
@@ -677,7 +677,7 @@ int perf_event__preprocess_sample(const union perf_event *event, symbol_filter_t filter) {u8 cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ; -struct thread *thread =machine__findnew_thread (machine, event->ip.pid); +struct thread *thread =machine__findnew_thread (machine, sample->pid);if (thread ==NULL )return -1 ;
@@ -699,7 +699,7 @@ int perf_event__preprocess_sample(const union perf_event *event,machine__create_kernel_maps (machine);thread__find_addr_map (thread, machine, cpumode,MAP__FUNCTION , - event->ip.ip, al); + sample->ip, al);dump_printf (" ...... dso: %s\n" , al->map ? al->map->dso->long_name : al->level =='H' ?"[hypervisor]" :"<not found>" );
tools/perf/util/evsel.c +2 -2
@@ -1170,7 +1170,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,return -EFAULT ;if (type &PERF_SAMPLE_IP ) { - data->ip = event->ip.ip; + data->ip = *array; array++; }
@@ -1343,7 +1343,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, array = event->sample.array;if (type &PERF_SAMPLE_IP ) { - event->ip.ip = sample->ip; + *array = sample->ip; array++; }
tools/perf/util/session.c +4 -3
@@ -811,7 +811,8 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,static struct machine *perf_session__find_machine_for_cpumode (struct perf_session *session, -union perf_event *event) +union perf_event *event, +struct perf_sample *sample) {const u8 cpumode = event->header.misc &PERF_RECORD_MISC_CPUMODE_MASK ;
@@ -823,7 +824,7 @@ static struct machine *if (event->header.type ==PERF_RECORD_MMAP ) pid = event->mmap.pid;else - pid = event->ip.pid; + pid = sample->pid;return perf_session__findnew_machine (session, pid); }
@@ -860,7 +861,7 @@ static int perf_session_deliver_event(struct perf_session *session,hists__inc_nr_events (&evsel->hists, event->header.type); } - machine =perf_session__find_machine_for_cpumode (session, event); + machine =perf_session__find_machine_for_cpumode (session, event, sample);switch (event->header.type) {case PERF_RECORD_SAMPLE :
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 19/21 perf tools: move struct ip_event
In reply to Adrian Hunterstruct ip_event assumes fixed positions for ip, pid and tid. That is no longer true with the addition of PERF_SAMPLE_IDENTIFIER.
struct ip_event is no longer used except by hists_link.c. Move it there.
--- tools/perf/tests/hists_link.c | 23 +++++++++++++++++++---- tools/perf/util/event.h | 11 ----------- 2 files changed, 19 insertions(+), 15 deletions(-)
tools/perf/tests/hists_link.c +19 -4
@@ -194,6 +194,19 @@ static struct sample fake_samples[][5] = { }, }; +/* PERF_SAMPLE_IP | PERF_SAMPLE_TID | * but not PERF_SAMPLE_IDENTIFIER */ +struct ip_event { +struct perf_event_header header; +u64 ip; +u32 pid, tid; +unsigned char __more_data[]; +}; + +union perf_ip_event { +struct ip_event ip; +union perf_event event; +}; +static int add_hist_entries (struct perf_evlist *evlist,struct machine *machine) {struct perf_evsel *evsel;
@@ -209,7 +222,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)*/ list_for_each_entry (evsel, &evlist->entries, node) {for (k =0 ; k <ARRAY_SIZE (fake_common_samples); k++) { -const union perf_event event = { +const union perf_ip_event ip_event = { .ip = { .header = { .misc =PERF_RECORD_MISC_USER ,
@@ -218,10 +231,11 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) .ip = fake_common_samples[k].ip, }, }; +const union perf_event *event = &ip_event.event; sample.pid = ip_event.ip.pid; sample.ip = ip_event.ip.ip; -if (perf_event__preprocess_sample (&event, machine, &al, +if (perf_event__preprocess_sample (event, machine, &al, &sample,0 ) <0 ) goto out;
@@ -235,7 +249,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) }for (k =0 ; k <ARRAY_SIZE (fake_samples[i]); k++) { -const union perf_event event = { +const union perf_ip_event ip_event = { .ip = { .header = { .misc =PERF_RECORD_MISC_USER ,
@@ -244,10 +258,11 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) .ip = fake_samples[i][k].ip, }, }; +const union perf_event *event = &ip_event.event; sample.pid = ip_event.ip.pid; sample.ip = ip_event.ip.ip; -if (perf_event__preprocess_sample (&event, machine, &al, +if (perf_event__preprocess_sample (event, machine, &al, &sample,0 ) <0 ) goto out;
tools/perf/util/event.h +0 -11
@@ -8,16 +8,6 @@#include "map.h" #include "build-id.h" -/* -* PERF_SAMPLE_IP | PERF_SAMPLE_TID | * -*/ -struct ip_event { -struct perf_event_header header; -u64 ip; -u32 pid, tid; -unsigned char __more_data[]; -}; -struct mmap_event {struct perf_event_header header;u32 pid, tid;
@@ -162,7 +152,6 @@ struct tracing_data_event {union perf_event {struct perf_event_header header; -struct ip_event ip;struct mmap_event mmap;struct comm_event comm;struct fork_event fork;
Signature · 1 line
1.7.11.7
Adrian Hunter
reviewerPATCH v4 20/21 perf: make events stream always parsable
In reply to Adrian HunterThe event stream is not always parsable because the format of a sample is dependent on the sample_type of the selected event. When there is more than one selected event and the sample_types are not the same then parsing becomes problematic. A sample can be matched to its selected event using the ID that is allocated when the event is opened. Unfortunately, to get the ID from the sample means first parsing it.
This patch adds a new sample format bit PERF_SAMPLE_IDENTIFER that puts the ID at a fixed position so that the ID can be retrieved without parsing the sample. For sample events, that is the first position immediately after the header. For non-sample events, that is the last position.
--- include/uapi/linux/perf_event.h | 3 ++- kernel/events/core.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-)
include/uapi/linux/perf_event.h +2 -1
@@ -134,8 +134,9 @@ enum perf_event_sample_format {PERF_SAMPLE_STACK_USER =1U <<13 ,PERF_SAMPLE_WEIGHT =1U <<14 ,PERF_SAMPLE_DATA_SRC =1U <<15 , +PERF_SAMPLE_IDENTIFIER =1U <<16 , - PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */ };/*
kernel/events/core.c +10 -1
@@ -1203,6 +1203,9 @@ static void perf_event__id_header_size(struct perf_event *event)if (sample_type &PERF_SAMPLE_TIME ) size +=sizeof (data->time); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) + size +=sizeof (data->id); +if (sample_type &PERF_SAMPLE_ID ) size +=sizeof (data->id);
@@ -4229,7 +4232,7 @@ static void __perf_event_header__init_id(struct perf_event_header *header,if (sample_type &PERF_SAMPLE_TIME ) data->time =perf_clock (); -if (sample_type &PERF_SAMPLE_ID ) +if (sample_type & (PERF_SAMPLE_ID |PERF_SAMPLE_IDENTIFIER )) data->id =primary_event_id (event);if (sample_type &PERF_SAMPLE_STREAM_ID )
@@ -4268,6 +4271,9 @@ static void __perf_event__output_id_sample(struct perf_output_handle *handle,if (sample_type &PERF_SAMPLE_CPU )perf_output_put (handle, data->cpu_entry); + +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); } void perf_event__output_id_sample(struct perf_event *event,
@@ -4380,6 +4386,9 @@ void perf_output_sample(struct perf_output_handle *handle,perf_output_put (handle, *header); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); +if (sample_type &PERF_SAMPLE_IP )perf_output_put (handle, data->ip);
Signature · 1 line
1.7.11.7
Namhyung Kim
maintainerRe: [PATCH V4 20/21] perf: make events stream always parsable
Hi Adrian,
Quoted 7 lines · Adrian Hunter
The event stream is not always parsable because the format of a sample is dependent on the
sample_typeof the selected event. When there is more than one selected event and thesample_typesare not the same then parsing becomes problematic. A sample can be matched to its selected event using the ID that is allocated when the event is opened. Unfortunately, to get the ID from the sample means first parsing it.
Quoted 5 lines
This patch adds a new sample format bit
PERF_SAMPLE_IDENTIFERthat puts the ID at a fixed position so that the ID can be retrieved without parsing the sample. For sample events, that is the first position immediately after the header. For non-sample events, that is the last position.
Why do we have to keep another ID again?
If all we need is the sample_type, why not just saving it directly?
And for the implementation, I guess it'll break old perf tools by parsing invalid position of data. IOW if it's recorded on a newer kernel/tool and then reported on an older perf tool (maybe on a different machine). In this case the old tool cannot recognize the PERF_SAMPLE_IDENTIFIER and try to parse it as a different type of data, right?
So I suggest put the data at the end of sample data like other new sample types added. Older tools would simply ignore that part, and newer tools can access it directly by checking event.header.size and/or evsel->sample_size.
Thanks,
Namhyung
Quoted 68 lines
Signed-off-by Adrian Hunter <[email protected]>--- include/uapi/linux/perf_event.h | 3 ++- kernel/events/core.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-)include/uapi/linux/perf_event.h +2
-1@@ -134,8 +134,9 @@ enum perf_event_sample_format {PERF_SAMPLE_STACK_USER =1U <<13 ,PERF_SAMPLE_WEIGHT =1U <<14 ,PERF_SAMPLE_DATA_SRC =1U <<15 , +PERF_SAMPLE_IDENTIFIER =1U <<16 , - PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */ };/* kernel/events/core.c +10
-2@@ -1203,6 +1203,9 @@ static void perf_event__id_header_size(struct perf_event *event)if (sample_type &PERF_SAMPLE_TIME ) size +=sizeof (data->time); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) + size +=sizeof (data->id); +if (sample_type &PERF_SAMPLE_ID ) size +=sizeof (data->id);@@ -4229,7 +4232,7 @@ static void __perf_event_header__init_id(struct perf_event_header *header,if (sample_type &PERF_SAMPLE_TIME ) data->time =perf_clock (); -if (sample_type &PERF_SAMPLE_ID ) +if (sample_type & (PERF_SAMPLE_ID |PERF_SAMPLE_IDENTIFIER )) data->id =primary_event_id (event);if (sample_type &PERF_SAMPLE_STREAM_ID )@@ -4268,6 +4271,9 @@ static void __perf_event__output_id_sample(struct perf_output_handle *handle,if (sample_type &PERF_SAMPLE_CPU )perf_output_put (handle, data->cpu_entry); + +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); } void perf_event__output_id_sample(struct perf_event *event,@@ -4380,6 +4386,9 @@ void perf_output_sample(struct perf_output_handle *handle,perf_output_put (handle, *header); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); +if (sample_type &PERF_SAMPLE_IP )perf_output_put (handle, data->ip); --1.7.11.7
Adrian Hunter
reviewerRe: [PATCH V4 20/21] perf: make events stream always parsable
Quoted 10 lines · Namhyung Kim
Hi Adrian,
Quoted 7 lines · Adrian Hunter
The event stream is not always parsable because the format of a sample is dependent on the
sample_typeof the selected event. When there is more than one selected event and thesample_typesare not the same then parsing becomes problematic. A sample can be matched to its selected event using the ID that is allocated when the event is opened. Unfortunately, to get the ID from the sample means first parsing it.
Quoted 7 lines
Quoted 5 lines
This patch adds a new sample format bit
PERF_SAMPLE_IDENTIFERthat puts the ID at a fixed position so that the ID can be retrieved without parsing the sample. For sample events, that is the first position immediately after the header. For non-sample events, that is the last position.Why do we have to keep another ID again?
It is a different place for the ID not another ID.
Quoted 1 line
If all we need is the
sample_type, why not just saving it directly?
We really want to associate the event with the attribute so the ID is needed, not just the sample type.
Quoted 7 lines
And for the implementation, I guess it'll break old perf tools by parsing invalid position of data. IOW if it's recorded on a newer kernel/tool and then reported on an older perf tool (maybe on a different machine). In this case the old tool cannot recognize the
PERF_SAMPLE_IDENTIFIERand try to parse it as a different type of data, right?
I have changed the code so that PERF_SAMPLE_IDENTIFIER is only used for non-matching sample types. Since in those cases the data was anyway not parsable, the scenario you outline cannot happen.
Quoted 5 lines
So I suggest put the data at the end of sample data like other new sample types added. Older tools would simply ignore that part, and newer tools can access it directly by checking event.header.size and/or
evsel->sample_size.
The ID will be on the end of non-sample (e.g. mmap, comm, task) events, so if tools are parsing those events backwards (as perf tools does) then they will anyway fail if they are not expecting PERF_SAMPLE_IDENTIFIER. However that scenario only happens when the data is anyway not parsable as I mentioned above.
Quoted 74 lines
Thanks,
NamhyungQuoted 68 lines
Signed-off-by Adrian Hunter <[email protected]>--- include/uapi/linux/perf_event.h | 3 ++- kernel/events/core.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-)include/uapi/linux/perf_event.h +2
-1@@ -134,8 +134,9 @@ enum perf_event_sample_format {PERF_SAMPLE_STACK_USER =1U <<13 ,PERF_SAMPLE_WEIGHT =1U <<14 ,PERF_SAMPLE_DATA_SRC =1U <<15 , +PERF_SAMPLE_IDENTIFIER =1U <<16 , - PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */ };/* kernel/events/core.c +10
-2@@ -1203,6 +1203,9 @@ static void perf_event__id_header_size(struct perf_event *event)if (sample_type &PERF_SAMPLE_TIME ) size +=sizeof (data->time); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) + size +=sizeof (data->id); +if (sample_type &PERF_SAMPLE_ID ) size +=sizeof (data->id);@@ -4229,7 +4232,7 @@ static void __perf_event_header__init_id(struct perf_event_header *header,if (sample_type &PERF_SAMPLE_TIME ) data->time =perf_clock (); -if (sample_type &PERF_SAMPLE_ID ) +if (sample_type & (PERF_SAMPLE_ID |PERF_SAMPLE_IDENTIFIER )) data->id =primary_event_id (event);if (sample_type &PERF_SAMPLE_STREAM_ID )@@ -4268,6 +4271,9 @@ static void __perf_event__output_id_sample(struct perf_output_handle *handle,if (sample_type &PERF_SAMPLE_CPU )perf_output_put (handle, data->cpu_entry); + +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); } void perf_event__output_id_sample(struct perf_event *event,@@ -4380,6 +4386,9 @@ void perf_output_sample(struct perf_output_handle *handle,perf_output_put (handle, *header); +if (sample_type &PERF_SAMPLE_IDENTIFIER ) +perf_output_put (handle, data->id); +if (sample_type &PERF_SAMPLE_IP )perf_output_put (handle, data->ip); --1.7.11.7
Adrian Hunter
reviewerPATCH v4 21/21 perf tools: add support for PERF_SAMPLE_IDENTFIER
In reply to Adrian HunterEnable parsing of samples with sample format bit PERF_SAMPLE_IDENTFIER. In addition, if the kernel supports it, prefer it to selecting PERF_SAMPLE_ID thereby avoiding the need to force compatible sample types.
--- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/util/event.h | 9 +++-- tools/perf/util/evlist.c | 83 +++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.c | 41 +++++++++++++++++---- tools/perf/util/evsel.h | 3 +- 6 files changed, 125 insertions(+), 14 deletions(-)
tools/perf/tests/mmap-basic.c +1 -1
@@ -72,7 +72,7 @@ int test__basic_mmap(void) } evsels[i]->attr.wakeup_events =1 ; -perf_evsel__set_sample_id (evsels[i]); +perf_evsel__set_sample_id (evsels[i], false);perf_evlist__add (evlist, evsels[i]);
tools/perf/util/event.h +6 -3
@@ -53,7 +53,8 @@ struct read_event { (PERF_SAMPLE_IP |PERF_SAMPLE_TID | \PERF_SAMPLE_TIME |PERF_SAMPLE_ADDR | \PERF_SAMPLE_ID |PERF_SAMPLE_STREAM_ID | \ -PERF_SAMPLE_CPU |PERF_SAMPLE_PERIOD ) +PERF_SAMPLE_CPU |PERF_SAMPLE_PERIOD | \ +PERF_SAMPLE_IDENTIFIER )/* * Events have compatible sample types if the following bits all have the same
@@ -61,13 +62,15 @@ struct read_event {* events the order is: PERF_SAMPLE_IP, PERF_SAMPLE_TID, PERF_SAMPLE_TIME, * PERF_SAMPLE_ADDR, PERF_SAMPLE_ID. For non-sample events the sample members * are accessed in reverse order. The order is: PERF_SAMPLE_ID, -* PERF_SAMPLE_STREAM_ID, PERF_SAMPLE_CPU. +* PERF_SAMPLE_STREAM_ID, PERF_SAMPLE_CPU. PERF_SAMPLE_IDENTIFIER is added for +* completeness but it should not be used with PERF_SAMPLE_ID. Sample types +* that include PERF_SAMPLE_IDENTIFIER are always compatible. */ #define PERF_COMPAT_MASK \ (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ - PERF_SAMPLE_CPU) + PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER)struct sample_event {struct perf_event_header header;
tools/perf/util/evlist.c +81 -2
107 lines not on this page · raw message
tools/perf/util/evlist.h +1 -0
@@ -88,6 +88,7 @@ int perf_evlist__open(struct perf_evlist *evlist);void perf_evlist__close (struct perf_evlist *evlist);void perf_evlist__make_sample_types_compatible (struct perf_evlist *evlist); +bool perf_can_sample_identifier (void );void perf_evlist__config (struct perf_evlist *evlist,struct perf_record_opts *opts);
tools/perf/util/evsel.c +34 -7
100 lines not on this page · raw message
tools/perf/util/evsel.h +2 -1
@@ -148,7 +148,8 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,#define perf_evsel__reset_sample_bit (evsel, bit) \ __perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit) -void perf_evsel__set_sample_id (struct perf_evsel *evsel); +void perf_evsel__set_sample_id (struct perf_evsel *evsel, +bool use_sample_identifier);int perf_evsel__set_filter (struct perf_evsel *evsel,int ncpus,int nthreads,const char *filter);
Signature · 1 line
1.7.11.7