aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c31
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c6
-rw-r--r--tools/perf/util/hist.h12
-rw-r--r--tools/perf/util/session.c63
-rw-r--r--tools/perf/util/session.h16
-rw-r--r--tools/perf/util/ui/browsers/hists.c32
8 files changed, 98 insertions, 66 deletions
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f6fc8f651a25..281b60e5fc7b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -7,6 +7,7 @@
7#include "types.h" 7#include "types.h"
8#include "xyarray.h" 8#include "xyarray.h"
9#include "cgroup.h" 9#include "cgroup.h"
10#include "hist.h"
10 11
11struct perf_counts_values { 12struct perf_counts_values {
12 union { 13 union {
@@ -51,6 +52,7 @@ struct perf_evsel {
51 struct xyarray *id; 52 struct xyarray *id;
52 struct perf_counts *counts; 53 struct perf_counts *counts;
53 int idx; 54 int idx;
55 struct hists hists;
54 char *name; 56 char *name;
55 void *priv; 57 void *priv;
56 struct cgroup_sel *cgrp; 58 struct cgroup_sel *cgrp;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 72c124dc5781..108b0db7bbef 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -969,37 +969,6 @@ bool perf_header__sample_id_all(const struct perf_header *header)
969 return value; 969 return value;
970} 970}
971 971
972struct perf_event_attr *
973perf_header__find_attr(u64 id, struct perf_header *header)
974{
975 int i;
976
977 /*
978 * We set id to -1 if the data file doesn't contain sample
979 * ids. This can happen when the data file contains one type
980 * of event and in that case, the header can still store the
981 * event attribute information. Check for this and avoid
982 * walking through the entire list of ids which may be large.
983 */
984 if (id == -1ULL) {
985 if (header->attrs > 0)
986 return &header->attr[0]->attr;
987 return NULL;
988 }
989
990 for (i = 0; i < header->attrs; i++) {
991 struct perf_header_attr *attr = header->attr[i];
992 int j;
993
994 for (j = 0; j < attr->ids; j++) {
995 if (attr->id[j] == id)
996 return &attr->attr;
997 }
998 }
999
1000 return NULL;
1001}
1002
1003int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 972int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
1004 perf_event__handler_t process, 973 perf_event__handler_t process,
1005 struct perf_session *session) 974 struct perf_session *session)
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f042cebcec1e..2fab13348aab 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -85,8 +85,6 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
85 85
86u64 perf_header__sample_type(struct perf_header *header); 86u64 perf_header__sample_type(struct perf_header *header);
87bool perf_header__sample_id_all(const struct perf_header *header); 87bool perf_header__sample_id_all(const struct perf_header *header);
88struct perf_event_attr *
89perf_header__find_attr(u64 id, struct perf_header *header);
90void perf_header__set_feat(struct perf_header *self, int feat); 88void perf_header__set_feat(struct perf_header *self, int feat);
91void perf_header__clear_feat(struct perf_header *self, int feat); 89void perf_header__clear_feat(struct perf_header *self, int feat);
92bool perf_header__has_feat(const struct perf_header *self, int feat); 90bool perf_header__has_feat(const struct perf_header *self, int feat);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f7ad6bdbc667..627a02e03c57 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -984,8 +984,12 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
984 size_t ret = 0; 984 size_t ret = 0;
985 985
986 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 986 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
987 const char *name = perf_event__name(i); 987 const char *name;
988 988
989 if (self->stats.nr_events[i] == 0)
990 continue;
991
992 name = perf_event__name(i);
989 if (!strcmp(name, "UNKNOWN")) 993 if (!strcmp(name, "UNKNOWN"))
990 continue; 994 continue;
991 995
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 37c79089de09..0d38b435827b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -42,13 +42,10 @@ enum hist_column {
42}; 42};
43 43
44struct hists { 44struct hists {
45 struct rb_node rb_node;
46 struct rb_root entries; 45 struct rb_root entries;
47 u64 nr_entries; 46 u64 nr_entries;
48 struct events_stats stats; 47 struct events_stats stats;
49 u64 config;
50 u64 event_stream; 48 u64 event_stream;
51 u32 type;
52 u16 col_len[HISTC_NR_COLS]; 49 u16 col_len[HISTC_NR_COLS];
53 /* Best would be to reuse the session callchain cursor */ 50 /* Best would be to reuse the session callchain cursor */
54 struct callchain_cursor callchain_cursor; 51 struct callchain_cursor callchain_cursor;
@@ -87,6 +84,8 @@ u16 hists__col_len(struct hists *self, enum hist_column col);
87void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 84void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
88bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); 85bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
89 86
87struct perf_evlist;
88
90#ifdef NO_NEWT_SUPPORT 89#ifdef NO_NEWT_SUPPORT
91static inline int hists__browse(struct hists *self __used, 90static inline int hists__browse(struct hists *self __used,
92 const char *helpline __used, 91 const char *helpline __used,
@@ -95,9 +94,8 @@ static inline int hists__browse(struct hists *self __used,
95 return 0; 94 return 0;
96} 95}
97 96
98static inline int hists__tui_browse_tree(struct rb_root *self __used, 97static inline int hists__tui_browse_tree(struct perf_evlist *evlist __used,
99 const char *help __used, 98 const char *help __used)
100 int evidx __used)
101{ 99{
102 return 0; 100 return 0;
103} 101}
@@ -118,7 +116,7 @@ int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
118#define KEY_LEFT NEWT_KEY_LEFT 116#define KEY_LEFT NEWT_KEY_LEFT
119#define KEY_RIGHT NEWT_KEY_RIGHT 117#define KEY_RIGHT NEWT_KEY_RIGHT
120 118
121int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx); 119int hists__tui_browse_tree(struct perf_evlist *evlist, const char *help);
122#endif 120#endif
123 121
124unsigned int hists__sort_list_width(struct hists *self); 122unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a3a871f7bda3..0d414199889d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -7,10 +7,52 @@
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9 9
10#include "evlist.h"
11#include "evsel.h"
10#include "session.h" 12#include "session.h"
11#include "sort.h" 13#include "sort.h"
12#include "util.h" 14#include "util.h"
13 15
16static int perf_session__read_evlist(struct perf_session *session)
17{
18 int i, j;
19
20 session->evlist = perf_evlist__new(NULL, NULL);
21 if (session->evlist == NULL)
22 return -ENOMEM;
23
24 for (i = 0; i < session->header.attrs; ++i) {
25 struct perf_header_attr *hattr = session->header.attr[i];
26 struct perf_evsel *evsel = perf_evsel__new(&hattr->attr, i);
27
28 if (evsel == NULL)
29 goto out_delete_evlist;
30 /*
31 * Do it before so that if perf_evsel__alloc_id fails, this
32 * entry gets purged too at perf_evlist__delete().
33 */
34 perf_evlist__add(session->evlist, evsel);
35 /*
36 * We don't have the cpu and thread maps on the header, so
37 * for allocating the perf_sample_id table we fake 1 cpu and
38 * hattr->ids threads.
39 */
40 if (perf_evsel__alloc_id(evsel, 1, hattr->ids))
41 goto out_delete_evlist;
42
43 for (j = 0; j < hattr->ids; ++j)
44 perf_evlist__id_hash(session->evlist, evsel, 0, j,
45 hattr->id[j]);
46 }
47
48 return 0;
49
50out_delete_evlist:
51 perf_evlist__delete(session->evlist);
52 session->evlist = NULL;
53 return -ENOMEM;
54}
55
14static int perf_session__open(struct perf_session *self, bool force) 56static int perf_session__open(struct perf_session *self, bool force)
15{ 57{
16 struct stat input_stat; 58 struct stat input_stat;
@@ -56,6 +98,11 @@ static int perf_session__open(struct perf_session *self, bool force)
56 goto out_close; 98 goto out_close;
57 } 99 }
58 100
101 if (perf_session__read_evlist(self) < 0) {
102 pr_err("Not enough memory to read the event selector list\n");
103 goto out_close;
104 }
105
59 self->size = input_stat.st_size; 106 self->size = input_stat.st_size;
60 return 0; 107 return 0;
61 108
@@ -141,7 +188,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
141 memcpy(self->filename, filename, len); 188 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT; 189 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads); 190 INIT_LIST_HEAD(&self->dead_threads);
144 self->hists_tree = RB_ROOT;
145 self->last_match = NULL; 191 self->last_match = NULL;
146 /* 192 /*
147 * On 64bit we can mmap the data file in one go. No need for tiny mmap 193 * On 64bit we can mmap the data file in one go. No need for tiny mmap
@@ -1137,3 +1183,18 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
1137 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); 1183 size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
1138 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); 1184 return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
1139} 1185}
1186
1187size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1188{
1189 struct perf_evsel *pos;
1190 size_t ret = fprintf(fp, "Aggregated stats:\n");
1191
1192 ret += hists__fprintf_nr_events(&session->hists, fp);
1193
1194 list_for_each_entry(pos, &session->evlist->entries, node) {
1195 ret += fprintf(fp, "%s stats:\n", event_name(pos));
1196 ret += hists__fprintf_nr_events(&pos->hists, fp);
1197 }
1198
1199 return ret;
1200}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 977b3a1b14aa..05dd7bcb9453 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -34,12 +34,12 @@ struct perf_session {
34 struct thread *last_match; 34 struct thread *last_match;
35 struct machine host_machine; 35 struct machine host_machine;
36 struct rb_root machines; 36 struct rb_root machines;
37 struct rb_root hists_tree; 37 struct perf_evlist *evlist;
38 /* 38 /*
39 * FIXME: should point to the first entry in hists_tree and 39 * FIXME: Need to split this up further, we need global
40 * be a hists instance. Right now its only 'report' 40 * stats + per event stats. 'perf diff' also needs
41 * that is using ->hists_tree while all the rest use 41 * to properly support multiple events in a single
42 * ->hists. 42 * perf.data file.
43 */ 43 */
44 struct hists hists; 44 struct hists hists;
45 u64 sample_type; 45 u64 sample_type;
@@ -151,11 +151,7 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
151size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 151size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
152 FILE *fp, bool with_hits); 152 FILE *fp, bool with_hits);
153 153
154static inline 154size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
155size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp)
156{
157 return hists__fprintf_nr_events(&self->hists, fp);
158}
159 155
160static inline int perf_session__parse_sample(struct perf_session *session, 156static inline int perf_session__parse_sample(struct perf_session *session,
161 const union perf_event *event, 157 const union perf_event *event,
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index c98e6f81d285..f3af4fe5cdc4 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -7,6 +7,8 @@
7#include <newt.h> 7#include <newt.h>
8#include <linux/rbtree.h> 8#include <linux/rbtree.h>
9 9
10#include "../../evsel.h"
11#include "../../evlist.h"
10#include "../../hist.h" 12#include "../../hist.h"
11#include "../../pstack.h" 13#include "../../pstack.h"
12#include "../../sort.h" 14#include "../../sort.h"
@@ -987,31 +989,33 @@ out:
987 return key; 989 return key;
988} 990}
989 991
990int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx) 992int hists__tui_browse_tree(struct perf_evlist *evlist, const char *help)
991{ 993{
992 struct rb_node *first = rb_first(self), *nd = first, *next; 994 struct perf_evsel *pos;
993 int key = 0;
994 995
995 while (nd) { 996 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
996 struct hists *hists = rb_entry(nd, struct hists, rb_node); 997 while (pos) {
997 const char *ev_name = __event_name(hists->type, hists->config); 998 struct hists *hists = &pos->hists;
999 const char *ev_name = event_name(pos);
1000 int key = hists__browse(hists, help, ev_name, pos->idx);
998 1001
999 key = hists__browse(hists, help, ev_name, evidx);
1000 switch (key) { 1002 switch (key) {
1001 case NEWT_KEY_TAB: 1003 case NEWT_KEY_TAB:
1002 next = rb_next(nd); 1004 if (pos->node.next == &evlist->entries)
1003 if (next) 1005 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1004 nd = next; 1006 else
1007 pos = list_entry(pos->node.next, struct perf_evsel, node);
1005 break; 1008 break;
1006 case NEWT_KEY_UNTAB: 1009 case NEWT_KEY_UNTAB:
1007 if (nd == first) 1010 if (pos->node.prev == &evlist->entries)
1008 continue; 1011 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1009 nd = rb_prev(nd); 1012 else
1013 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1010 break; 1014 break;
1011 default: 1015 default:
1012 return key; 1016 return key;
1013 } 1017 }
1014 } 1018 }
1015 1019
1016 return key; 1020 return 0;
1017} 1021}