linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] perf tools: Various updates
@ 2012-08-16 19:10 Robert Richter
  2012-08-16 19:10 ` [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids Robert Richter
                   ` (8 more replies)
  0 siblings, 9 replies; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

This patch set contains various perf tools updates. Most patches deal
with event naming. If the event name is unknown it is named like the
command line string of it. This is esp. valueable for pmu events like
for AMD IBS:

     $ perf report | grep '^#.*event'
     # event : name = ibs_op/cnt_ctl=1/GH, type = 7, config = 0x80000, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 0, precise_ip = 0, id = { 
     # event : name = ibs_fetch/config=0/, type = 6, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 1, precise_ip = 0, id = { 57, 
     # Samples: 20K of event 'ibs_op/cnt_ctl=1/GH'
     # Samples: 4K of event 'ibs_fetch/config=0/'

Another patch stores the pmu/type mapping in the header of perf.data.
Now the pmu types are known and event can be attributed to a certain
dynamically allocated pmu:

     # pmu mappings: ibs_op = 7, ibs_fetch = 6, cpu = 4, breakpoint = 5, tracepoint = 2, software = 1

This is usefull for analysing the perf.data file on a system where the
pmu mappings are no longer available, e.g. on a remote system or if
the pmu has been unregistered.

Patches base on commit 0c21f736e0a37c50f66ab248d2a52f711b28a4e4
(acme/perf/core):

  perf evlist: Introduce evsel list accessors (2012-08-15 10:14:18 -0300)

-Robert

Robert Richter (8):
  perf tools: Fix type for evsel->ids and add size check for ids
  perf tools: Report number of pmu type of unknown events
  perf tools: Rename some variables for better understanding
  perf tools: Rename global variable 'events' in util/header.c
  perf tools: Catch event names from command line
  perf tools: Refactor print_event_desc()
  perf report: Update event names from header description
  perf tools: Add pmu mappings to header information

 tools/perf/util/evsel.c        |    3 +-
 tools/perf/util/evsel.h        |    2 +-
 tools/perf/util/header.c       |  357 ++++++++++++++++++++++++++++++----------
 tools/perf/util/header.h       |    3 +-
 tools/perf/util/parse-events.c |   12 ++
 tools/perf/util/parse-events.h |    1 +
 tools/perf/util/parse-events.l |   50 +++++-
 tools/perf/util/parse-events.y |   20 ++-
 tools/perf/util/pmu.c          |   50 ++++++-
 tools/perf/util/pmu.h          |    2 +
 10 files changed, 396 insertions(+), 104 deletions(-)

-- 
1.7.8.6



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-21 16:24   ` [tip:perf/core] perf tools: Fix type for evsel-> ids " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 2/8] perf tools: Report number of pmu type of unknown events Robert Richter
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

Use same type for ids everywhere.

In case of writing to perf.data the size is u32. In pipe mode it is
limited to header.size (less than u16). Adding a size check here.

Size overflow due to casting shouldn't actually happen in practice,
but during development this may cause type missmatch warninngs/errors,
unifying types avoids this.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/evsel.h  |    2 +-
 tools/perf/util/header.c |   11 +++++++----
 tools/perf/util/header.h |    2 +-
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 65f39fd..94f6ba1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -53,7 +53,7 @@ struct perf_evsel {
 	u64			*id;
 	struct perf_counts	*counts;
 	int			idx;
-	int			ids;
+	u32			ids;
 	struct hists		hists;
 	char			*name;
 	struct event_format	*tp_format;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 77832b8..471b0c4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2240,7 +2240,7 @@ out_delete_evlist:
 }
 
 int perf_event__synthesize_attr(struct perf_tool *tool,
-				struct perf_event_attr *attr, u16 ids, u64 *id,
+				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process)
 {
 	union perf_event *ev;
@@ -2261,9 +2261,12 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 	memcpy(ev->attr.id, id, ids * sizeof(u64));
 
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
-	ev->attr.header.size = size;
+	ev->attr.header.size = (u16)size;
 
-	err = process(tool, ev, NULL, NULL);
+	if (ev->attr.header.size == size)
+		err = process(tool, ev, NULL, NULL);
+	else
+		err = -E2BIG;
 
 	free(ev);
 
@@ -2292,7 +2295,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 int perf_event__process_attr(union perf_event *event,
 			     struct perf_evlist **pevlist)
 {
-	unsigned int i, ids, n_ids;
+	u32 i, ids, n_ids;
 	struct perf_evsel *evsel;
 	struct perf_evlist *evlist = *pevlist;
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e..24962e7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -99,7 +99,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
 int perf_event__synthesize_attr(struct perf_tool *tool,
-				struct perf_event_attr *attr, u16 ids, u64 *id,
+				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process);
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/8] perf tools: Report number of pmu type of unknown events
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
  2012-08-16 19:10 ` [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-21 16:25   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 3/8] perf tools: Rename some variables for better understanding Robert Richter
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

If detection fails and an event name is unknown, report the type
number. Example perf header output:

 # Samples: 10K of event 'unknown attr type: 7'

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/evsel.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6c7dcc1..7ff3c8f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -319,7 +319,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
 		break;
 
 	default:
-		scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
+		scnprintf(bf, sizeof(bf), "unknown attr type: %d",
+			  evsel->attr.type);
 		break;
 	}
 
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/8] perf tools: Rename some variables for better understanding
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
  2012-08-16 19:10 ` [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids Robert Richter
  2012-08-16 19:10 ` [PATCH 2/8] perf tools: Report number of pmu type of unknown events Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-17 15:34   ` Arnaldo Carvalho de Melo
  2012-08-21 16:26   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 4/8] perf tools: Rename global variable 'events' in util/header.c Robert Richter
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

Trivial patch to improve understanding of code.

Varible attr is usually used for struct perf_event_attr. Using it in a
different context is irritating. Thus, renaming it.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/header.c |   42 +++++++++++++++++++++---------------------
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 471b0c4..e2e5129 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -608,11 +608,11 @@ static int write_nrcpus(int fd, struct perf_header *h __used,
 static int write_event_desc(int fd, struct perf_header *h __used,
 			    struct perf_evlist *evlist)
 {
-	struct perf_evsel *attr;
+	struct perf_evsel *evsel;
 	u32 nre = 0, nri, sz;
 	int ret;
 
-	list_for_each_entry(attr, &evlist->entries, node)
+	list_for_each_entry(evsel, &evlist->entries, node)
 		nre++;
 
 	/*
@@ -625,14 +625,14 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 	/*
 	 * size of perf_event_attr struct
 	 */
-	sz = (u32)sizeof(attr->attr);
+	sz = (u32)sizeof(evsel->attr);
 	ret = do_write(fd, &sz, sizeof(sz));
 	if (ret < 0)
 		return ret;
 
-	list_for_each_entry(attr, &evlist->entries, node) {
+	list_for_each_entry(evsel, &evlist->entries, node) {
 
-		ret = do_write(fd, &attr->attr, sz);
+		ret = do_write(fd, &evsel->attr, sz);
 		if (ret < 0)
 			return ret;
 		/*
@@ -642,7 +642,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 		 * copy into an nri to be independent of the
 		 * type of ids,
 		 */
-		nri = attr->ids;
+		nri = evsel->ids;
 		ret = do_write(fd, &nri, sizeof(nri));
 		if (ret < 0)
 			return ret;
@@ -650,13 +650,13 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 		/*
 		 * write event string as passed on cmdline
 		 */
-		ret = do_write_string(fd, perf_evsel__name(attr));
+		ret = do_write_string(fd, perf_evsel__name(evsel));
 		if (ret < 0)
 			return ret;
 		/*
 		 * write unique ids for this event
 		 */
-		ret = do_write(fd, attr->id, attr->ids * sizeof(u64));
+		ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
 		if (ret < 0)
 			return ret;
 	}
@@ -1683,7 +1683,7 @@ int perf_session__write_header(struct perf_session *session,
 	struct perf_file_header f_header;
 	struct perf_file_attr   f_attr;
 	struct perf_header *header = &session->header;
-	struct perf_evsel *attr, *pair = NULL;
+	struct perf_evsel *evsel, *pair = NULL;
 	int err;
 
 	lseek(fd, sizeof(f_header), SEEK_SET);
@@ -1691,9 +1691,9 @@ int perf_session__write_header(struct perf_session *session,
 	if (session->evlist != evlist)
 		pair = perf_evlist__first(session->evlist);
 
-	list_for_each_entry(attr, &evlist->entries, node) {
-		attr->id_offset = lseek(fd, 0, SEEK_CUR);
-		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		evsel->id_offset = lseek(fd, 0, SEEK_CUR);
+		err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
 		if (err < 0) {
 out_err_write:
 			pr_debug("failed to write perf header\n");
@@ -1703,19 +1703,19 @@ out_err_write:
 			err = do_write(fd, pair->id, pair->ids * sizeof(u64));
 			if (err < 0)
 				goto out_err_write;
-			attr->ids += pair->ids;
+			evsel->ids += pair->ids;
 			pair = perf_evsel__next(pair);
 		}
 	}
 
 	header->attr_offset = lseek(fd, 0, SEEK_CUR);
 
-	list_for_each_entry(attr, &evlist->entries, node) {
+	list_for_each_entry(evsel, &evlist->entries, node) {
 		f_attr = (struct perf_file_attr){
-			.attr = attr->attr,
+			.attr = evsel->attr,
 			.ids  = {
-				.offset = attr->id_offset,
-				.size   = attr->ids * sizeof(u64),
+				.offset = evsel->id_offset,
+				.size   = evsel->ids * sizeof(u64),
 			}
 		};
 		err = do_write(fd, &f_attr, sizeof(f_attr));
@@ -2277,12 +2277,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
 {
-	struct perf_evsel *attr;
+	struct perf_evsel *evsel;
 	int err = 0;
 
-	list_for_each_entry(attr, &session->evlist->entries, node) {
-		err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
-						  attr->id, process);
+	list_for_each_entry(evsel, &session->evlist->entries, node) {
+		err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
+						  evsel->id, process);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
 			return err;
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/8] perf tools: Rename global variable 'events' in util/header.c
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (2 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 3/8] perf tools: Rename some variables for better understanding Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-21 16:27   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 5/8] perf tools: Catch event names from command line Robert Richter
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

Trivial patch that renames global variable 'events' in util/header.c.

Use a more specific naming to avoid conflicts. Same for variable
'event_count'.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/header.c |   40 ++++++++++++++++++++--------------------
 1 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e2e5129..1e5b6aa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -23,8 +23,8 @@
 
 static bool no_buildid_cache = false;
 
-static int event_count;
-static struct perf_trace_event_type *events;
+static int trace_event_count;
+static struct perf_trace_event_type *trace_events;
 
 static u32 header_argc;
 static const char **header_argv;
@@ -36,24 +36,24 @@ int perf_header__push_event(u64 id, const char *name)
 	if (strlen(name) > MAX_EVENT_NAME)
 		pr_warning("Event %s will be truncated\n", name);
 
-	nevents = realloc(events, (event_count + 1) * sizeof(*events));
+	nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events));
 	if (nevents == NULL)
 		return -ENOMEM;
-	events = nevents;
+	trace_events = nevents;
 
-	memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
-	events[event_count].event_id = id;
-	strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
-	event_count++;
+	memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type));
+	trace_events[trace_event_count].event_id = id;
+	strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1);
+	trace_event_count++;
 	return 0;
 }
 
 char *perf_header__find_event(u64 id)
 {
 	int i;
-	for (i = 0 ; i < event_count; i++) {
-		if (events[i].event_id == id)
-			return events[i].name;
+	for (i = 0 ; i < trace_event_count; i++) {
+		if (trace_events[i].event_id == id)
+			return trace_events[i].name;
 	}
 	return NULL;
 }
@@ -1726,9 +1726,9 @@ out_err_write:
 	}
 
 	header->event_offset = lseek(fd, 0, SEEK_CUR);
-	header->event_size = event_count * sizeof(struct perf_trace_event_type);
-	if (events) {
-		err = do_write(fd, events, header->event_size);
+	header->event_size = trace_event_count * sizeof(struct perf_trace_event_type);
+	if (trace_events) {
+		err = do_write(fd, trace_events, header->event_size);
 		if (err < 0) {
 			pr_debug("failed to write perf header events\n");
 			return err;
@@ -2211,13 +2211,13 @@ int perf_session__read_header(struct perf_session *session, int fd)
 
 	if (f_header.event_types.size) {
 		lseek(fd, f_header.event_types.offset, SEEK_SET);
-		events = malloc(f_header.event_types.size);
-		if (events == NULL)
+		trace_events = malloc(f_header.event_types.size);
+		if (trace_events == NULL)
 			return -ENOMEM;
-		if (perf_header__getbuffer64(header, fd, events,
+		if (perf_header__getbuffer64(header, fd, trace_events,
 					     f_header.event_types.size))
 			goto out_errno;
-		event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
+		trace_event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
 	}
 
 	perf_header__process_sections(header, fd, &session->pevent,
@@ -2362,8 +2362,8 @@ int perf_event__synthesize_event_types(struct perf_tool *tool,
 	struct perf_trace_event_type *type;
 	int i, err = 0;
 
-	for (i = 0; i < event_count; i++) {
-		type = &events[i];
+	for (i = 0; i < trace_event_count; i++) {
+		type = &trace_events[i];
 
 		err = perf_event__synthesize_event_type(tool, type->event_id,
 							type->name, process,
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 5/8] perf tools: Catch event names from command line
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (3 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 4/8] perf tools: Rename global variable 'events' in util/header.c Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-20 17:42   ` Jiri Olsa
  2012-08-27 16:54   ` [tip:perf/core] perf tools: Catch event names from command line tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 6/8] perf tools: Refactor print_event_desc() Robert Richter
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

Use command line string provided by the -e option to name events. This
way we get unique events names that also support pmu event syntax
(<pmu_name>/<config>/<modifier>). No need to reconstruct the name
anymore from its attributes. We use the event_desc of the header to
store the name in the perf.data header. Thus it is also available for
perf report.

Implemented by putting the parser in different states to parse events
or configs.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/parse-events.c |   12 +++++++++
 tools/perf/util/parse-events.h |    1 +
 tools/perf/util/parse-events.l |   50 ++++++++++++++++++++++++++++++++--------
 tools/perf/util/parse-events.y |   20 ++++++++++++++-
 4 files changed, 71 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 925784a..b246303 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -751,6 +751,18 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	return 0;
 }
 
+int parse_events_name(struct list_head *list, char *name)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, list, node) {
+		if (!evsel->name)
+			evsel->name = strdup(name);
+	}
+
+	return 0;
+}
+
 static int parse_events__scanner(const char *str, void *data, int start_token)
 {
 	YY_BUFFER_STATE buffer;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 0b9782d..c356e44 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -81,6 +81,7 @@ int parse_events__term_clone(struct parse_events__term **new,
 void parse_events__free_terms(struct list_head *terms);
 int parse_events__modifier_event(struct list_head *list, char *str, bool add);
 int parse_events__modifier_group(struct list_head *list, char *event_mod);
+int parse_events_name(struct list_head *list, char *name);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
 				char *sys, char *event);
 int parse_events_add_numeric(struct list_head **list, int *idx,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 2c0d006..f5e28dc 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -70,6 +70,12 @@ static int term(yyscan_t scanner, int type)
 %}
 
 %x mem
+%s config
+%x event
+
+group		[^,{}/]*[{][^}]*[}][^,{}/]*
+event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
+event		[^,{}/]+
 
 num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
@@ -84,7 +90,13 @@ modifier_bp	[rwx]{1,3}
 	{
 		int start_token;
 
-		start_token = (int) parse_events_get_extra(yyscanner);
+		start_token = parse_events_get_extra(yyscanner);
+
+		if (start_token == PE_START_TERMS)
+			BEGIN(config);
+		else if (start_token == PE_START_EVENTS)
+			BEGIN(event);
+
 		if (start_token) {
 			parse_events_set_extra(NULL, yyscanner);
 			return start_token;
@@ -92,6 +104,26 @@ modifier_bp	[rwx]{1,3}
          }
 %}
 
+<event>{
+
+{group}		{
+			BEGIN(INITIAL); yyless(0);
+		}
+
+{event_pmu}	|
+{event}		{
+			str(yyscanner, PE_EVENT_NAME);
+			BEGIN(INITIAL); yyless(0);
+			return PE_EVENT_NAME;
+		}
+
+.		|
+<<EOF>>		{
+			BEGIN(INITIAL); yyless(0);
+		}
+
+}
+
 cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
 stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
 stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -127,18 +159,16 @@ speculative-read|speculative-load	|
 refs|Reference|ops|access		|
 misses|miss				{ return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
 
-	/*
-	 * These are event config hardcoded term names to be specified
-	 * within xxx/.../ syntax. So far we dont clash with other names,
-	 * so we can put them here directly. In case the we have a conflict
-	 * in future, this needs to go into '//' condition block.
-	 */
+<config>{
 config			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
 config1			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
 config2			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
 name			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
 period			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
 branch_type		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+,			{ return ','; }
+"/"			{ BEGIN(INITIAL); return '/'; }
+}
 
 mem:			{ BEGIN(mem); return PE_PREFIX_MEM; }
 r{num_raw_hex}		{ return raw(yyscanner); }
@@ -147,11 +177,11 @@ r{num_raw_hex}		{ return raw(yyscanner); }
 
 {modifier_event}	{ return str(yyscanner, PE_MODIFIER_EVENT); }
 {name}			{ return str(yyscanner, PE_NAME); }
-"/"			{ return '/'; }
+"/"			{ BEGIN(config); return '/'; }
 -			{ return '-'; }
-,			{ return ','; }
+,			{ BEGIN(event); return ','; }
 :			{ return ':'; }
-"{"			{ return '{'; }
+"{"			{ BEGIN(event); return '{'; }
 "}"			{ return '}'; }
 =			{ return '='; }
 \n			{ }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 66850f8..42d9a17 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -27,6 +27,7 @@ do { \
 
 %token PE_START_EVENTS PE_START_TERMS
 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
+%token PE_EVENT_NAME
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
@@ -42,6 +43,7 @@ do { \
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
 %type <str> PE_MODIFIER_BP
+%type <str> PE_EVENT_NAME
 %type <num> value_sym
 %type <head> event_config
 %type <term> event_term
@@ -53,6 +55,8 @@ do { \
 %type <head> event_legacy_numeric
 %type <head> event_legacy_raw
 %type <head> event_def
+%type <head> event_mod
+%type <head> event_name
 %type <head> event
 %type <head> events
 %type <head> group_def
@@ -143,8 +147,10 @@ events ',' event
 |
 event
 
-event:
-event_def PE_MODIFIER_EVENT
+event: event_mod
+
+event_mod:
+event_name PE_MODIFIER_EVENT
 {
 	struct list_head *list = $1;
 
@@ -157,6 +163,16 @@ event_def PE_MODIFIER_EVENT
 	$$ = list;
 }
 |
+event_name
+
+event_name:
+PE_EVENT_NAME event_def
+{
+	ABORT_ON(parse_events_name($2, $1));
+	free($1);
+	$$ = $2;
+}
+|
 event_def
 
 event_def: event_pmu |
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 6/8] perf tools: Refactor print_event_desc()
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (4 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 5/8] perf tools: Catch event names from command line Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-27 16:55   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 7/8] perf report: Update event names from header description Robert Richter
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

For later use we need a function read_event_desc() for processing the
event_desc feature. Split it from print_event_desc().

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/header.c |  134 ++++++++++++++++++++++++++++++++--------------
 1 files changed, 93 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1e5b6aa..7454cf4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1148,12 +1148,29 @@ static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp)
 	}
 }
 
-static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
+static void free_event_desc(struct perf_evsel *events)
 {
-	struct perf_event_attr attr;
-	uint64_t id;
+	struct perf_evsel *evsel;
+
+	if (!events)
+		return;
+
+	for (evsel = events; evsel->attr.size; evsel++) {
+		if (evsel->name)
+			free(evsel->name);
+		if (evsel->id)
+			free(evsel->id);
+	}
+
+	free(events);
+}
+
+static struct perf_evsel *
+read_event_desc(struct perf_header *ph, int fd)
+{
+	struct perf_evsel *evsel, *events = NULL;
+	u64 *id;
 	void *buf = NULL;
-	char *str;
 	u32 nre, sz, nr, i, j;
 	ssize_t ret;
 	size_t msz;
@@ -1173,18 +1190,22 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 	if (ph->needs_swap)
 		sz = bswap_32(sz);
 
-	memset(&attr, 0, sizeof(attr));
-
 	/* buffer to hold on file attr struct */
 	buf = malloc(sz);
 	if (!buf)
 		goto error;
 
-	msz = sizeof(attr);
+	/* the last event terminates with evsel->attr.size == 0: */
+	events = calloc(nre + 1, sizeof(*events));
+	if (!events)
+		goto error;
+
+	msz = sizeof(evsel->attr);
 	if (sz < msz)
 		msz = sz;
 
-	for (i = 0 ; i < nre; i++) {
+	for (i = 0, evsel = events; i < nre; evsel++, i++) {
+		evsel->idx = i;
 
 		/*
 		 * must read entire on-file attr struct to
@@ -1197,7 +1218,7 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 		if (ph->needs_swap)
 			perf_event__attr_swap(buf);
 
-		memcpy(&attr, buf, msz);
+		memcpy(&evsel->attr, buf, msz);
 
 		ret = read(fd, &nr, sizeof(nr));
 		if (ret != (ssize_t)sizeof(nr))
@@ -1206,51 +1227,82 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 		if (ph->needs_swap)
 			nr = bswap_32(nr);
 
-		str = do_read_string(fd, ph);
-		fprintf(fp, "# event : name = %s, ", str);
-		free(str);
+		evsel->name = do_read_string(fd, ph);
+
+		if (!nr)
+			continue;
+
+		id = calloc(nr, sizeof(*id));
+		if (!id)
+			goto error;
+		evsel->ids = nr;
+		evsel->id = id;
+
+		for (j = 0 ; j < nr; j++) {
+			ret = read(fd, id, sizeof(*id));
+			if (ret != (ssize_t)sizeof(*id))
+				goto error;
+			if (ph->needs_swap)
+				*id = bswap_64(*id);
+			id++;
+		}
+	}
+out:
+	if (buf)
+		free(buf);
+	return events;
+error:
+	if (events)
+		free_event_desc(events);
+	events = NULL;
+	goto out;
+}
+
+static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
+{
+	struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
+	u32 j;
+	u64 *id;
+
+	if (!events) {
+		fprintf(fp, "# event desc: not available or unable to read\n");
+		return;
+	}
+
+	for (evsel = events; evsel->attr.size; evsel++) {
+		fprintf(fp, "# event : name = %s, ", evsel->name);
 
 		fprintf(fp, "type = %d, config = 0x%"PRIx64
 			    ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
-				attr.type,
-				(u64)attr.config,
-				(u64)attr.config1,
-				(u64)attr.config2);
+				evsel->attr.type,
+				(u64)evsel->attr.config,
+				(u64)evsel->attr.config1,
+				(u64)evsel->attr.config2);
 
 		fprintf(fp, ", excl_usr = %d, excl_kern = %d",
-				attr.exclude_user,
-				attr.exclude_kernel);
+				evsel->attr.exclude_user,
+				evsel->attr.exclude_kernel);
 
 		fprintf(fp, ", excl_host = %d, excl_guest = %d",
-				attr.exclude_host,
-				attr.exclude_guest);
+				evsel->attr.exclude_host,
+				evsel->attr.exclude_guest);
 
-		fprintf(fp, ", precise_ip = %d", attr.precise_ip);
+		fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
 
-		if (nr)
+		if (evsel->ids) {
 			fprintf(fp, ", id = {");
-
-		for (j = 0 ; j < nr; j++) {
-			ret = read(fd, &id, sizeof(id));
-			if (ret != (ssize_t)sizeof(id))
-				goto error;
-
-			if (ph->needs_swap)
-				id = bswap_64(id);
-
-			if (j)
-				fputc(',', fp);
-
-			fprintf(fp, " %"PRIu64, id);
-		}
-		if (nr && j == nr)
+			for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
+				if (j)
+					fputc(',', fp);
+				fprintf(fp, " %"PRIu64, *id);
+			}
 			fprintf(fp, " }");
+		}
+
 		fputc('\n', fp);
 	}
-	free(buf);
-	return;
-error:
-	fprintf(fp, "# event desc: not available or unable to read\n");
+
+	free_event_desc(events);
 }
 
 static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp)
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 7/8] perf report: Update event names from header description
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (5 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 6/8] perf tools: Refactor print_event_desc() Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-27 16:56   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-16 19:10 ` [PATCH 8/8] perf tools: Add pmu mappings to header information Robert Richter
  2012-08-17 16:18 ` [PATCH 0/8] perf tools: Various updates Arnaldo Carvalho de Melo
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

Name events based on the event description in the perf.data header.

Example output:

 $ perf report | grep '^#.*event'
 # event : name = ibs_op/cnt_ctl=1/GH, type = 7, config = 0x80000, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 0, precise_ip = 0, id = { 49, 50, 51, 52, 53, 54, 55, 56 }
 # event : name = ibs_fetch/config=0/, type = 6, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 1, precise_ip = 0, id = { 57, 58, 59, 60, 61, 62, 63, 64 }
 # Samples: 20K of event 'ibs_op/cnt_ctl=1/GH'
 # Samples: 4K of event 'ibs_fetch/config=0/'

Note the new pmu event syntax of the names.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/header.c |   52 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7454cf4..c0311b3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1556,6 +1556,56 @@ static int process_build_id(struct perf_file_section *section,
 	return 0;
 }
 
+static struct perf_evsel *
+perf_evlist_find_by_index(struct perf_evlist *evlist, int idx)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if (evsel->idx == idx)
+			return evsel;
+	}
+
+	return NULL;
+}
+
+static void
+perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event)
+{
+	struct perf_evsel *evsel;
+
+	if (!event->name)
+		return;
+
+	evsel = perf_evlist_find_by_index(evlist, event->idx);
+	if (!evsel)
+		return;
+
+	if (evsel->name)
+		return;
+
+	evsel->name = strdup(event->name);
+}
+
+static int
+process_event_desc(struct perf_file_section *section __unused,
+		   struct perf_header *header, int feat __unused, int fd,
+		   void *data __used)
+{
+	struct perf_session *session = container_of(header, struct perf_session, header);
+	struct perf_evsel *evsel, *events = read_event_desc(header, fd);
+
+	if (!events)
+		return 0;
+
+	for (evsel = events; evsel->attr.size; evsel++)
+		perf_evlist__set_event_name(session->evlist, evsel);
+
+	free_event_desc(events);
+
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
 	void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1589,7 +1639,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPA(HEADER_CPUDESC,	cpudesc),
 	FEAT_OPA(HEADER_CPUID,		cpuid),
 	FEAT_OPA(HEADER_TOTAL_MEM,	total_mem),
-	FEAT_OPA(HEADER_EVENT_DESC,	event_desc),
+	FEAT_OPP(HEADER_EVENT_DESC,	event_desc),
 	FEAT_OPA(HEADER_CMDLINE,	cmdline),
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 8/8] perf tools: Add pmu mappings to header information
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (6 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 7/8] perf report: Update event names from header description Robert Richter
@ 2012-08-16 19:10 ` Robert Richter
  2012-08-27 16:57   ` [tip:perf/core] " tip-bot for Robert Richter
  2012-08-17 16:18 ` [PATCH 0/8] perf tools: Various updates Arnaldo Carvalho de Melo
  8 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-16 19:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML, Robert Richter

With dynamic pmu allocation there are also dynamically assigned pmu
ids. These ids are used in event->attr.type to describe the pmu to be
used for that event. The information is available in sysfs, e.g:

 /sys/bus/event_source/devices/breakpoint/type: 5
 /sys/bus/event_source/devices/cpu/type: 4
 /sys/bus/event_source/devices/ibs_fetch/type: 6
 /sys/bus/event_source/devices/ibs_op/type: 7
 /sys/bus/event_source/devices/software/type: 1
 /sys/bus/event_source/devices/tracepoint/type: 2

These mappings are needed to know which samples belong to which pmu.
If a pmu is added dynamically like for ibs_fetch or ibs_op the type
value may vary.

Now, when decoding samples from perf.data this information in sysfs
might be no longer available or may have changed. We need to store it
in perf.data. Using the header for this. Now the header information
created with perf report contains an additional section looking like
this:

 # pmu mappings: ibs_op = 7, ibs_fetch = 6, cpu = 4, breakpoint = 5, tracepoint = 2, software = 1

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/header.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h |    1 +
 tools/perf/util/pmu.c    |   50 ++++++++++++++++++++++++++++-
 tools/perf/util/pmu.h    |    2 +
 4 files changed, 129 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c0311b3..26262d5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -20,6 +20,7 @@
 #include "symbol.h"
 #include "debug.h"
 #include "cpumap.h"
+#include "pmu.h"
 
 static bool no_buildid_cache = false;
 
@@ -1004,6 +1005,45 @@ done:
 }
 
 /*
+ * File format:
+ *
+ * struct pmu_mappings {
+ *	u32	pmu_num;
+ *	struct pmu_map {
+ *		u32	type;
+ *		char	name[];
+ *	}[pmu_num];
+ * };
+ */
+
+static int write_pmu_mappings(int fd, struct perf_header *h __used,
+			      struct perf_evlist *evlist __used)
+{
+	struct perf_pmu *pmu = NULL;
+	off_t offset = lseek(fd, 0, SEEK_CUR);
+	__u32 pmu_num = 0;
+
+	/* write real pmu_num later */
+	do_write(fd, &pmu_num, sizeof(pmu_num));
+
+	while ((pmu = perf_pmu__scan(pmu))) {
+		if (!pmu->name)
+			continue;
+		pmu_num++;
+		do_write(fd, &pmu->type, sizeof(pmu->type));
+		do_write_string(fd, pmu->name);
+	}
+
+	if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
+		/* discard all */
+		lseek(fd, offset, SEEK_SET);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
  * default get_cpuid(): nothing gets recorded
  * actual implementation must be in arch/$(ARCH)/util/header.c
  */
@@ -1389,6 +1429,43 @@ static void print_branch_stack(struct perf_header *ph __used, int fd __used,
 	fprintf(fp, "# contains samples with branch stack\n");
 }
 
+static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
+{
+	const char *delimiter = "# pmu mappings: ";
+	char *name;
+	int ret;
+	u32 pmu_num;
+	u32 type;
+
+	ret = read(fd, &pmu_num, sizeof(pmu_num));
+	if (ret != sizeof(pmu_num))
+		goto error;
+
+	if (!pmu_num) {
+		fprintf(fp, "# pmu mappings: not available\n");
+		return;
+	}
+
+	while (pmu_num) {
+		if (read(fd, &type, sizeof(type)) != sizeof(type))
+			break;
+		name = do_read_string(fd, ph);
+		if (!name)
+			break;
+		pmu_num--;
+		fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type);
+		free(name);
+		delimiter = ", ";
+	}
+
+	fprintf(fp, "\n");
+
+	if (!pmu_num)
+		return;
+error:
+	fprintf(fp, "# pmu mappings: unable to read\n");
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
 				    char *filename,
 				    struct perf_session *session)
@@ -1644,6 +1721,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
 	FEAT_OPA(HEADER_BRANCH_STACK,	branch_stack),
+	FEAT_OPA(HEADER_PMU_MAPPINGS,	pmu_mappings),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 24962e7..9d5eedc 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -28,6 +28,7 @@ enum {
 	HEADER_CPU_TOPOLOGY,
 	HEADER_NUMA_TOPOLOGY,
 	HEADER_BRANCH_STACK,
+	HEADER_PMU_MAPPINGS,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a4..6631d82 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -10,6 +10,8 @@
 #include "pmu.h"
 #include "parse-events.h"
 
+#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
+
 int perf_pmu_parse(struct list_head *list, char *name);
 extern FILE *perf_pmu_in;
 
@@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format)
 		return -1;
 
 	snprintf(path, PATH_MAX,
-		 "%s/bus/event_source/devices/%s/format", sysfs, name);
+		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
 
 	if (stat(path, &st) < 0)
 		return 0;	/* no error if format does not exist */
@@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type)
 		return -1;
 
 	snprintf(path, PATH_MAX,
-		 "%s/bus/event_source/devices/%s/type", sysfs, name);
+		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
 
 	if (stat(path, &st) < 0)
 		return -1;
@@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type)
 	return ret;
 }
 
+/* Add all pmus in sysfs to pmu list: */
+static void pmu_read_sysfs(void)
+{
+	char path[PATH_MAX];
+	const char *sysfs;
+	DIR *dir;
+	struct dirent *dent;
+
+	sysfs = sysfs_find_mountpoint();
+	if (!sysfs)
+		return;
+
+	snprintf(path, PATH_MAX,
+		 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
+
+	dir = opendir(path);
+	if (!dir)
+		return;
+
+	while ((dent = readdir(dir))) {
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+		/* add to static LIST_HEAD(pmus): */
+		perf_pmu__find(dent->d_name);
+	}
+
+	closedir(dir);
+}
+
 static struct perf_pmu *pmu_lookup(char *name)
 {
 	struct perf_pmu *pmu;
@@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name)
 	return NULL;
 }
 
+struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
+{
+	/*
+	 * pmu iterator: If pmu is NULL, we start at the begin,
+	 * otherwise return the next pmu. Returns NULL on end.
+	 */
+	if (!pmu) {
+		pmu_read_sysfs();
+		pmu = list_prepare_entry(pmu, &pmus, list);
+	}
+	list_for_each_entry_continue(pmu, &pmus, list)
+		return pmu;
+	return NULL;
+}
+
 struct perf_pmu *perf_pmu__find(char *name)
 {
 	struct perf_pmu *pmu;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 535f2c5..47f68d3 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -46,5 +46,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
 			 int config, unsigned long *bits);
 void perf_pmu__set_format(unsigned long *bits, long from, long to);
 
+struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
+
 int perf_pmu__test(void);
 #endif /* __PMU_H */
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/8] perf tools: Rename some variables for better understanding
  2012-08-16 19:10 ` [PATCH 3/8] perf tools: Rename some variables for better understanding Robert Richter
@ 2012-08-17 15:34   ` Arnaldo Carvalho de Melo
  2012-08-21 16:26   ` [tip:perf/core] " tip-bot for Robert Richter
  1 sibling, 0 replies; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-17 15:34 UTC (permalink / raw)
  To: Robert Richter; +Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML

Em Thu, Aug 16, 2012 at 09:10:19PM +0200, Robert Richter escreveu:
> Trivial patch to improve understanding of code.
> 
> Varible attr is usually used for struct perf_event_attr. Using it in a
> different context is irritating. Thus, renaming it.

Right, this is historical stuff, originally it was a perf_event_attr, so
'attr', when I converted it to evsel I kept 'attr' to reduce the patch
size.

Anyway, applying, thanks,

- Arnaldo
 
> Signed-off-by: Robert Richter <robert.richter@amd.com>
> ---
>  tools/perf/util/header.c |   42 +++++++++++++++++++++---------------------
>  1 files changed, 21 insertions(+), 21 deletions(-)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 471b0c4..e2e5129 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -608,11 +608,11 @@ static int write_nrcpus(int fd, struct perf_header *h __used,
>  static int write_event_desc(int fd, struct perf_header *h __used,
>  			    struct perf_evlist *evlist)
>  {
> -	struct perf_evsel *attr;
> +	struct perf_evsel *evsel;
>  	u32 nre = 0, nri, sz;
>  	int ret;
>  
> -	list_for_each_entry(attr, &evlist->entries, node)
> +	list_for_each_entry(evsel, &evlist->entries, node)
>  		nre++;
>  
>  	/*
> @@ -625,14 +625,14 @@ static int write_event_desc(int fd, struct perf_header *h __used,
>  	/*
>  	 * size of perf_event_attr struct
>  	 */
> -	sz = (u32)sizeof(attr->attr);
> +	sz = (u32)sizeof(evsel->attr);
>  	ret = do_write(fd, &sz, sizeof(sz));
>  	if (ret < 0)
>  		return ret;
>  
> -	list_for_each_entry(attr, &evlist->entries, node) {
> +	list_for_each_entry(evsel, &evlist->entries, node) {
>  
> -		ret = do_write(fd, &attr->attr, sz);
> +		ret = do_write(fd, &evsel->attr, sz);
>  		if (ret < 0)
>  			return ret;
>  		/*
> @@ -642,7 +642,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
>  		 * copy into an nri to be independent of the
>  		 * type of ids,
>  		 */
> -		nri = attr->ids;
> +		nri = evsel->ids;
>  		ret = do_write(fd, &nri, sizeof(nri));
>  		if (ret < 0)
>  			return ret;
> @@ -650,13 +650,13 @@ static int write_event_desc(int fd, struct perf_header *h __used,
>  		/*
>  		 * write event string as passed on cmdline
>  		 */
> -		ret = do_write_string(fd, perf_evsel__name(attr));
> +		ret = do_write_string(fd, perf_evsel__name(evsel));
>  		if (ret < 0)
>  			return ret;
>  		/*
>  		 * write unique ids for this event
>  		 */
> -		ret = do_write(fd, attr->id, attr->ids * sizeof(u64));
> +		ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
>  		if (ret < 0)
>  			return ret;
>  	}
> @@ -1683,7 +1683,7 @@ int perf_session__write_header(struct perf_session *session,
>  	struct perf_file_header f_header;
>  	struct perf_file_attr   f_attr;
>  	struct perf_header *header = &session->header;
> -	struct perf_evsel *attr, *pair = NULL;
> +	struct perf_evsel *evsel, *pair = NULL;
>  	int err;
>  
>  	lseek(fd, sizeof(f_header), SEEK_SET);
> @@ -1691,9 +1691,9 @@ int perf_session__write_header(struct perf_session *session,
>  	if (session->evlist != evlist)
>  		pair = perf_evlist__first(session->evlist);
>  
> -	list_for_each_entry(attr, &evlist->entries, node) {
> -		attr->id_offset = lseek(fd, 0, SEEK_CUR);
> -		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
> +	list_for_each_entry(evsel, &evlist->entries, node) {
> +		evsel->id_offset = lseek(fd, 0, SEEK_CUR);
> +		err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
>  		if (err < 0) {
>  out_err_write:
>  			pr_debug("failed to write perf header\n");
> @@ -1703,19 +1703,19 @@ out_err_write:
>  			err = do_write(fd, pair->id, pair->ids * sizeof(u64));
>  			if (err < 0)
>  				goto out_err_write;
> -			attr->ids += pair->ids;
> +			evsel->ids += pair->ids;
>  			pair = perf_evsel__next(pair);
>  		}
>  	}
>  
>  	header->attr_offset = lseek(fd, 0, SEEK_CUR);
>  
> -	list_for_each_entry(attr, &evlist->entries, node) {
> +	list_for_each_entry(evsel, &evlist->entries, node) {
>  		f_attr = (struct perf_file_attr){
> -			.attr = attr->attr,
> +			.attr = evsel->attr,
>  			.ids  = {
> -				.offset = attr->id_offset,
> -				.size   = attr->ids * sizeof(u64),
> +				.offset = evsel->id_offset,
> +				.size   = evsel->ids * sizeof(u64),
>  			}
>  		};
>  		err = do_write(fd, &f_attr, sizeof(f_attr));
> @@ -2277,12 +2277,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
>  				   struct perf_session *session,
>  				   perf_event__handler_t process)
>  {
> -	struct perf_evsel *attr;
> +	struct perf_evsel *evsel;
>  	int err = 0;
>  
> -	list_for_each_entry(attr, &session->evlist->entries, node) {
> -		err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
> -						  attr->id, process);
> +	list_for_each_entry(evsel, &session->evlist->entries, node) {
> +		err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
> +						  evsel->id, process);
>  		if (err) {
>  			pr_debug("failed to create perf header attribute\n");
>  			return err;
> -- 
> 1.7.8.6
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/8] perf tools: Various updates
  2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
                   ` (7 preceding siblings ...)
  2012-08-16 19:10 ` [PATCH 8/8] perf tools: Add pmu mappings to header information Robert Richter
@ 2012-08-17 16:18 ` Arnaldo Carvalho de Melo
  8 siblings, 0 replies; 24+ messages in thread
From: Arnaldo Carvalho de Melo @ 2012-08-17 16:18 UTC (permalink / raw)
  To: Robert Richter; +Cc: Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML

Em Thu, Aug 16, 2012 at 09:10:16PM +0200, Robert Richter escreveu:
> This patch set contains various perf tools updates. Most patches deal
> with event naming. If the event name is unknown it is named like the
> command line string of it. This is esp. valueable for pmu events like
> for AMD IBS:
> 
>      $ perf report | grep '^#.*event'
>      # event : name = ibs_op/cnt_ctl=1/GH, type = 7, config = 0x80000, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 0, precise_ip = 0, id = { 
>      # event : name = ibs_fetch/config=0/, type = 6, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 1, precise_ip = 0, id = { 57, 
>      # Samples: 20K of event 'ibs_op/cnt_ctl=1/GH'
>      # Samples: 4K of event 'ibs_fetch/config=0/'

There is a command for that pipe sequence:

[root@sandy ~]# perf record -e cache-misses:u,cycles:k,instructions usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.020 MB perf.data (~861 samples) ]
[root@sandy ~]# perf evlist
cache-misses:u
cycles:k
instructions
[root@sandy ~]# perf evlist -v
cache-misses:u: sample_freq=4000, config: 3, size: 96, sample_type: 327, read_format: 7, disabled: 1, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, sample_id_all: 1
cycles:k: sample_freq=4000, size: 96, sample_type: 327, read_format: 7, disabled: 1, inherit: 1, exclude_user: 1, exclude_hv: 1, freq: 1, enable_on_exec: 1, sample_id_all: 1
instructions: sample_freq=4000, config: 1, size: 96, sample_type: 327, read_format: 7, disabled: 1, inherit: 1, freq: 1, enable_on_exec: 1, sample_id_all: 1, exclude_guest: 1
[root@sandy ~]#

- Arnaldo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/8] perf tools: Catch event names from command line
  2012-08-16 19:10 ` [PATCH 5/8] perf tools: Catch event names from command line Robert Richter
@ 2012-08-20 17:42   ` Jiri Olsa
  2012-08-21 18:02     ` Robert Richter
  2012-08-21 18:03     ` [PATCH 1/2] perf test: Update event names in test cases Robert Richter
  2012-08-27 16:54   ` [tip:perf/core] perf tools: Catch event names from command line tip-bot for Robert Richter
  1 sibling, 2 replies; 24+ messages in thread
From: Jiri Olsa @ 2012-08-20 17:42 UTC (permalink / raw)
  To: Robert Richter
  Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, LKML

On Thu, Aug 16, 2012 at 09:10:21PM +0200, Robert Richter wrote:
> Use command line string provided by the -e option to name events. This
> way we get unique events names that also support pmu event syntax
> (<pmu_name>/<config>/<modifier>). No need to reconstruct the name
> anymore from its attributes. We use the event_desc of the header to
> store the name in the perf.data header. Thus it is also available for
> perf report.
> 
> Implemented by putting the parser in different states to parse events
> or configs.

I like the idea of multiple states in parser,
but parse tests fails:

[jolsa@krava perf]$ ./perf test -vvv parse
 5: parse events tests:
--- start ---
running test 0 'syscalls:sys_enter_open'
running test 1 'syscalls:*'
running test 2 'r1a'
running test 3 '1:1'
running test 4 'instructions'
running test 5 'cycles/period=100000,config2/'
running test 6 'faults'
running test 7 'L1-dcache-load-miss'
running test 8 'mem:0'
running test 9 'mem:0:x'
running test 10 'mem:0:r'
running test 11 'mem:0:w'
running test 12 'syscalls:sys_enter_open:k'
running test 13 'syscalls:*:u'
running test 14 'r1a:kp'
running test 15 '1:1:hp'
running test 16 'instructions:h'
running test 17 'faults:u'
running test 18 'L1-dcache-load-miss:kp'
running test 19 'mem:0:u'
FAILED util/parse-events-test.c:309 wrong name
---- end ----
parse events tests: FAILED!


jirka

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Fix type for evsel-> ids and add size check for ids
  2012-08-16 19:10 ` [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids Robert Richter
@ 2012-08-21 16:24   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-21 16:24 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  f4d834367cda98eee3769638da6ad687607c74e6
Gitweb:     http://git.kernel.org/tip/f4d834367cda98eee3769638da6ad687607c74e6
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:17 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 17 Aug 2012 12:38:07 -0300

perf tools: Fix type for evsel->ids and add size check for ids

Use same type for ids everywhere.

In case of writing to perf.data the size is u32. In pipe mode it is
limited to header.size (less than u16). Adding a size check here.

Size overflow due to casting shouldn't actually happen in practice, but
during development this may cause type missmatch warninngs/errors,
unifying types avoids this.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-2-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.h  |    2 +-
 tools/perf/util/header.c |   11 +++++++----
 tools/perf/util/header.h |    2 +-
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 65f39fd..94f6ba1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -53,7 +53,7 @@ struct perf_evsel {
 	u64			*id;
 	struct perf_counts	*counts;
 	int			idx;
-	int			ids;
+	u32			ids;
 	struct hists		hists;
 	char			*name;
 	struct event_format	*tp_format;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 77832b8..471b0c4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2240,7 +2240,7 @@ out_delete_evlist:
 }
 
 int perf_event__synthesize_attr(struct perf_tool *tool,
-				struct perf_event_attr *attr, u16 ids, u64 *id,
+				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process)
 {
 	union perf_event *ev;
@@ -2261,9 +2261,12 @@ int perf_event__synthesize_attr(struct perf_tool *tool,
 	memcpy(ev->attr.id, id, ids * sizeof(u64));
 
 	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
-	ev->attr.header.size = size;
+	ev->attr.header.size = (u16)size;
 
-	err = process(tool, ev, NULL, NULL);
+	if (ev->attr.header.size == size)
+		err = process(tool, ev, NULL, NULL);
+	else
+		err = -E2BIG;
 
 	free(ev);
 
@@ -2292,7 +2295,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 int perf_event__process_attr(union perf_event *event,
 			     struct perf_evlist **pevlist)
 {
-	unsigned int i, ids, n_ids;
+	u32 i, ids, n_ids;
 	struct perf_evsel *evsel;
 	struct perf_evlist *evlist = *pevlist;
 
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e..24962e7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -99,7 +99,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
 int perf_event__synthesize_attr(struct perf_tool *tool,
-				struct perf_event_attr *attr, u16 ids, u64 *id,
+				struct perf_event_attr *attr, u32 ids, u64 *id,
 				perf_event__handler_t process);
 int perf_event__synthesize_attrs(struct perf_tool *tool,
 				 struct perf_session *session,

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Report number of pmu type of unknown events
  2012-08-16 19:10 ` [PATCH 2/8] perf tools: Report number of pmu type of unknown events Robert Richter
@ 2012-08-21 16:25   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-21 16:25 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  ca1b145761e9355f90bfae1f42c9d9194702066b
Gitweb:     http://git.kernel.org/tip/ca1b145761e9355f90bfae1f42c9d9194702066b
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:18 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 17 Aug 2012 13:11:29 -0300

perf tools: Report number of pmu type of unknown events

If detection fails and an event name is unknown, report the type number.
Example perf header output:

 # Samples: 10K of event 'unknown attr type: 7'

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-3-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6c7dcc1..7ff3c8f 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -319,7 +319,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
 		break;
 
 	default:
-		scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
+		scnprintf(bf, sizeof(bf), "unknown attr type: %d",
+			  evsel->attr.type);
 		break;
 	}
 

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Rename some variables for better understanding
  2012-08-16 19:10 ` [PATCH 3/8] perf tools: Rename some variables for better understanding Robert Richter
  2012-08-17 15:34   ` Arnaldo Carvalho de Melo
@ 2012-08-21 16:26   ` tip-bot for Robert Richter
  1 sibling, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-21 16:26 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  6606f8733d7b635e09e2dc3a391a5e1f0feb218f
Gitweb:     http://git.kernel.org/tip/6606f8733d7b635e09e2dc3a391a5e1f0feb218f
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:19 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 17 Aug 2012 13:11:58 -0300

perf tools: Rename some variables for better understanding

Trivial patch to improve understanding of code.

Varible attr is usually used for struct perf_event_attr. Using it in a
different context is irritating. Thus, renaming it.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-4-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c |   42 +++++++++++++++++++++---------------------
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 471b0c4..e2e5129 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -608,11 +608,11 @@ static int write_nrcpus(int fd, struct perf_header *h __used,
 static int write_event_desc(int fd, struct perf_header *h __used,
 			    struct perf_evlist *evlist)
 {
-	struct perf_evsel *attr;
+	struct perf_evsel *evsel;
 	u32 nre = 0, nri, sz;
 	int ret;
 
-	list_for_each_entry(attr, &evlist->entries, node)
+	list_for_each_entry(evsel, &evlist->entries, node)
 		nre++;
 
 	/*
@@ -625,14 +625,14 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 	/*
 	 * size of perf_event_attr struct
 	 */
-	sz = (u32)sizeof(attr->attr);
+	sz = (u32)sizeof(evsel->attr);
 	ret = do_write(fd, &sz, sizeof(sz));
 	if (ret < 0)
 		return ret;
 
-	list_for_each_entry(attr, &evlist->entries, node) {
+	list_for_each_entry(evsel, &evlist->entries, node) {
 
-		ret = do_write(fd, &attr->attr, sz);
+		ret = do_write(fd, &evsel->attr, sz);
 		if (ret < 0)
 			return ret;
 		/*
@@ -642,7 +642,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 		 * copy into an nri to be independent of the
 		 * type of ids,
 		 */
-		nri = attr->ids;
+		nri = evsel->ids;
 		ret = do_write(fd, &nri, sizeof(nri));
 		if (ret < 0)
 			return ret;
@@ -650,13 +650,13 @@ static int write_event_desc(int fd, struct perf_header *h __used,
 		/*
 		 * write event string as passed on cmdline
 		 */
-		ret = do_write_string(fd, perf_evsel__name(attr));
+		ret = do_write_string(fd, perf_evsel__name(evsel));
 		if (ret < 0)
 			return ret;
 		/*
 		 * write unique ids for this event
 		 */
-		ret = do_write(fd, attr->id, attr->ids * sizeof(u64));
+		ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
 		if (ret < 0)
 			return ret;
 	}
@@ -1683,7 +1683,7 @@ int perf_session__write_header(struct perf_session *session,
 	struct perf_file_header f_header;
 	struct perf_file_attr   f_attr;
 	struct perf_header *header = &session->header;
-	struct perf_evsel *attr, *pair = NULL;
+	struct perf_evsel *evsel, *pair = NULL;
 	int err;
 
 	lseek(fd, sizeof(f_header), SEEK_SET);
@@ -1691,9 +1691,9 @@ int perf_session__write_header(struct perf_session *session,
 	if (session->evlist != evlist)
 		pair = perf_evlist__first(session->evlist);
 
-	list_for_each_entry(attr, &evlist->entries, node) {
-		attr->id_offset = lseek(fd, 0, SEEK_CUR);
-		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		evsel->id_offset = lseek(fd, 0, SEEK_CUR);
+		err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
 		if (err < 0) {
 out_err_write:
 			pr_debug("failed to write perf header\n");
@@ -1703,19 +1703,19 @@ out_err_write:
 			err = do_write(fd, pair->id, pair->ids * sizeof(u64));
 			if (err < 0)
 				goto out_err_write;
-			attr->ids += pair->ids;
+			evsel->ids += pair->ids;
 			pair = perf_evsel__next(pair);
 		}
 	}
 
 	header->attr_offset = lseek(fd, 0, SEEK_CUR);
 
-	list_for_each_entry(attr, &evlist->entries, node) {
+	list_for_each_entry(evsel, &evlist->entries, node) {
 		f_attr = (struct perf_file_attr){
-			.attr = attr->attr,
+			.attr = evsel->attr,
 			.ids  = {
-				.offset = attr->id_offset,
-				.size   = attr->ids * sizeof(u64),
+				.offset = evsel->id_offset,
+				.size   = evsel->ids * sizeof(u64),
 			}
 		};
 		err = do_write(fd, &f_attr, sizeof(f_attr));
@@ -2277,12 +2277,12 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
 				   struct perf_session *session,
 				   perf_event__handler_t process)
 {
-	struct perf_evsel *attr;
+	struct perf_evsel *evsel;
 	int err = 0;
 
-	list_for_each_entry(attr, &session->evlist->entries, node) {
-		err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
-						  attr->id, process);
+	list_for_each_entry(evsel, &session->evlist->entries, node) {
+		err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
+						  evsel->id, process);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
 			return err;

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Rename global variable 'events' in util/header.c
  2012-08-16 19:10 ` [PATCH 4/8] perf tools: Rename global variable 'events' in util/header.c Robert Richter
@ 2012-08-21 16:27   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-21 16:27 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  db146f06ac0bbea63271b6c78f4341ee46843e10
Gitweb:     http://git.kernel.org/tip/db146f06ac0bbea63271b6c78f4341ee46843e10
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:20 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 17 Aug 2012 13:13:08 -0300

perf tools: Rename global variable 'events' in util/header.c

Trivial patch that renames global variable 'events' in util/header.c.

Use a more specific naming to avoid conflicts. Same for variable
'event_count'.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-5-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c |   40 ++++++++++++++++++++--------------------
 1 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e2e5129..1e5b6aa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -23,8 +23,8 @@
 
 static bool no_buildid_cache = false;
 
-static int event_count;
-static struct perf_trace_event_type *events;
+static int trace_event_count;
+static struct perf_trace_event_type *trace_events;
 
 static u32 header_argc;
 static const char **header_argv;
@@ -36,24 +36,24 @@ int perf_header__push_event(u64 id, const char *name)
 	if (strlen(name) > MAX_EVENT_NAME)
 		pr_warning("Event %s will be truncated\n", name);
 
-	nevents = realloc(events, (event_count + 1) * sizeof(*events));
+	nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events));
 	if (nevents == NULL)
 		return -ENOMEM;
-	events = nevents;
+	trace_events = nevents;
 
-	memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
-	events[event_count].event_id = id;
-	strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
-	event_count++;
+	memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type));
+	trace_events[trace_event_count].event_id = id;
+	strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1);
+	trace_event_count++;
 	return 0;
 }
 
 char *perf_header__find_event(u64 id)
 {
 	int i;
-	for (i = 0 ; i < event_count; i++) {
-		if (events[i].event_id == id)
-			return events[i].name;
+	for (i = 0 ; i < trace_event_count; i++) {
+		if (trace_events[i].event_id == id)
+			return trace_events[i].name;
 	}
 	return NULL;
 }
@@ -1726,9 +1726,9 @@ out_err_write:
 	}
 
 	header->event_offset = lseek(fd, 0, SEEK_CUR);
-	header->event_size = event_count * sizeof(struct perf_trace_event_type);
-	if (events) {
-		err = do_write(fd, events, header->event_size);
+	header->event_size = trace_event_count * sizeof(struct perf_trace_event_type);
+	if (trace_events) {
+		err = do_write(fd, trace_events, header->event_size);
 		if (err < 0) {
 			pr_debug("failed to write perf header events\n");
 			return err;
@@ -2211,13 +2211,13 @@ int perf_session__read_header(struct perf_session *session, int fd)
 
 	if (f_header.event_types.size) {
 		lseek(fd, f_header.event_types.offset, SEEK_SET);
-		events = malloc(f_header.event_types.size);
-		if (events == NULL)
+		trace_events = malloc(f_header.event_types.size);
+		if (trace_events == NULL)
 			return -ENOMEM;
-		if (perf_header__getbuffer64(header, fd, events,
+		if (perf_header__getbuffer64(header, fd, trace_events,
 					     f_header.event_types.size))
 			goto out_errno;
-		event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
+		trace_event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
 	}
 
 	perf_header__process_sections(header, fd, &session->pevent,
@@ -2362,8 +2362,8 @@ int perf_event__synthesize_event_types(struct perf_tool *tool,
 	struct perf_trace_event_type *type;
 	int i, err = 0;
 
-	for (i = 0; i < event_count; i++) {
-		type = &events[i];
+	for (i = 0; i < trace_event_count; i++) {
+		type = &trace_events[i];
 
 		err = perf_event__synthesize_event_type(tool, type->event_id,
 							type->name, process,

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/8] perf tools: Catch event names from command line
  2012-08-20 17:42   ` Jiri Olsa
@ 2012-08-21 18:02     ` Robert Richter
  2012-08-21 18:03     ` [PATCH 1/2] perf test: Update event names in test cases Robert Richter
  1 sibling, 0 replies; 24+ messages in thread
From: Robert Richter @ 2012-08-21 18:02 UTC (permalink / raw)
  To: Jiri Olsa; +Cc: Arnaldo Carvalho de Melo, Ingo Molnar, Peter Zijlstra, LKML

On 20.08.12 19:42:47, Jiri Olsa wrote:
> I like the idea of multiple states in parser,
> but parse tests fails:
> 
> [jolsa@krava perf]$ ./perf test -vvv parse
>  5: parse events tests:
> --- start ---
> running test 0 'syscalls:sys_enter_open'
> running test 1 'syscalls:*'
> running test 2 'r1a'
> running test 3 '1:1'
> running test 4 'instructions'
> running test 5 'cycles/period=100000,config2/'
> running test 6 'faults'
> running test 7 'L1-dcache-load-miss'
> running test 8 'mem:0'
> running test 9 'mem:0:x'
> running test 10 'mem:0:r'
> running test 11 'mem:0:w'
> running test 12 'syscalls:sys_enter_open:k'
> running test 13 'syscalls:*:u'
> running test 14 'r1a:kp'
> running test 15 '1:1:hp'
> running test 16 'instructions:h'
> running test 17 'faults:u'
> running test 18 'L1-dcache-load-miss:kp'
> running test 19 'mem:0:u'
> FAILED util/parse-events-test.c:309 wrong name
> ---- end ----
> parse events tests: FAILED!

Right, I need to updated the test cases. Have patches ready for this.

-Robert

-- 
Advanced Micro Devices, Inc.
Operating System Research Center


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/2] perf test: Update event names in test cases
  2012-08-20 17:42   ` Jiri Olsa
  2012-08-21 18:02     ` Robert Richter
@ 2012-08-21 18:03     ` Robert Richter
  2012-08-21 18:03       ` [PATCH 2/2] perf test: Do not abort tests on error Robert Richter
  1 sibling, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-21 18:03 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: Ingo Molnar, Peter Zijlstra, LKML, Robert Richter

Event names are now generated from the command line specification.
Update event names in test cases accordingly.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/parse-events-test.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index bf055ce..74be1bf 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -301,12 +301,13 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
 {
 	struct perf_evsel *evsel = perf_evlist__first(evlist);
 
+
 	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:u"));
 
 	return test__checkevent_breakpoint(evlist);
 }
@@ -320,7 +321,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:x:k"));
 
 	return test__checkevent_breakpoint_x(evlist);
 }
@@ -334,7 +335,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:r:hp"));
 
 	return test__checkevent_breakpoint_r(evlist);
 }
@@ -348,7 +349,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:w:up"));
 
 	return test__checkevent_breakpoint_w(evlist);
 }
@@ -362,7 +363,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:rw:kp"));
 
 	return test__checkevent_breakpoint_rw(evlist);
 }
@@ -437,7 +438,7 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
 	TEST_ASSERT_VAL("wrong config",  2 == evsel->attr.config);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
+			!strcmp(perf_evsel__name(evsel), "cpu/config=2/u"));
 
 	return 0;
 }
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/2] perf test: Do not abort tests on error
  2012-08-21 18:03     ` [PATCH 1/2] perf test: Update event names in test cases Robert Richter
@ 2012-08-21 18:03       ` Robert Richter
  2012-08-27 16:53         ` [tip:perf/core] " tip-bot for Robert Richter
  0 siblings, 1 reply; 24+ messages in thread
From: Robert Richter @ 2012-08-21 18:03 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: Ingo Molnar, Peter Zijlstra, LKML, Robert Richter

Run through all tests regardless of failures. On errors, return the
first error code detected.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 tools/perf/util/parse-events-test.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 74be1bf..bc8b651 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -949,19 +949,19 @@ static int test_event(struct test__event_st *e)
 
 static int test_events(struct test__event_st *events, unsigned cnt)
 {
-	int ret = 0;
+	int ret1, ret2 = 0;
 	unsigned i;
 
 	for (i = 0; i < cnt; i++) {
 		struct test__event_st *e = &events[i];
 
 		pr_debug("running test %d '%s'\n", i, e->name);
-		ret = test_event(e);
-		if (ret)
-			break;
+		ret1 = test_event(e);
+		if (ret1)
+			ret2 = ret1;
 	}
 
-	return ret;
+	return ret2;
 }
 
 static int test_term(struct test__term *t)
@@ -1022,13 +1022,13 @@ static int test_pmu(void)
 
 int parse_events__test(void)
 {
-	int ret;
+	int ret1, ret2 = 0;
 
 #define TEST_EVENTS(tests)				\
 do {							\
-	ret = test_events(tests, ARRAY_SIZE(tests));	\
-	if (ret)					\
-		return ret;				\
+	ret1 = test_events(tests, ARRAY_SIZE(tests));	\
+	if (!ret2)					\
+		ret2 = ret1;				\
 } while (0)
 
 	TEST_EVENTS(test__events);
@@ -1036,5 +1036,9 @@ do {							\
 	if (test_pmu())
 		TEST_EVENTS(test__events_pmu);
 
-	return test_terms(test__terms, ARRAY_SIZE(test__terms));
+	ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
+	if (!ret2)
+		ret2 = ret1;
+
+	return ret2;
 }
-- 
1.7.8.6



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf test: Do not abort tests on error
  2012-08-21 18:03       ` [PATCH 2/2] perf test: Do not abort tests on error Robert Richter
@ 2012-08-27 16:53         ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-27 16:53 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  9bfbbc6d1e6b4d055860231e232b807911bf8325
Gitweb:     http://git.kernel.org/tip/9bfbbc6d1e6b4d055860231e232b807911bf8325
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Tue, 21 Aug 2012 20:03:15 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 22 Aug 2012 13:34:23 -0300

perf test: Do not abort tests on error

Run through all tests regardless of failures. On errors, return the
first error code detected.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345572195-23857-2-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/parse-events-test.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index bf055ce..392308c 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -948,19 +948,19 @@ static int test_event(struct test__event_st *e)
 
 static int test_events(struct test__event_st *events, unsigned cnt)
 {
-	int ret = 0;
+	int ret1, ret2 = 0;
 	unsigned i;
 
 	for (i = 0; i < cnt; i++) {
 		struct test__event_st *e = &events[i];
 
 		pr_debug("running test %d '%s'\n", i, e->name);
-		ret = test_event(e);
-		if (ret)
-			break;
+		ret1 = test_event(e);
+		if (ret1)
+			ret2 = ret1;
 	}
 
-	return ret;
+	return ret2;
 }
 
 static int test_term(struct test__term *t)
@@ -1021,13 +1021,13 @@ static int test_pmu(void)
 
 int parse_events__test(void)
 {
-	int ret;
+	int ret1, ret2 = 0;
 
 #define TEST_EVENTS(tests)				\
 do {							\
-	ret = test_events(tests, ARRAY_SIZE(tests));	\
-	if (ret)					\
-		return ret;				\
+	ret1 = test_events(tests, ARRAY_SIZE(tests));	\
+	if (!ret2)					\
+		ret2 = ret1;				\
 } while (0)
 
 	TEST_EVENTS(test__events);
@@ -1035,5 +1035,9 @@ do {							\
 	if (test_pmu())
 		TEST_EVENTS(test__events_pmu);
 
-	return test_terms(test__terms, ARRAY_SIZE(test__terms));
+	ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
+	if (!ret2)
+		ret2 = ret1;
+
+	return ret2;
 }

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Catch event names from command line
  2012-08-16 19:10 ` [PATCH 5/8] perf tools: Catch event names from command line Robert Richter
  2012-08-20 17:42   ` Jiri Olsa
@ 2012-08-27 16:54   ` tip-bot for Robert Richter
  1 sibling, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-27 16:54 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  ac2ba9f36bb400755e411309f3e76dbf308a10e7
Gitweb:     http://git.kernel.org/tip/ac2ba9f36bb400755e411309f3e76dbf308a10e7
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:21 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 22 Aug 2012 13:40:49 -0300

perf tools: Catch event names from command line

Use command line string provided by the -e option to name events. This
way we get unique events names that also support pmu event syntax
(<pmu_name>/<config>/<modifier>). No need to reconstruct the name
anymore from its attributes. We use the event_desc of the header to
store the name in the perf.data header. Thus it is also available for
perf report.

Implemented by putting the parser in different states to parse events or
configs.

And since event names are now generated from the command line
specification.  Update event names in test cases accordingly.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-6-git-send-email-robert.richter@amd.com
[ committer note: Folded patch fixing 'perf test' failure reported by Jiri Olsa ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/parse-events-test.c |   13 +++++----
 tools/perf/util/parse-events.c      |   12 ++++++++
 tools/perf/util/parse-events.h      |    1 +
 tools/perf/util/parse-events.l      |   50 ++++++++++++++++++++++++++++-------
 tools/perf/util/parse-events.y      |   20 ++++++++++++-
 5 files changed, 78 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 392308c..bc8b651 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -301,12 +301,13 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
 {
 	struct perf_evsel *evsel = perf_evlist__first(evlist);
 
+
 	TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
 	TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:u"));
 
 	return test__checkevent_breakpoint(evlist);
 }
@@ -320,7 +321,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:x:k"));
 
 	return test__checkevent_breakpoint_x(evlist);
 }
@@ -334,7 +335,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:r:hp"));
 
 	return test__checkevent_breakpoint_r(evlist);
 }
@@ -348,7 +349,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:w:up"));
 
 	return test__checkevent_breakpoint_w(evlist);
 }
@@ -362,7 +363,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
 	TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
+			!strcmp(perf_evsel__name(evsel), "mem:0:rw:kp"));
 
 	return test__checkevent_breakpoint_rw(evlist);
 }
@@ -437,7 +438,7 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
 	TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
 	TEST_ASSERT_VAL("wrong config",  2 == evsel->attr.config);
 	TEST_ASSERT_VAL("wrong name",
-			!strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
+			!strcmp(perf_evsel__name(evsel), "cpu/config=2/u"));
 
 	return 0;
 }
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 925784a..b246303 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -751,6 +751,18 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	return 0;
 }
 
+int parse_events_name(struct list_head *list, char *name)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, list, node) {
+		if (!evsel->name)
+			evsel->name = strdup(name);
+	}
+
+	return 0;
+}
+
 static int parse_events__scanner(const char *str, void *data, int start_token)
 {
 	YY_BUFFER_STATE buffer;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 0b9782d..c356e44 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -81,6 +81,7 @@ int parse_events__term_clone(struct parse_events__term **new,
 void parse_events__free_terms(struct list_head *terms);
 int parse_events__modifier_event(struct list_head *list, char *str, bool add);
 int parse_events__modifier_group(struct list_head *list, char *event_mod);
+int parse_events_name(struct list_head *list, char *name);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
 				char *sys, char *event);
 int parse_events_add_numeric(struct list_head **list, int *idx,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 2c0d006..f5e28dc 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -70,6 +70,12 @@ static int term(yyscan_t scanner, int type)
 %}
 
 %x mem
+%s config
+%x event
+
+group		[^,{}/]*[{][^}]*[}][^,{}/]*
+event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
+event		[^,{}/]+
 
 num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
@@ -84,7 +90,13 @@ modifier_bp	[rwx]{1,3}
 	{
 		int start_token;
 
-		start_token = (int) parse_events_get_extra(yyscanner);
+		start_token = parse_events_get_extra(yyscanner);
+
+		if (start_token == PE_START_TERMS)
+			BEGIN(config);
+		else if (start_token == PE_START_EVENTS)
+			BEGIN(event);
+
 		if (start_token) {
 			parse_events_set_extra(NULL, yyscanner);
 			return start_token;
@@ -92,6 +104,26 @@ modifier_bp	[rwx]{1,3}
          }
 %}
 
+<event>{
+
+{group}		{
+			BEGIN(INITIAL); yyless(0);
+		}
+
+{event_pmu}	|
+{event}		{
+			str(yyscanner, PE_EVENT_NAME);
+			BEGIN(INITIAL); yyless(0);
+			return PE_EVENT_NAME;
+		}
+
+.		|
+<<EOF>>		{
+			BEGIN(INITIAL); yyless(0);
+		}
+
+}
+
 cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
 stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
 stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -127,18 +159,16 @@ speculative-read|speculative-load	|
 refs|Reference|ops|access		|
 misses|miss				{ return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
 
-	/*
-	 * These are event config hardcoded term names to be specified
-	 * within xxx/.../ syntax. So far we dont clash with other names,
-	 * so we can put them here directly. In case the we have a conflict
-	 * in future, this needs to go into '//' condition block.
-	 */
+<config>{
 config			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
 config1			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
 config2			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
 name			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
 period			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
 branch_type		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+,			{ return ','; }
+"/"			{ BEGIN(INITIAL); return '/'; }
+}
 
 mem:			{ BEGIN(mem); return PE_PREFIX_MEM; }
 r{num_raw_hex}		{ return raw(yyscanner); }
@@ -147,11 +177,11 @@ r{num_raw_hex}		{ return raw(yyscanner); }
 
 {modifier_event}	{ return str(yyscanner, PE_MODIFIER_EVENT); }
 {name}			{ return str(yyscanner, PE_NAME); }
-"/"			{ return '/'; }
+"/"			{ BEGIN(config); return '/'; }
 -			{ return '-'; }
-,			{ return ','; }
+,			{ BEGIN(event); return ','; }
 :			{ return ':'; }
-"{"			{ return '{'; }
+"{"			{ BEGIN(event); return '{'; }
 "}"			{ return '}'; }
 =			{ return '='; }
 \n			{ }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 66850f8..42d9a17 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -27,6 +27,7 @@ do { \
 
 %token PE_START_EVENTS PE_START_TERMS
 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
+%token PE_EVENT_NAME
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
@@ -42,6 +43,7 @@ do { \
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
 %type <str> PE_MODIFIER_BP
+%type <str> PE_EVENT_NAME
 %type <num> value_sym
 %type <head> event_config
 %type <term> event_term
@@ -53,6 +55,8 @@ do { \
 %type <head> event_legacy_numeric
 %type <head> event_legacy_raw
 %type <head> event_def
+%type <head> event_mod
+%type <head> event_name
 %type <head> event
 %type <head> events
 %type <head> group_def
@@ -143,8 +147,10 @@ events ',' event
 |
 event
 
-event:
-event_def PE_MODIFIER_EVENT
+event: event_mod
+
+event_mod:
+event_name PE_MODIFIER_EVENT
 {
 	struct list_head *list = $1;
 
@@ -157,6 +163,16 @@ event_def PE_MODIFIER_EVENT
 	$$ = list;
 }
 |
+event_name
+
+event_name:
+PE_EVENT_NAME event_def
+{
+	ABORT_ON(parse_events_name($2, $1));
+	free($1);
+	$$ = $2;
+}
+|
 event_def
 
 event_def: event_pmu |

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Refactor print_event_desc()
  2012-08-16 19:10 ` [PATCH 6/8] perf tools: Refactor print_event_desc() Robert Richter
@ 2012-08-27 16:55   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-27 16:55 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  4e1b9c679fcb208275b55eb8fc46c2d58ef6a2ee
Gitweb:     http://git.kernel.org/tip/4e1b9c679fcb208275b55eb8fc46c2d58ef6a2ee
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:22 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 22 Aug 2012 13:45:59 -0300

perf tools: Refactor print_event_desc()

For later use we need a function read_event_desc() for processing the
event_desc feature. Split it from print_event_desc().

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-7-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c |  134 ++++++++++++++++++++++++++++++++--------------
 1 files changed, 93 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1e5b6aa..7454cf4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1148,12 +1148,29 @@ static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp)
 	}
 }
 
-static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
+static void free_event_desc(struct perf_evsel *events)
 {
-	struct perf_event_attr attr;
-	uint64_t id;
+	struct perf_evsel *evsel;
+
+	if (!events)
+		return;
+
+	for (evsel = events; evsel->attr.size; evsel++) {
+		if (evsel->name)
+			free(evsel->name);
+		if (evsel->id)
+			free(evsel->id);
+	}
+
+	free(events);
+}
+
+static struct perf_evsel *
+read_event_desc(struct perf_header *ph, int fd)
+{
+	struct perf_evsel *evsel, *events = NULL;
+	u64 *id;
 	void *buf = NULL;
-	char *str;
 	u32 nre, sz, nr, i, j;
 	ssize_t ret;
 	size_t msz;
@@ -1173,18 +1190,22 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 	if (ph->needs_swap)
 		sz = bswap_32(sz);
 
-	memset(&attr, 0, sizeof(attr));
-
 	/* buffer to hold on file attr struct */
 	buf = malloc(sz);
 	if (!buf)
 		goto error;
 
-	msz = sizeof(attr);
+	/* the last event terminates with evsel->attr.size == 0: */
+	events = calloc(nre + 1, sizeof(*events));
+	if (!events)
+		goto error;
+
+	msz = sizeof(evsel->attr);
 	if (sz < msz)
 		msz = sz;
 
-	for (i = 0 ; i < nre; i++) {
+	for (i = 0, evsel = events; i < nre; evsel++, i++) {
+		evsel->idx = i;
 
 		/*
 		 * must read entire on-file attr struct to
@@ -1197,7 +1218,7 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 		if (ph->needs_swap)
 			perf_event__attr_swap(buf);
 
-		memcpy(&attr, buf, msz);
+		memcpy(&evsel->attr, buf, msz);
 
 		ret = read(fd, &nr, sizeof(nr));
 		if (ret != (ssize_t)sizeof(nr))
@@ -1206,51 +1227,82 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
 		if (ph->needs_swap)
 			nr = bswap_32(nr);
 
-		str = do_read_string(fd, ph);
-		fprintf(fp, "# event : name = %s, ", str);
-		free(str);
+		evsel->name = do_read_string(fd, ph);
+
+		if (!nr)
+			continue;
+
+		id = calloc(nr, sizeof(*id));
+		if (!id)
+			goto error;
+		evsel->ids = nr;
+		evsel->id = id;
+
+		for (j = 0 ; j < nr; j++) {
+			ret = read(fd, id, sizeof(*id));
+			if (ret != (ssize_t)sizeof(*id))
+				goto error;
+			if (ph->needs_swap)
+				*id = bswap_64(*id);
+			id++;
+		}
+	}
+out:
+	if (buf)
+		free(buf);
+	return events;
+error:
+	if (events)
+		free_event_desc(events);
+	events = NULL;
+	goto out;
+}
+
+static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
+{
+	struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
+	u32 j;
+	u64 *id;
+
+	if (!events) {
+		fprintf(fp, "# event desc: not available or unable to read\n");
+		return;
+	}
+
+	for (evsel = events; evsel->attr.size; evsel++) {
+		fprintf(fp, "# event : name = %s, ", evsel->name);
 
 		fprintf(fp, "type = %d, config = 0x%"PRIx64
 			    ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
-				attr.type,
-				(u64)attr.config,
-				(u64)attr.config1,
-				(u64)attr.config2);
+				evsel->attr.type,
+				(u64)evsel->attr.config,
+				(u64)evsel->attr.config1,
+				(u64)evsel->attr.config2);
 
 		fprintf(fp, ", excl_usr = %d, excl_kern = %d",
-				attr.exclude_user,
-				attr.exclude_kernel);
+				evsel->attr.exclude_user,
+				evsel->attr.exclude_kernel);
 
 		fprintf(fp, ", excl_host = %d, excl_guest = %d",
-				attr.exclude_host,
-				attr.exclude_guest);
+				evsel->attr.exclude_host,
+				evsel->attr.exclude_guest);
 
-		fprintf(fp, ", precise_ip = %d", attr.precise_ip);
+		fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
 
-		if (nr)
+		if (evsel->ids) {
 			fprintf(fp, ", id = {");
-
-		for (j = 0 ; j < nr; j++) {
-			ret = read(fd, &id, sizeof(id));
-			if (ret != (ssize_t)sizeof(id))
-				goto error;
-
-			if (ph->needs_swap)
-				id = bswap_64(id);
-
-			if (j)
-				fputc(',', fp);
-
-			fprintf(fp, " %"PRIu64, id);
-		}
-		if (nr && j == nr)
+			for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
+				if (j)
+					fputc(',', fp);
+				fprintf(fp, " %"PRIu64, *id);
+			}
 			fprintf(fp, " }");
+		}
+
 		fputc('\n', fp);
 	}
-	free(buf);
-	return;
-error:
-	fprintf(fp, "# event desc: not available or unable to read\n");
+
+	free_event_desc(events);
 }
 
 static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp)

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf report: Update event names from header description
  2012-08-16 19:10 ` [PATCH 7/8] perf report: Update event names from header description Robert Richter
@ 2012-08-27 16:56   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-27 16:56 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  7c2f7afd36cc111dd08eb8eb8ef74fb6564fd131
Gitweb:     http://git.kernel.org/tip/7c2f7afd36cc111dd08eb8eb8ef74fb6564fd131
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:23 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 22 Aug 2012 13:47:17 -0300

perf report: Update event names from header description

Name events based on the event description in the perf.data header.

Example output:

 $ perf report | grep '^#.*event'
 # event : name = ibs_op/cnt_ctl=1/GH, type = 7, config = 0x80000, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 0, precise_ip = 0, id = { 49, 50, 51, 52, 53, 54, 55, 56 }
 # event : name = ibs_fetch/config=0/, type = 6, config = 0x0, config1 = 0x0, config2 = 0x0, excl_usr = 0, excl_kern = 0, excl_host = 0, excl_guest = 1, precise_ip = 0, id = { 57, 58, 59, 60, 61, 62, 63, 64 }
 # Samples: 20K of event 'ibs_op/cnt_ctl=1/GH'
 # Samples: 4K of event 'ibs_fetch/config=0/'

Note the new pmu event syntax of the names.

Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-8-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c |   52 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7454cf4..69374de 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1556,6 +1556,56 @@ static int process_build_id(struct perf_file_section *section,
 	return 0;
 }
 
+static struct perf_evsel *
+perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
+{
+	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if (evsel->idx == idx)
+			return evsel;
+	}
+
+	return NULL;
+}
+
+static void
+perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event)
+{
+	struct perf_evsel *evsel;
+
+	if (!event->name)
+		return;
+
+	evsel = perf_evlist__find_by_index(evlist, event->idx);
+	if (!evsel)
+		return;
+
+	if (evsel->name)
+		return;
+
+	evsel->name = strdup(event->name);
+}
+
+static int
+process_event_desc(struct perf_file_section *section __unused,
+		   struct perf_header *header, int feat __unused, int fd,
+		   void *data __used)
+{
+	struct perf_session *session = container_of(header, struct perf_session, header);
+	struct perf_evsel *evsel, *events = read_event_desc(header, fd);
+
+	if (!events)
+		return 0;
+
+	for (evsel = events; evsel->attr.size; evsel++)
+		perf_evlist__set_event_name(session->evlist, evsel);
+
+	free_event_desc(events);
+
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
 	void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1589,7 +1639,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPA(HEADER_CPUDESC,	cpudesc),
 	FEAT_OPA(HEADER_CPUID,		cpuid),
 	FEAT_OPA(HEADER_TOTAL_MEM,	total_mem),
-	FEAT_OPA(HEADER_EVENT_DESC,	event_desc),
+	FEAT_OPP(HEADER_EVENT_DESC,	event_desc),
 	FEAT_OPA(HEADER_CMDLINE,	cmdline),
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [tip:perf/core] perf tools: Add pmu mappings to header information
  2012-08-16 19:10 ` [PATCH 8/8] perf tools: Add pmu mappings to header information Robert Richter
@ 2012-08-27 16:57   ` tip-bot for Robert Richter
  0 siblings, 0 replies; 24+ messages in thread
From: tip-bot for Robert Richter @ 2012-08-27 16:57 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, hpa, mingo, peterz, jolsa, robert.richter, tglx

Commit-ID:  50a9667c9383982d7ec4e6bbc707f67be0e163d2
Gitweb:     http://git.kernel.org/tip/50a9667c9383982d7ec4e6bbc707f67be0e163d2
Author:     Robert Richter <robert.richter@amd.com>
AuthorDate: Thu, 16 Aug 2012 21:10:24 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 22 Aug 2012 15:22:55 -0300

perf tools: Add pmu mappings to header information

With dynamic pmu allocation there are also dynamically assigned pmu ids.
These ids are used in event->attr.type to describe the pmu to be used
for that event. The information is available in sysfs, e.g:

 /sys/bus/event_source/devices/breakpoint/type: 5
 /sys/bus/event_source/devices/cpu/type: 4
 /sys/bus/event_source/devices/ibs_fetch/type: 6
 /sys/bus/event_source/devices/ibs_op/type: 7
 /sys/bus/event_source/devices/software/type: 1
 /sys/bus/event_source/devices/tracepoint/type: 2

These mappings are needed to know which samples belong to which pmu.  If
a pmu is added dynamically like for ibs_fetch or ibs_op the type value
may vary.

Now, when decoding samples from perf.data this information in sysfs
might be no longer available or may have changed. We need to store it in
perf.data. Using the header for this. Now the header information created
with perf report contains an additional section looking like this:

 # pmu mappings: ibs_op = 7, ibs_fetch = 6, cpu = 4, breakpoint = 5, tracepoint = 2, software = 1

Signed-off-by: Robert Richter <robert.richter@amd.com>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1345144224-27280-9-git-send-email-robert.richter@amd.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/header.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h |    1 +
 tools/perf/util/pmu.c    |   50 ++++++++++++++++++++++++++++-
 tools/perf/util/pmu.h    |    2 +
 4 files changed, 129 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 69374de..63aad31 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -20,6 +20,7 @@
 #include "symbol.h"
 #include "debug.h"
 #include "cpumap.h"
+#include "pmu.h"
 
 static bool no_buildid_cache = false;
 
@@ -1004,6 +1005,45 @@ done:
 }
 
 /*
+ * File format:
+ *
+ * struct pmu_mappings {
+ *	u32	pmu_num;
+ *	struct pmu_map {
+ *		u32	type;
+ *		char	name[];
+ *	}[pmu_num];
+ * };
+ */
+
+static int write_pmu_mappings(int fd, struct perf_header *h __used,
+			      struct perf_evlist *evlist __used)
+{
+	struct perf_pmu *pmu = NULL;
+	off_t offset = lseek(fd, 0, SEEK_CUR);
+	__u32 pmu_num = 0;
+
+	/* write real pmu_num later */
+	do_write(fd, &pmu_num, sizeof(pmu_num));
+
+	while ((pmu = perf_pmu__scan(pmu))) {
+		if (!pmu->name)
+			continue;
+		pmu_num++;
+		do_write(fd, &pmu->type, sizeof(pmu->type));
+		do_write_string(fd, pmu->name);
+	}
+
+	if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
+		/* discard all */
+		lseek(fd, offset, SEEK_SET);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
  * default get_cpuid(): nothing gets recorded
  * actual implementation must be in arch/$(ARCH)/util/header.c
  */
@@ -1389,6 +1429,43 @@ static void print_branch_stack(struct perf_header *ph __used, int fd __used,
 	fprintf(fp, "# contains samples with branch stack\n");
 }
 
+static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
+{
+	const char *delimiter = "# pmu mappings: ";
+	char *name;
+	int ret;
+	u32 pmu_num;
+	u32 type;
+
+	ret = read(fd, &pmu_num, sizeof(pmu_num));
+	if (ret != sizeof(pmu_num))
+		goto error;
+
+	if (!pmu_num) {
+		fprintf(fp, "# pmu mappings: not available\n");
+		return;
+	}
+
+	while (pmu_num) {
+		if (read(fd, &type, sizeof(type)) != sizeof(type))
+			break;
+		name = do_read_string(fd, ph);
+		if (!name)
+			break;
+		pmu_num--;
+		fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type);
+		free(name);
+		delimiter = ", ";
+	}
+
+	fprintf(fp, "\n");
+
+	if (!pmu_num)
+		return;
+error:
+	fprintf(fp, "# pmu mappings: unable to read\n");
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
 				    char *filename,
 				    struct perf_session *session)
@@ -1644,6 +1721,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
 	FEAT_OPA(HEADER_BRANCH_STACK,	branch_stack),
+	FEAT_OPA(HEADER_PMU_MAPPINGS,	pmu_mappings),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 24962e7..9d5eedc 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -28,6 +28,7 @@ enum {
 	HEADER_CPU_TOPOLOGY,
 	HEADER_NUMA_TOPOLOGY,
 	HEADER_BRANCH_STACK,
+	HEADER_PMU_MAPPINGS,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a4..6631d82 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -10,6 +10,8 @@
 #include "pmu.h"
 #include "parse-events.h"
 
+#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
+
 int perf_pmu_parse(struct list_head *list, char *name);
 extern FILE *perf_pmu_in;
 
@@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format)
 		return -1;
 
 	snprintf(path, PATH_MAX,
-		 "%s/bus/event_source/devices/%s/format", sysfs, name);
+		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
 
 	if (stat(path, &st) < 0)
 		return 0;	/* no error if format does not exist */
@@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type)
 		return -1;
 
 	snprintf(path, PATH_MAX,
-		 "%s/bus/event_source/devices/%s/type", sysfs, name);
+		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
 
 	if (stat(path, &st) < 0)
 		return -1;
@@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type)
 	return ret;
 }
 
+/* Add all pmus in sysfs to pmu list: */
+static void pmu_read_sysfs(void)
+{
+	char path[PATH_MAX];
+	const char *sysfs;
+	DIR *dir;
+	struct dirent *dent;
+
+	sysfs = sysfs_find_mountpoint();
+	if (!sysfs)
+		return;
+
+	snprintf(path, PATH_MAX,
+		 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
+
+	dir = opendir(path);
+	if (!dir)
+		return;
+
+	while ((dent = readdir(dir))) {
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+		/* add to static LIST_HEAD(pmus): */
+		perf_pmu__find(dent->d_name);
+	}
+
+	closedir(dir);
+}
+
 static struct perf_pmu *pmu_lookup(char *name)
 {
 	struct perf_pmu *pmu;
@@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name)
 	return NULL;
 }
 
+struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
+{
+	/*
+	 * pmu iterator: If pmu is NULL, we start at the begin,
+	 * otherwise return the next pmu. Returns NULL on end.
+	 */
+	if (!pmu) {
+		pmu_read_sysfs();
+		pmu = list_prepare_entry(pmu, &pmus, list);
+	}
+	list_for_each_entry_continue(pmu, &pmus, list)
+		return pmu;
+	return NULL;
+}
+
 struct perf_pmu *perf_pmu__find(char *name)
 {
 	struct perf_pmu *pmu;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 535f2c5..47f68d3 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -46,5 +46,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
 			 int config, unsigned long *bits);
 void perf_pmu__set_format(unsigned long *bits, long from, long to);
 
+struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
+
 int perf_pmu__test(void);
 #endif /* __PMU_H */

^ permalink raw reply related	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2012-08-27 16:57 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-16 19:10 [PATCH 0/8] perf tools: Various updates Robert Richter
2012-08-16 19:10 ` [PATCH 1/8] perf tools: Fix type for evsel->ids and add size check for ids Robert Richter
2012-08-21 16:24   ` [tip:perf/core] perf tools: Fix type for evsel-> ids " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 2/8] perf tools: Report number of pmu type of unknown events Robert Richter
2012-08-21 16:25   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 3/8] perf tools: Rename some variables for better understanding Robert Richter
2012-08-17 15:34   ` Arnaldo Carvalho de Melo
2012-08-21 16:26   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 4/8] perf tools: Rename global variable 'events' in util/header.c Robert Richter
2012-08-21 16:27   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 5/8] perf tools: Catch event names from command line Robert Richter
2012-08-20 17:42   ` Jiri Olsa
2012-08-21 18:02     ` Robert Richter
2012-08-21 18:03     ` [PATCH 1/2] perf test: Update event names in test cases Robert Richter
2012-08-21 18:03       ` [PATCH 2/2] perf test: Do not abort tests on error Robert Richter
2012-08-27 16:53         ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-27 16:54   ` [tip:perf/core] perf tools: Catch event names from command line tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 6/8] perf tools: Refactor print_event_desc() Robert Richter
2012-08-27 16:55   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 7/8] perf report: Update event names from header description Robert Richter
2012-08-27 16:56   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-16 19:10 ` [PATCH 8/8] perf tools: Add pmu mappings to header information Robert Richter
2012-08-27 16:57   ` [tip:perf/core] " tip-bot for Robert Richter
2012-08-17 16:18 ` [PATCH 0/8] perf tools: Various updates Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).