aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 427182953fd7..695de4b5ae63 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -19,6 +19,8 @@
19#include "perf.h" 19#include "perf.h"
20#include "util/debug.h" 20#include "util/debug.h"
21 21
22#include "util/evlist.h"
23#include "util/evsel.h"
22#include "util/annotate.h" 24#include "util/annotate.h"
23#include "util/event.h" 25#include "util/event.h"
24#include "util/parse-options.h" 26#include "util/parse-options.h"
@@ -38,9 +40,13 @@ static bool print_line;
38 40
39static const char *sym_hist_filter; 41static const char *sym_hist_filter;
40 42
41static int hists__add_entry(struct hists *self, struct addr_location *al) 43static int perf_evlist__add_sample(struct perf_evlist *evlist,
44 struct perf_sample *sample,
45 struct addr_location *al)
42{ 46{
47 struct perf_evsel *evsel;
43 struct hist_entry *he; 48 struct hist_entry *he;
49 int ret;
44 50
45 if (sym_hist_filter != NULL && 51 if (sym_hist_filter != NULL &&
46 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) { 52 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) {
@@ -53,23 +59,35 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
53 return 0; 59 return 0;
54 } 60 }
55 61
56 he = __hists__add_entry(self, al, NULL, 1); 62 evsel = perf_evlist__id2evsel(evlist, sample->id);
63 if (evsel == NULL) {
64 /*
65 * FIXME: Propagate this back, but at least we're in a builtin,
66 * where exit() is allowed. ;-)
67 */
68 ui__warning("Invalid %s file, contains samples with id not in "
69 "its header!\n", input_name);
70 exit_browser(0);
71 exit(1);
72 }
73
74 he = __hists__add_entry(&evsel->hists, al, NULL, 1);
57 if (he == NULL) 75 if (he == NULL)
58 return -ENOMEM; 76 return -ENOMEM;
59 77
78 ret = 0;
60 if (he->ms.sym != NULL) { 79 if (he->ms.sym != NULL) {
61 /*
62 * All aggregated on the first sym_hist.
63 */
64 struct annotation *notes = symbol__annotation(he->ms.sym); 80 struct annotation *notes = symbol__annotation(he->ms.sym);
65 if (notes->src == NULL && 81 if (notes->src == NULL &&
66 symbol__alloc_hist(he->ms.sym, 1) < 0) 82 symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
67 return -ENOMEM; 83 return -ENOMEM;
68 84
69 return hist_entry__inc_addr_samples(he, 0, al->addr); 85 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
70 } 86 }
71 87
72 return 0; 88 evsel->hists.stats.total_period += sample->period;
89 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
90 return ret;
73} 91}
74 92
75static int process_sample_event(union perf_event *event, 93static int process_sample_event(union perf_event *event,
@@ -85,7 +103,7 @@ static int process_sample_event(union perf_event *event,
85 return -1; 103 return -1;
86 } 104 }
87 105
88 if (!al.filtered && hists__add_entry(&session->hists, &al)) { 106 if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) {
89 pr_warning("problem incrementing symbol count, " 107 pr_warning("problem incrementing symbol count, "
90 "skipping event\n"); 108 "skipping event\n");
91 return -1; 109 return -1;
@@ -100,7 +118,7 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
100 print_line, full_paths, 0, 0); 118 print_line, full_paths, 0, 0);
101} 119}
102 120
103static void hists__find_annotations(struct hists *self) 121static void hists__find_annotations(struct hists *self, int evidx)
104{ 122{
105 struct rb_node *nd = rb_first(&self->entries), *next; 123 struct rb_node *nd = rb_first(&self->entries), *next;
106 int key = KEY_RIGHT; 124 int key = KEY_RIGHT;
@@ -123,8 +141,7 @@ find_next:
123 } 141 }
124 142
125 if (use_browser > 0) { 143 if (use_browser > 0) {
126 /* For now all is aggregated on the first */ 144 key = hist_entry__tui_annotate(he, evidx);
127 key = hist_entry__tui_annotate(he, 0);
128 switch (key) { 145 switch (key) {
129 case KEY_RIGHT: 146 case KEY_RIGHT:
130 next = rb_next(nd); 147 next = rb_next(nd);
@@ -139,8 +156,7 @@ find_next:
139 if (next != NULL) 156 if (next != NULL)
140 nd = next; 157 nd = next;
141 } else { 158 } else {
142 /* For now all is aggregated on the first */ 159 hist_entry__tty_annotate(he, evidx);
143 hist_entry__tty_annotate(he, 0);
144 nd = rb_next(nd); 160 nd = rb_next(nd);
145 /* 161 /*
146 * Since we have a hist_entry per IP for the same 162 * Since we have a hist_entry per IP for the same
@@ -166,6 +182,8 @@ static int __cmd_annotate(void)
166{ 182{
167 int ret; 183 int ret;
168 struct perf_session *session; 184 struct perf_session *session;
185 struct perf_evsel *pos;
186 u64 total_nr_samples;
169 187
170 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 188 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
171 if (session == NULL) 189 if (session == NULL)
@@ -186,12 +204,36 @@ static int __cmd_annotate(void)
186 if (verbose > 2) 204 if (verbose > 2)
187 perf_session__fprintf_dsos(session, stdout); 205 perf_session__fprintf_dsos(session, stdout);
188 206
189 hists__collapse_resort(&session->hists); 207 total_nr_samples = 0;
190 hists__output_resort(&session->hists); 208 list_for_each_entry(pos, &session->evlist->entries, node) {
191 hists__find_annotations(&session->hists); 209 struct hists *hists = &pos->hists;
192out_delete: 210 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
193 perf_session__delete(session); 211
212 if (nr_samples > 0) {
213 total_nr_samples += nr_samples;
214 hists__collapse_resort(hists);
215 hists__output_resort(hists);
216 hists__find_annotations(hists, pos->idx);
217 }
218 }
194 219
220 if (total_nr_samples == 0) {
221 ui__warning("The %s file has no samples!\n", input_name);
222 goto out_delete;
223 }
224out_delete:
225 /*
226 * Speed up the exit process, for large files this can
227 * take quite a while.
228 *
229 * XXX Enable this when using valgrind or if we ever
230 * librarize this command.
231 *
232 * Also experiment with obstacks to see how much speed
233 * up we'll get here.
234 *
235 * perf_session__delete(session);
236 */
195 return ret; 237 return ret;
196} 238}
197 239