diff options
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 67 |
1 files changed, 34 insertions, 33 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b790673cb0aa..7dbf22d096b8 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -139,7 +139,7 @@ static void sig_winch_handler(int sig __used) | |||
139 | static int parse_source(struct sym_entry *syme) | 139 | static int parse_source(struct sym_entry *syme) |
140 | { | 140 | { |
141 | struct symbol *sym; | 141 | struct symbol *sym; |
142 | struct sym_entry_source *source; | 142 | struct annotation *notes; |
143 | struct map *map; | 143 | struct map *map; |
144 | int err = -1; | 144 | int err = -1; |
145 | 145 | ||
@@ -152,39 +152,35 @@ static int parse_source(struct sym_entry *syme) | |||
152 | /* | 152 | /* |
153 | * We can't annotate with just /proc/kallsyms | 153 | * We can't annotate with just /proc/kallsyms |
154 | */ | 154 | */ |
155 | if (map->dso->origin == DSO__ORIG_KERNEL) | 155 | if (map->dso->origin == DSO__ORIG_KERNEL) { |
156 | pr_err("Can't annotate %s: No vmlinux file was found in the " | ||
157 | "path\n", sym->name); | ||
158 | sleep(1); | ||
156 | return -1; | 159 | return -1; |
157 | |||
158 | if (syme->src == NULL) { | ||
159 | syme->src = zalloc(sizeof(*source)); | ||
160 | if (syme->src == NULL) | ||
161 | return -1; | ||
162 | pthread_mutex_init(&syme->src->lock, NULL); | ||
163 | INIT_LIST_HEAD(&syme->src->head); | ||
164 | } | 160 | } |
165 | 161 | ||
166 | source = syme->src; | 162 | notes = symbol__annotation(sym); |
167 | 163 | if (notes->src != NULL) { | |
168 | if (symbol__annotation(sym)->histograms != NULL) { | 164 | pthread_mutex_lock(¬es->lock); |
169 | pthread_mutex_lock(&source->lock); | ||
170 | goto out_assign; | 165 | goto out_assign; |
171 | } | 166 | } |
172 | 167 | ||
173 | pthread_mutex_lock(&source->lock); | 168 | pthread_mutex_lock(¬es->lock); |
174 | 169 | ||
175 | if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { | 170 | if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { |
176 | pr_err("Not enough memory for annotating '%s' symbol!\n", | 171 | pr_err("Not enough memory for annotating '%s' symbol!\n", |
177 | sym->name); | 172 | sym->name); |
173 | sleep(1); | ||
178 | goto out_unlock; | 174 | goto out_unlock; |
179 | } | 175 | } |
180 | 176 | ||
181 | err = symbol__annotate(sym, syme->map, &source->head, 0); | 177 | err = symbol__annotate(sym, syme->map, 0); |
182 | if (err == 0) { | 178 | if (err == 0) { |
183 | out_assign: | 179 | out_assign: |
184 | sym_filter_entry = syme; | 180 | sym_filter_entry = syme; |
185 | } | 181 | } |
186 | out_unlock: | 182 | out_unlock: |
187 | pthread_mutex_unlock(&source->lock); | 183 | pthread_mutex_unlock(¬es->lock); |
188 | return err; | 184 | return err; |
189 | } | 185 | } |
190 | 186 | ||
@@ -196,20 +192,27 @@ static void __zero_source_counters(struct sym_entry *syme) | |||
196 | 192 | ||
197 | static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) | 193 | static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) |
198 | { | 194 | { |
195 | struct annotation *notes; | ||
196 | struct symbol *sym; | ||
197 | |||
199 | if (syme != sym_filter_entry) | 198 | if (syme != sym_filter_entry) |
200 | return; | 199 | return; |
201 | 200 | ||
202 | if (pthread_mutex_trylock(&syme->src->lock)) | 201 | sym = sym_entry__symbol(syme); |
202 | notes = symbol__annotation(sym); | ||
203 | |||
204 | if (pthread_mutex_trylock(¬es->lock)) | ||
203 | return; | 205 | return; |
204 | 206 | ||
205 | ip = syme->map->map_ip(syme->map, ip); | 207 | ip = syme->map->map_ip(syme->map, ip); |
206 | symbol__inc_addr_samples(sym_entry__symbol(syme), syme->map, counter, ip); | 208 | symbol__inc_addr_samples(sym, syme->map, counter, ip); |
207 | 209 | ||
208 | pthread_mutex_unlock(&syme->src->lock); | 210 | pthread_mutex_unlock(¬es->lock); |
209 | } | 211 | } |
210 | 212 | ||
211 | static void show_details(struct sym_entry *syme) | 213 | static void show_details(struct sym_entry *syme) |
212 | { | 214 | { |
215 | struct annotation *notes; | ||
213 | struct symbol *symbol; | 216 | struct symbol *symbol; |
214 | int more; | 217 | int more; |
215 | 218 | ||
@@ -217,24 +220,26 @@ static void show_details(struct sym_entry *syme) | |||
217 | return; | 220 | return; |
218 | 221 | ||
219 | symbol = sym_entry__symbol(syme); | 222 | symbol = sym_entry__symbol(syme); |
220 | if (!syme->src || symbol__annotation(symbol)->histograms == NULL) | 223 | notes = symbol__annotation(symbol); |
221 | return; | 224 | |
225 | pthread_mutex_lock(¬es->lock); | ||
226 | |||
227 | if (notes->src == NULL) | ||
228 | goto out_unlock; | ||
222 | 229 | ||
223 | printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); | 230 | printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); |
224 | printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); | 231 | printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); |
225 | 232 | ||
226 | pthread_mutex_lock(&syme->src->lock); | 233 | more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx, |
227 | more = symbol__annotate_printf(symbol, syme->map, &syme->src->head, | 234 | 0, sym_pcnt_filter, top.print_entries); |
228 | top.sym_evsel->idx, 0, sym_pcnt_filter, | ||
229 | top.print_entries); | ||
230 | if (top.zero) | 235 | if (top.zero) |
231 | symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); | 236 | symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); |
232 | else | 237 | else |
233 | symbol__annotate_decay_histogram(symbol, &syme->src->head, | 238 | symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx); |
234 | top.sym_evsel->idx); | ||
235 | pthread_mutex_unlock(&syme->src->lock); | ||
236 | if (more != 0) | 239 | if (more != 0) |
237 | printf("%d lines not displayed, maybe increase display entries [e]\n", more); | 240 | printf("%d lines not displayed, maybe increase display entries [e]\n", more); |
241 | out_unlock: | ||
242 | pthread_mutex_unlock(¬es->lock); | ||
238 | } | 243 | } |
239 | 244 | ||
240 | static const char CONSOLE_CLEAR[] = "[H[2J"; | 245 | static const char CONSOLE_CLEAR[] = "[H[2J"; |
@@ -372,10 +377,8 @@ static void prompt_symbol(struct sym_entry **target, const char *msg) | |||
372 | 377 | ||
373 | /* zero counters of active symbol */ | 378 | /* zero counters of active symbol */ |
374 | if (syme) { | 379 | if (syme) { |
375 | pthread_mutex_lock(&syme->src->lock); | ||
376 | __zero_source_counters(syme); | 380 | __zero_source_counters(syme); |
377 | *target = NULL; | 381 | *target = NULL; |
378 | pthread_mutex_unlock(&syme->src->lock); | ||
379 | } | 382 | } |
380 | 383 | ||
381 | fprintf(stdout, "\n%s: ", msg); | 384 | fprintf(stdout, "\n%s: ", msg); |
@@ -554,10 +557,8 @@ static void handle_keypress(struct perf_session *session, int c) | |||
554 | else { | 557 | else { |
555 | struct sym_entry *syme = sym_filter_entry; | 558 | struct sym_entry *syme = sym_filter_entry; |
556 | 559 | ||
557 | pthread_mutex_lock(&syme->src->lock); | ||
558 | sym_filter_entry = NULL; | 560 | sym_filter_entry = NULL; |
559 | __zero_source_counters(syme); | 561 | __zero_source_counters(syme); |
560 | pthread_mutex_unlock(&syme->src->lock); | ||
561 | } | 562 | } |
562 | break; | 563 | break; |
563 | case 'U': | 564 | case 'U': |
@@ -653,7 +654,7 @@ static int symbol_filter(struct map *map, struct symbol *sym) | |||
653 | 654 | ||
654 | syme = symbol__priv(sym); | 655 | syme = symbol__priv(sym); |
655 | syme->map = map; | 656 | syme->map = map; |
656 | syme->src = NULL; | 657 | symbol__annotate_init(map, sym); |
657 | 658 | ||
658 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { | 659 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { |
659 | /* schedule initial sym_filter_entry setup */ | 660 | /* schedule initial sym_filter_entry setup */ |