[PATCH V13 07/12] perf tools: add support for PERF_SAMPLE_IDENTFIER

2013-08-27 Thread Adrian Hunter
Enable parsing of samples with sample format bit
PERF_SAMPLE_IDENTFIER.  In addition, if the kernel supports
it, prefer it to selecting PERF_SAMPLE_ID thereby allowing
non-matching sample types.

Signed-off-by: Adrian Hunter 
---
 tools/perf/builtin-report.c   |   2 +-
 tools/perf/tests/mmap-basic.c |   2 +-
 tools/perf/util/event.h   |   3 +-
 tools/perf/util/evlist.c  | 111 +++---
 tools/perf/util/evlist.h  |   8 ++-
 tools/perf/util/evsel.c   | 101 --
 tools/perf/util/evsel.h   |  14 +-
 tools/perf/util/record.c  |  89 +++--
 tools/perf/util/session.c |   2 +-
 9 files changed, 310 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 958a56a..9725aa3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool,
 static int perf_report__setup_sample_type(struct perf_report *rep)
 {
struct perf_session *self = rep->session;
-   u64 sample_type = perf_evlist__sample_type(self->evlist);
+   u64 sample_type = perf_evlist__combined_sample_type(self->evlist);
 
if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 5b1b5ab..c4185b9 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -72,7 +72,7 @@ int test__basic_mmap(void)
}
 
evsels[i]->attr.wakeup_events = 1;
-   perf_evsel__set_sample_id(evsels[i]);
+   perf_evsel__set_sample_id(evsels[i], false);
 
perf_evlist__add(evlist, evsels[i]);
 
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 19d911c..4913339 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -53,7 +53,8 @@ struct read_event {
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR |  \
PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID |\
-PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
+PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
+PERF_SAMPLE_IDENTIFIER)
 
 struct sample_event {
struct perf_event_headerheader;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9d682e5..6a629af 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void)
return evlist;
 }
 
+/**
+ * perf_evlist__set_id_pos - set the positions of event ids.
+ * @evlist: selected event list
+ *
+ * Events with compatible sample types all have the same id_pos
+ * and is_pos.  For convenience, put a copy on evlist.
+ */
+void perf_evlist__set_id_pos(struct perf_evlist *evlist)
+{
+   struct perf_evsel *first = perf_evlist__first(evlist);
+
+   evlist->id_pos = first->id_pos;
+   evlist->is_pos = first->is_pos;
+}
+
 static void perf_evlist__purge(struct perf_evlist *evlist)
 {
struct perf_evsel *pos, *n;
@@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist)
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
 {
list_add_tail(>node, >entries);
-   ++evlist->nr_entries;
+   if (!evlist->nr_entries++)
+   perf_evlist__set_id_pos(evlist);
 }
 
 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
   struct list_head *list,
   int nr_entries)
 {
+   bool set_id_pos = !evlist->nr_entries;
+
list_splice_tail(list, >entries);
evlist->nr_entries += nr_entries;
+   if (set_id_pos)
+   perf_evlist__set_id_pos(evlist);
 }
 
 void __perf_evlist__set_leader(struct list_head *list)
@@ -349,6 +369,55 @@ struct perf_evsel *perf_evlist__id2evsel(struct 
perf_evlist *evlist, u64 id)
return NULL;
 }
 
+static int perf_evlist__event2id(struct perf_evlist *evlist,
+union perf_event *event, u64 *id)
+{
+   const u64 *array = event->sample.array;
+   ssize_t n;
+
+   n = (event->header.size - sizeof(event->header)) >> 3;
+
+   if (event->header.type == PERF_RECORD_SAMPLE) {
+   if (evlist->id_pos >= n)
+   return -1;
+   *id = array[evlist->id_pos];
+   } else {
+   if (evlist->is_pos > n)
+   return -1;
+   n -= evlist->is_pos;
+   *id = array[n];
+   }
+   return 0;
+}
+
+static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
+  union perf_event *event)
+{
+   struct hlist_head *head;
+   struct perf_sample_id *sid;
+   int hash;
+   u64 id;
+
+   if 

[PATCH V13 07/12] perf tools: add support for PERF_SAMPLE_IDENTFIER

2013-08-27 Thread Adrian Hunter
Enable parsing of samples with sample format bit
PERF_SAMPLE_IDENTFIER.  In addition, if the kernel supports
it, prefer it to selecting PERF_SAMPLE_ID thereby allowing
non-matching sample types.

Signed-off-by: Adrian Hunter adrian.hun...@intel.com
---
 tools/perf/builtin-report.c   |   2 +-
 tools/perf/tests/mmap-basic.c |   2 +-
 tools/perf/util/event.h   |   3 +-
 tools/perf/util/evlist.c  | 111 +++---
 tools/perf/util/evlist.h  |   8 ++-
 tools/perf/util/evsel.c   | 101 --
 tools/perf/util/evsel.h   |  14 +-
 tools/perf/util/record.c  |  89 +++--
 tools/perf/util/session.c |   2 +-
 9 files changed, 310 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 958a56a..9725aa3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool,
 static int perf_report__setup_sample_type(struct perf_report *rep)
 {
struct perf_session *self = rep-session;
-   u64 sample_type = perf_evlist__sample_type(self-evlist);
+   u64 sample_type = perf_evlist__combined_sample_type(self-evlist);
 
if (!self-fd_pipe  !(sample_type  PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 5b1b5ab..c4185b9 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -72,7 +72,7 @@ int test__basic_mmap(void)
}
 
evsels[i]-attr.wakeup_events = 1;
-   perf_evsel__set_sample_id(evsels[i]);
+   perf_evsel__set_sample_id(evsels[i], false);
 
perf_evlist__add(evlist, evsels[i]);
 
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 19d911c..4913339 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -53,7 +53,8 @@ struct read_event {
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR |  \
PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID |\
-PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
+PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
+PERF_SAMPLE_IDENTIFIER)
 
 struct sample_event {
struct perf_event_headerheader;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9d682e5..6a629af 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void)
return evlist;
 }
 
+/**
+ * perf_evlist__set_id_pos - set the positions of event ids.
+ * @evlist: selected event list
+ *
+ * Events with compatible sample types all have the same id_pos
+ * and is_pos.  For convenience, put a copy on evlist.
+ */
+void perf_evlist__set_id_pos(struct perf_evlist *evlist)
+{
+   struct perf_evsel *first = perf_evlist__first(evlist);
+
+   evlist-id_pos = first-id_pos;
+   evlist-is_pos = first-is_pos;
+}
+
 static void perf_evlist__purge(struct perf_evlist *evlist)
 {
struct perf_evsel *pos, *n;
@@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist)
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
 {
list_add_tail(entry-node, evlist-entries);
-   ++evlist-nr_entries;
+   if (!evlist-nr_entries++)
+   perf_evlist__set_id_pos(evlist);
 }
 
 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
   struct list_head *list,
   int nr_entries)
 {
+   bool set_id_pos = !evlist-nr_entries;
+
list_splice_tail(list, evlist-entries);
evlist-nr_entries += nr_entries;
+   if (set_id_pos)
+   perf_evlist__set_id_pos(evlist);
 }
 
 void __perf_evlist__set_leader(struct list_head *list)
@@ -349,6 +369,55 @@ struct perf_evsel *perf_evlist__id2evsel(struct 
perf_evlist *evlist, u64 id)
return NULL;
 }
 
+static int perf_evlist__event2id(struct perf_evlist *evlist,
+union perf_event *event, u64 *id)
+{
+   const u64 *array = event-sample.array;
+   ssize_t n;
+
+   n = (event-header.size - sizeof(event-header))  3;
+
+   if (event-header.type == PERF_RECORD_SAMPLE) {
+   if (evlist-id_pos = n)
+   return -1;
+   *id = array[evlist-id_pos];
+   } else {
+   if (evlist-is_pos  n)
+   return -1;
+   n -= evlist-is_pos;
+   *id = array[n];
+   }
+   return 0;
+}
+
+static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
+  union perf_event *event)
+{
+   struct hlist_head *head;
+   struct perf_sample_id *sid;
+   int hash;
+   u64 id;
+
+