aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c507
1 files changed, 307 insertions, 200 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 37512e936235..e0a374d0e43a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -54,26 +55,31 @@
54 55
55static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 56static int fd[MAX_NR_CPUS][MAX_COUNTERS];
56 57
57static int system_wide = 0; 58static int system_wide = 0;
58 59
59static int default_interval = 100000; 60static int default_interval = 0;
60 61
61static int count_filter = 5; 62static int count_filter = 5;
62static int print_entries = 15; 63static int print_entries;
63 64
64static int target_pid = -1; 65static int target_pid = -1;
65static int inherit = 0; 66static int inherit = 0;
66static int profile_cpu = -1; 67static int profile_cpu = -1;
67static int nr_cpus = 0; 68static int nr_cpus = 0;
68static unsigned int realtime_prio = 0; 69static unsigned int realtime_prio = 0;
69static int group = 0; 70static int group = 0;
70static unsigned int page_size; 71static unsigned int page_size;
71static unsigned int mmap_pages = 16; 72static unsigned int mmap_pages = 16;
72static int freq = 0; 73static int freq = 1000; /* 1 KHz */
73 74
74static int delay_secs = 2; 75static int delay_secs = 2;
75static int zero; 76static int zero = 0;
76static int dump_symtab; 77static int dump_symtab = 0;
78
79static bool hide_kernel_symbols = false;
80static bool hide_user_symbols = false;
81static struct winsize winsize;
82struct symbol_conf symbol_conf;
77 83
78/* 84/*
79 * Source 85 * Source
@@ -86,83 +92,126 @@ struct source_line {
86 struct source_line *next; 92 struct source_line *next;
87}; 93};
88 94
89static char *sym_filter = NULL; 95static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL; 96struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5; 97static int sym_pcnt_filter = 5;
92static int sym_counter = 0; 98static int sym_counter = 0;
93static int display_weighted = -1; 99static int display_weighted = -1;
94 100
95/* 101/*
96 * Symbols 102 * Symbols
97 */ 103 */
98 104
99static u64 min_ip; 105struct sym_entry_source {
100static u64 max_ip = -1ll; 106 struct source_line *source;
107 struct source_line *lines;
108 struct source_line **lines_tail;
109 pthread_mutex_t lock;
110};
101 111
102struct sym_entry { 112struct sym_entry {
103 struct rb_node rb_node; 113 struct rb_node rb_node;
104 struct list_head node; 114 struct list_head node;
105 unsigned long count[MAX_COUNTERS];
106 unsigned long snap_count; 115 unsigned long snap_count;
107 double weight; 116 double weight;
108 int skip; 117 int skip;
109 struct source_line *source; 118 u16 name_len;
110 struct source_line *lines; 119 u8 origin;
111 struct source_line **lines_tail; 120 struct map *map;
112 pthread_mutex_t source_lock; 121 struct sym_entry_source *src;
122 unsigned long count[0];
113}; 123};
114 124
115/* 125/*
116 * Source functions 126 * Source functions
117 */ 127 */
118 128
129static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
130{
131 return ((void *)self) + symbol_conf.priv_size;
132}
133
134static void get_term_dimensions(struct winsize *ws)
135{
136 char *s = getenv("LINES");
137
138 if (s != NULL) {
139 ws->ws_row = atoi(s);
140 s = getenv("COLUMNS");
141 if (s != NULL) {
142 ws->ws_col = atoi(s);
143 if (ws->ws_row && ws->ws_col)
144 return;
145 }
146 }
147#ifdef TIOCGWINSZ
148 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
149 ws->ws_row && ws->ws_col)
150 return;
151#endif
152 ws->ws_row = 25;
153 ws->ws_col = 80;
154}
155
156static void update_print_entries(struct winsize *ws)
157{
158 print_entries = ws->ws_row;
159
160 if (print_entries > 9)
161 print_entries -= 9;
162}
163
164static void sig_winch_handler(int sig __used)
165{
166 get_term_dimensions(&winsize);
167 update_print_entries(&winsize);
168}
169
119static void parse_source(struct sym_entry *syme) 170static void parse_source(struct sym_entry *syme)
120{ 171{
121 struct symbol *sym; 172 struct symbol *sym;
122 struct module *module; 173 struct sym_entry_source *source;
123 struct section *section = NULL; 174 struct map *map;
124 FILE *file; 175 FILE *file;
125 char command[PATH_MAX*2]; 176 char command[PATH_MAX*2];
126 const char *path = vmlinux_name; 177 const char *path;
127 u64 start, end, len; 178 u64 len;
128 179
129 if (!syme) 180 if (!syme)
130 return; 181 return;
131 182
132 if (syme->lines) { 183 if (syme->src == NULL) {
133 pthread_mutex_lock(&syme->source_lock); 184 syme->src = zalloc(sizeof(*source));
134 goto out_assign; 185 if (syme->src == NULL)
186 return;
187 pthread_mutex_init(&syme->src->lock, NULL);
135 } 188 }
136 189
137 sym = (struct symbol *)(syme + 1); 190 source = syme->src;
138 module = sym->module;
139
140 if (module)
141 path = module->path;
142 if (!path)
143 return;
144
145 start = sym->obj_start;
146 if (!start)
147 start = sym->start;
148 191
149 if (module) { 192 if (source->lines) {
150 section = module->sections->find_section(module->sections, ".text"); 193 pthread_mutex_lock(&source->lock);
151 if (section) 194 goto out_assign;
152 start -= section->vma;
153 } 195 }
154 196
155 end = start + sym->end - sym->start + 1; 197 sym = sym_entry__symbol(syme);
198 map = syme->map;
199 path = map->dso->long_name;
200
156 len = sym->end - sym->start; 201 len = sym->end - sym->start;
157 202
158 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 203 sprintf(command,
204 "objdump --start-address=0x%016Lx "
205 "--stop-address=0x%016Lx -dS %s",
206 map->unmap_ip(map, sym->start),
207 map->unmap_ip(map, sym->end), path);
159 208
160 file = popen(command, "r"); 209 file = popen(command, "r");
161 if (!file) 210 if (!file)
162 return; 211 return;
163 212
164 pthread_mutex_lock(&syme->source_lock); 213 pthread_mutex_lock(&source->lock);
165 syme->lines_tail = &syme->lines; 214 source->lines_tail = &source->lines;
166 while (!feof(file)) { 215 while (!feof(file)) {
167 struct source_line *src; 216 struct source_line *src;
168 size_t dummy = 0; 217 size_t dummy = 0;
@@ -182,24 +231,22 @@ static void parse_source(struct sym_entry *syme)
182 *c = 0; 231 *c = 0;
183 232
184 src->next = NULL; 233 src->next = NULL;
185 *syme->lines_tail = src; 234 *source->lines_tail = src;
186 syme->lines_tail = &src->next; 235 source->lines_tail = &src->next;
187 236
188 if (strlen(src->line)>8 && src->line[8] == ':') { 237 if (strlen(src->line)>8 && src->line[8] == ':') {
189 src->eip = strtoull(src->line, NULL, 16); 238 src->eip = strtoull(src->line, NULL, 16);
190 if (section) 239 src->eip = map->unmap_ip(map, src->eip);
191 src->eip += section->vma;
192 } 240 }
193 if (strlen(src->line)>8 && src->line[16] == ':') { 241 if (strlen(src->line)>8 && src->line[16] == ':') {
194 src->eip = strtoull(src->line, NULL, 16); 242 src->eip = strtoull(src->line, NULL, 16);
195 if (section) 243 src->eip = map->unmap_ip(map, src->eip);
196 src->eip += section->vma;
197 } 244 }
198 } 245 }
199 pclose(file); 246 pclose(file);
200out_assign: 247out_assign:
201 sym_filter_entry = syme; 248 sym_filter_entry = syme;
202 pthread_mutex_unlock(&syme->source_lock); 249 pthread_mutex_unlock(&source->lock);
203} 250}
204 251
205static void __zero_source_counters(struct sym_entry *syme) 252static void __zero_source_counters(struct sym_entry *syme)
@@ -207,7 +254,7 @@ static void __zero_source_counters(struct sym_entry *syme)
207 int i; 254 int i;
208 struct source_line *line; 255 struct source_line *line;
209 256
210 line = syme->lines; 257 line = syme->src->lines;
211 while (line) { 258 while (line) {
212 for (i = 0; i < nr_counters; i++) 259 for (i = 0; i < nr_counters; i++)
213 line->count[i] = 0; 260 line->count[i] = 0;
@@ -222,13 +269,13 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
222 if (syme != sym_filter_entry) 269 if (syme != sym_filter_entry)
223 return; 270 return;
224 271
225 if (pthread_mutex_trylock(&syme->source_lock)) 272 if (pthread_mutex_trylock(&syme->src->lock))
226 return; 273 return;
227 274
228 if (!syme->source) 275 if (syme->src == NULL || syme->src->source == NULL)
229 goto out_unlock; 276 goto out_unlock;
230 277
231 for (line = syme->lines; line; line = line->next) { 278 for (line = syme->src->lines; line; line = line->next) {
232 if (line->eip == ip) { 279 if (line->eip == ip) {
233 line->count[counter]++; 280 line->count[counter]++;
234 break; 281 break;
@@ -237,32 +284,25 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
237 break; 284 break;
238 } 285 }
239out_unlock: 286out_unlock:
240 pthread_mutex_unlock(&syme->source_lock); 287 pthread_mutex_unlock(&syme->src->lock);
241} 288}
242 289
243static void lookup_sym_source(struct sym_entry *syme) 290static void lookup_sym_source(struct sym_entry *syme)
244{ 291{
245 struct symbol *symbol = (struct symbol *)(syme + 1); 292 struct symbol *symbol = sym_entry__symbol(syme);
246 struct source_line *line; 293 struct source_line *line;
247 char pattern[PATH_MAX]; 294 char pattern[PATH_MAX];
248 char *idx;
249 295
250 sprintf(pattern, "<%s>:", symbol->name); 296 sprintf(pattern, "<%s>:", symbol->name);
251 297
252 if (symbol->module) { 298 pthread_mutex_lock(&syme->src->lock);
253 idx = strstr(pattern, "\t"); 299 for (line = syme->src->lines; line; line = line->next) {
254 if (idx)
255 *idx = 0;
256 }
257
258 pthread_mutex_lock(&syme->source_lock);
259 for (line = syme->lines; line; line = line->next) {
260 if (strstr(line->line, pattern)) { 300 if (strstr(line->line, pattern)) {
261 syme->source = line; 301 syme->src->source = line;
262 break; 302 break;
263 } 303 }
264 } 304 }
265 pthread_mutex_unlock(&syme->source_lock); 305 pthread_mutex_unlock(&syme->src->lock);
266} 306}
267 307
268static void show_lines(struct source_line *queue, int count, int total) 308static void show_lines(struct source_line *queue, int count, int total)
@@ -292,24 +332,24 @@ static void show_details(struct sym_entry *syme)
292 if (!syme) 332 if (!syme)
293 return; 333 return;
294 334
295 if (!syme->source) 335 if (!syme->src->source)
296 lookup_sym_source(syme); 336 lookup_sym_source(syme);
297 337
298 if (!syme->source) 338 if (!syme->src->source)
299 return; 339 return;
300 340
301 symbol = (struct symbol *)(syme + 1); 341 symbol = sym_entry__symbol(syme);
302 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 342 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
303 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 343 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
304 344
305 pthread_mutex_lock(&syme->source_lock); 345 pthread_mutex_lock(&syme->src->lock);
306 line = syme->source; 346 line = syme->src->source;
307 while (line) { 347 while (line) {
308 total += line->count[sym_counter]; 348 total += line->count[sym_counter];
309 line = line->next; 349 line = line->next;
310 } 350 }
311 351
312 line = syme->source; 352 line = syme->src->source;
313 while (line) { 353 while (line) {
314 float pcnt = 0.0; 354 float pcnt = 0.0;
315 355
@@ -334,13 +374,13 @@ static void show_details(struct sym_entry *syme)
334 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; 374 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
335 line = line->next; 375 line = line->next;
336 } 376 }
337 pthread_mutex_unlock(&syme->source_lock); 377 pthread_mutex_unlock(&syme->src->lock);
338 if (more) 378 if (more)
339 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 379 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
340} 380}
341 381
342/* 382/*
343 * Symbols will be added here in record_ip and will get out 383 * Symbols will be added here in event__process_sample and will get out
344 * after decayed. 384 * after decayed.
345 */ 385 */
346static LIST_HEAD(active_symbols); 386static LIST_HEAD(active_symbols);
@@ -411,6 +451,8 @@ static void print_sym_table(void)
411 struct sym_entry *syme, *n; 451 struct sym_entry *syme, *n;
412 struct rb_root tmp = RB_ROOT; 452 struct rb_root tmp = RB_ROOT;
413 struct rb_node *nd; 453 struct rb_node *nd;
454 int sym_width = 0, dso_width = 0, max_dso_width;
455 const int win_width = winsize.ws_col - 1;
414 456
415 samples = userspace_samples = 0; 457 samples = userspace_samples = 0;
416 458
@@ -422,6 +464,14 @@ static void print_sym_table(void)
422 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 464 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
423 syme->snap_count = syme->count[snap]; 465 syme->snap_count = syme->count[snap];
424 if (syme->snap_count != 0) { 466 if (syme->snap_count != 0) {
467
468 if ((hide_user_symbols &&
469 syme->origin == PERF_RECORD_MISC_USER) ||
470 (hide_kernel_symbols &&
471 syme->origin == PERF_RECORD_MISC_KERNEL)) {
472 list_remove_active_sym(syme);
473 continue;
474 }
425 syme->weight = sym_weight(syme); 475 syme->weight = sym_weight(syme);
426 rb_insert_active_sym(&tmp, syme); 476 rb_insert_active_sym(&tmp, syme);
427 sum_ksamples += syme->snap_count; 477 sum_ksamples += syme->snap_count;
@@ -434,8 +484,7 @@ static void print_sym_table(void)
434 484
435 puts(CONSOLE_CLEAR); 485 puts(CONSOLE_CLEAR);
436 486
437 printf( 487 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
438"------------------------------------------------------------------------------\n");
439 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [", 488 printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [",
440 samples_per_sec, 489 samples_per_sec,
441 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 490 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
@@ -473,33 +522,57 @@ static void print_sym_table(void)
473 printf(", %d CPUs)\n", nr_cpus); 522 printf(", %d CPUs)\n", nr_cpus);
474 } 523 }
475 524
476 printf("------------------------------------------------------------------------------\n\n"); 525 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
477 526
478 if (sym_filter_entry) { 527 if (sym_filter_entry) {
479 show_details(sym_filter_entry); 528 show_details(sym_filter_entry);
480 return; 529 return;
481 } 530 }
482 531
532 /*
533 * Find the longest symbol name that will be displayed
534 */
535 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
536 syme = rb_entry(nd, struct sym_entry, rb_node);
537 if (++printed > print_entries ||
538 (int)syme->snap_count < count_filter)
539 continue;
540
541 if (syme->map->dso->long_name_len > dso_width)
542 dso_width = syme->map->dso->long_name_len;
543
544 if (syme->name_len > sym_width)
545 sym_width = syme->name_len;
546 }
547
548 printed = 0;
549
550 max_dso_width = winsize.ws_col - sym_width - 29;
551 if (dso_width > max_dso_width)
552 dso_width = max_dso_width;
553 putchar('\n');
483 if (nr_counters == 1) 554 if (nr_counters == 1)
484 printf(" samples pcnt"); 555 printf(" samples pcnt");
485 else 556 else
486 printf(" weight samples pcnt"); 557 printf(" weight samples pcnt");
487 558
488 if (verbose) 559 if (verbose)
489 printf(" RIP "); 560 printf(" RIP ");
490 printf(" kernel function\n"); 561 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
491 printf(" %s _______ _____", 562 printf(" %s _______ _____",
492 nr_counters == 1 ? " " : "______"); 563 nr_counters == 1 ? " " : "______");
493 if (verbose) 564 if (verbose)
494 printf(" ________________"); 565 printf(" ________________");
495 printf(" _______________\n\n"); 566 printf(" %-*.*s", sym_width, sym_width, graph_line);
567 printf(" %-*.*s", dso_width, dso_width, graph_line);
568 puts("\n");
496 569
497 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 570 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
498 struct symbol *sym; 571 struct symbol *sym;
499 double pcnt; 572 double pcnt;
500 573
501 syme = rb_entry(nd, struct sym_entry, rb_node); 574 syme = rb_entry(nd, struct sym_entry, rb_node);
502 sym = (struct symbol *)(syme + 1); 575 sym = sym_entry__symbol(syme);
503 576
504 if (++printed > print_entries || (int)syme->snap_count < count_filter) 577 if (++printed > print_entries || (int)syme->snap_count < count_filter)
505 continue; 578 continue;
@@ -508,17 +581,18 @@ static void print_sym_table(void)
508 sum_ksamples)); 581 sum_ksamples));
509 582
510 if (nr_counters == 1 || !display_weighted) 583 if (nr_counters == 1 || !display_weighted)
511 printf("%20.2f - ", syme->weight); 584 printf("%20.2f ", syme->weight);
512 else 585 else
513 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 586 printf("%9.1f %10ld ", syme->weight, syme->snap_count);
514 587
515 percent_color_fprintf(stdout, "%4.1f%%", pcnt); 588 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
516 if (verbose) 589 if (verbose)
517 printf(" - %016llx", sym->start); 590 printf(" %016llx", sym->start);
518 printf(" : %s", sym->name); 591 printf(" %-*.*s", sym_width, sym_width, sym->name);
519 if (sym->module) 592 printf(" %-*.*s\n", dso_width, dso_width,
520 printf("\t[%s]", sym->module->name); 593 dso_width >= syme->map->dso->long_name_len ?
521 printf("\n"); 594 syme->map->dso->long_name :
595 syme->map->dso->short_name);
522 } 596 }
523} 597}
524 598
@@ -565,10 +639,10 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
565 639
566 /* zero counters of active symbol */ 640 /* zero counters of active symbol */
567 if (syme) { 641 if (syme) {
568 pthread_mutex_lock(&syme->source_lock); 642 pthread_mutex_lock(&syme->src->lock);
569 __zero_source_counters(syme); 643 __zero_source_counters(syme);
570 *target = NULL; 644 *target = NULL;
571 pthread_mutex_unlock(&syme->source_lock); 645 pthread_mutex_unlock(&syme->src->lock);
572 } 646 }
573 647
574 fprintf(stdout, "\n%s: ", msg); 648 fprintf(stdout, "\n%s: ", msg);
@@ -584,7 +658,7 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
584 pthread_mutex_unlock(&active_symbols_lock); 658 pthread_mutex_unlock(&active_symbols_lock);
585 659
586 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 660 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
587 struct symbol *sym = (struct symbol *)(syme + 1); 661 struct symbol *sym = sym_entry__symbol(syme);
588 662
589 if (!strcmp(buf, sym->name)) { 663 if (!strcmp(buf, sym->name)) {
590 found = syme; 664 found = syme;
@@ -608,7 +682,7 @@ static void print_mapped_keys(void)
608 char *name = NULL; 682 char *name = NULL;
609 683
610 if (sym_filter_entry) { 684 if (sym_filter_entry) {
611 struct symbol *sym = (struct symbol *)(sym_filter_entry+1); 685 struct symbol *sym = sym_entry__symbol(sym_filter_entry);
612 name = sym->name; 686 name = sym->name;
613 } 687 }
614 688
@@ -621,7 +695,7 @@ static void print_mapped_keys(void)
621 695
622 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 696 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
623 697
624 if (vmlinux_name) { 698 if (symbol_conf.vmlinux_name) {
625 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 699 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
626 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 700 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
627 fprintf(stdout, "\t[S] stop annotation.\n"); 701 fprintf(stdout, "\t[S] stop annotation.\n");
@@ -630,6 +704,12 @@ static void print_mapped_keys(void)
630 if (nr_counters > 1) 704 if (nr_counters > 1)
631 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 705 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
632 706
707 fprintf(stdout,
708 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
709 hide_kernel_symbols ? "yes" : "no");
710 fprintf(stdout,
711 "\t[U] hide user symbols. \t(%s)\n",
712 hide_user_symbols ? "yes" : "no");
633 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); 713 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0);
634 fprintf(stdout, "\t[qQ] quit.\n"); 714 fprintf(stdout, "\t[qQ] quit.\n");
635} 715}
@@ -643,6 +723,8 @@ static int key_mapped(int c)
643 case 'z': 723 case 'z':
644 case 'q': 724 case 'q':
645 case 'Q': 725 case 'Q':
726 case 'K':
727 case 'U':
646 return 1; 728 return 1;
647 case 'E': 729 case 'E':
648 case 'w': 730 case 'w':
@@ -650,7 +732,7 @@ static int key_mapped(int c)
650 case 'F': 732 case 'F':
651 case 's': 733 case 's':
652 case 'S': 734 case 'S':
653 return vmlinux_name ? 1 : 0; 735 return symbol_conf.vmlinux_name ? 1 : 0;
654 default: 736 default:
655 break; 737 break;
656 } 738 }
@@ -686,9 +768,16 @@ static void handle_keypress(int c)
686 switch (c) { 768 switch (c) {
687 case 'd': 769 case 'd':
688 prompt_integer(&delay_secs, "Enter display delay"); 770 prompt_integer(&delay_secs, "Enter display delay");
771 if (delay_secs < 1)
772 delay_secs = 1;
689 break; 773 break;
690 case 'e': 774 case 'e':
691 prompt_integer(&print_entries, "Enter display entries (lines)"); 775 prompt_integer(&print_entries, "Enter display entries (lines)");
776 if (print_entries == 0) {
777 sig_winch_handler(SIGWINCH);
778 signal(SIGWINCH, sig_winch_handler);
779 } else
780 signal(SIGWINCH, SIG_DFL);
692 break; 781 break;
693 case 'E': 782 case 'E':
694 if (nr_counters > 1) { 783 if (nr_counters > 1) {
@@ -713,9 +802,14 @@ static void handle_keypress(int c)
713 case 'F': 802 case 'F':
714 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 803 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
715 break; 804 break;
805 case 'K':
806 hide_kernel_symbols = !hide_kernel_symbols;
807 break;
716 case 'q': 808 case 'q':
717 case 'Q': 809 case 'Q':
718 printf("exiting.\n"); 810 printf("exiting.\n");
811 if (dump_symtab)
812 dsos__fprintf(stderr);
719 exit(0); 813 exit(0);
720 case 's': 814 case 's':
721 prompt_symbol(&sym_filter_entry, "Enter details symbol"); 815 prompt_symbol(&sym_filter_entry, "Enter details symbol");
@@ -726,12 +820,15 @@ static void handle_keypress(int c)
726 else { 820 else {
727 struct sym_entry *syme = sym_filter_entry; 821 struct sym_entry *syme = sym_filter_entry;
728 822
729 pthread_mutex_lock(&syme->source_lock); 823 pthread_mutex_lock(&syme->src->lock);
730 sym_filter_entry = NULL; 824 sym_filter_entry = NULL;
731 __zero_source_counters(syme); 825 __zero_source_counters(syme);
732 pthread_mutex_unlock(&syme->source_lock); 826 pthread_mutex_unlock(&syme->src->lock);
733 } 827 }
734 break; 828 break;
829 case 'U':
830 hide_user_symbols = !hide_user_symbols;
831 break;
735 case 'w': 832 case 'w':
736 display_weighted = ~display_weighted; 833 display_weighted = ~display_weighted;
737 break; 834 break;
@@ -788,7 +885,7 @@ static const char *skip_symbols[] = {
788 NULL 885 NULL
789}; 886};
790 887
791static int symbol_filter(struct dso *self, struct symbol *sym) 888static int symbol_filter(struct map *map, struct symbol *sym)
792{ 889{
793 struct sym_entry *syme; 890 struct sym_entry *syme;
794 const char *name = sym->name; 891 const char *name = sym->name;
@@ -810,8 +907,9 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
810 strstr(name, "_text_end")) 907 strstr(name, "_text_end"))
811 return 1; 908 return 1;
812 909
813 syme = dso__sym_priv(self, sym); 910 syme = symbol__priv(sym);
814 pthread_mutex_init(&syme->source_lock, NULL); 911 syme->map = map;
912 syme->src = NULL;
815 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 913 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
816 sym_filter_entry = syme; 914 sym_filter_entry = syme;
817 915
@@ -822,75 +920,65 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
822 } 920 }
823 } 921 }
824 922
825 return 0; 923 if (!syme->skip)
826} 924 syme->name_len = strlen(sym->name);
827
828static int parse_symbols(void)
829{
830 struct rb_node *node;
831 struct symbol *sym;
832 int use_modules = vmlinux_name ? 1 : 0;
833
834 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
835 if (kernel_dso == NULL)
836 return -1;
837
838 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
839 goto out_delete_dso;
840
841 node = rb_first(&kernel_dso->syms);
842 sym = rb_entry(node, struct symbol, rb_node);
843 min_ip = sym->start;
844
845 node = rb_last(&kernel_dso->syms);
846 sym = rb_entry(node, struct symbol, rb_node);
847 max_ip = sym->end;
848
849 if (dump_symtab)
850 dso__fprintf(kernel_dso, stderr);
851 925
852 return 0; 926 return 0;
853
854out_delete_dso:
855 dso__delete(kernel_dso);
856 kernel_dso = NULL;
857 return -1;
858} 927}
859 928
860/* 929static void event__process_sample(const event_t *self, int counter)
861 * Binary search in the histogram table and record the hit:
862 */
863static void record_ip(u64 ip, int counter)
864{ 930{
865 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 931 u64 ip = self->ip.ip;
866 932 struct sym_entry *syme;
867 if (sym != NULL) { 933 struct addr_location al;
868 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 934 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
869 935
870 if (!syme->skip) { 936 switch (origin) {
871 syme->count[counter]++; 937 case PERF_RECORD_MISC_USER:
872 record_precise_ip(syme, counter, ip); 938 if (hide_user_symbols)
873 pthread_mutex_lock(&active_symbols_lock);
874 if (list_empty(&syme->node) || !syme->node.next)
875 __list_insert_active_sym(syme);
876 pthread_mutex_unlock(&active_symbols_lock);
877 return; 939 return;
878 } 940 break;
941 case PERF_RECORD_MISC_KERNEL:
942 if (hide_kernel_symbols)
943 return;
944 break;
945 default:
946 return;
879 } 947 }
880 948
881 samples--; 949 if (event__preprocess_sample(self, &al, symbol_filter) < 0 ||
950 al.sym == NULL)
951 return;
952
953 syme = symbol__priv(al.sym);
954 if (!syme->skip) {
955 syme->count[counter]++;
956 syme->origin = origin;
957 record_precise_ip(syme, counter, ip);
958 pthread_mutex_lock(&active_symbols_lock);
959 if (list_empty(&syme->node) || !syme->node.next)
960 __list_insert_active_sym(syme);
961 pthread_mutex_unlock(&active_symbols_lock);
962 if (origin == PERF_RECORD_MISC_USER)
963 ++userspace_samples;
964 ++samples;
965 }
882} 966}
883 967
884static void process_event(u64 ip, int counter, int user) 968static int event__process(event_t *event)
885{ 969{
886 samples++; 970 switch (event->header.type) {
887 971 case PERF_RECORD_COMM:
888 if (user) { 972 event__process_comm(event);
889 userspace_samples++; 973 break;
890 return; 974 case PERF_RECORD_MMAP:
975 event__process_mmap(event);
976 break;
977 default:
978 break;
891 } 979 }
892 980
893 record_ip(ip, counter); 981 return 0;
894} 982}
895 983
896struct mmap_data { 984struct mmap_data {
@@ -911,8 +999,6 @@ static unsigned int mmap_read_head(struct mmap_data *md)
911 return head; 999 return head;
912} 1000}
913 1001
914struct timeval last_read, this_read;
915
916static void mmap_read_counter(struct mmap_data *md) 1002static void mmap_read_counter(struct mmap_data *md)
917{ 1003{
918 unsigned int head = mmap_read_head(md); 1004 unsigned int head = mmap_read_head(md);
@@ -920,8 +1006,6 @@ static void mmap_read_counter(struct mmap_data *md)
920 unsigned char *data = md->base + page_size; 1006 unsigned char *data = md->base + page_size;
921 int diff; 1007 int diff;
922 1008
923 gettimeofday(&this_read, NULL);
924
925 /* 1009 /*
926 * If we're further behind than half the buffer, there's a chance 1010 * If we're further behind than half the buffer, there's a chance
927 * the writer will bite our tail and mess up the samples under us. 1011 * the writer will bite our tail and mess up the samples under us.
@@ -932,14 +1016,7 @@ static void mmap_read_counter(struct mmap_data *md)
932 */ 1016 */
933 diff = head - old; 1017 diff = head - old;
934 if (diff > md->mask / 2 || diff < 0) { 1018 if (diff > md->mask / 2 || diff < 0) {
935 struct timeval iv; 1019 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
936 unsigned long msecs;
937
938 timersub(&this_read, &last_read, &iv);
939 msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
940
941 fprintf(stderr, "WARNING: failed to keep up with mmap data."
942 " Last read %lu msecs ago.\n", msecs);
943 1020
944 /* 1021 /*
945 * head points to a known good entry, start there. 1022 * head points to a known good entry, start there.
@@ -947,8 +1024,6 @@ static void mmap_read_counter(struct mmap_data *md)
947 old = head; 1024 old = head;
948 } 1025 }
949 1026
950 last_read = this_read;
951
952 for (; old != head;) { 1027 for (; old != head;) {
953 event_t *event = (event_t *)&data[old & md->mask]; 1028 event_t *event = (event_t *)&data[old & md->mask];
954 1029
@@ -976,13 +1051,11 @@ static void mmap_read_counter(struct mmap_data *md)
976 event = &event_copy; 1051 event = &event_copy;
977 } 1052 }
978 1053
1054 if (event->header.type == PERF_RECORD_SAMPLE)
1055 event__process_sample(event, md->counter);
1056 else
1057 event__process(event);
979 old += size; 1058 old += size;
980
981 if (event->header.type == PERF_RECORD_SAMPLE) {
982 int user =
983 (event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_USER;
984 process_event(event->ip.ip, md->counter, user);
985 }
986 } 1059 }
987 1060
988 md->prev = old; 1061 md->prev = old;
@@ -1016,8 +1089,15 @@ static void start_counter(int i, int counter)
1016 attr = attrs + counter; 1089 attr = attrs + counter;
1017 1090
1018 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1091 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1019 attr->freq = freq; 1092
1093 if (freq) {
1094 attr->sample_type |= PERF_SAMPLE_PERIOD;
1095 attr->freq = 1;
1096 attr->sample_freq = freq;
1097 }
1098
1020 attr->inherit = (cpu < 0) && inherit; 1099 attr->inherit = (cpu < 0) && inherit;
1100 attr->mmap = 1;
1021 1101
1022try_again: 1102try_again:
1023 fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0); 1103 fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0);
@@ -1025,7 +1105,7 @@ try_again:
1025 if (fd[i][counter] < 0) { 1105 if (fd[i][counter] < 0) {
1026 int err = errno; 1106 int err = errno;
1027 1107
1028 if (err == EPERM) 1108 if (err == EPERM || err == EACCES)
1029 die("No permission - are you root?\n"); 1109 die("No permission - are you root?\n");
1030 /* 1110 /*
1031 * If it's cycles then fall back to hrtimer 1111 * If it's cycles then fall back to hrtimer
@@ -1076,6 +1156,11 @@ static int __cmd_top(void)
1076 int i, counter; 1156 int i, counter;
1077 int ret; 1157 int ret;
1078 1158
1159 if (target_pid != -1)
1160 event__synthesize_thread(target_pid, event__process);
1161 else
1162 event__synthesize_threads(event__process);
1163
1079 for (i = 0; i < nr_cpus; i++) { 1164 for (i = 0; i < nr_cpus; i++) {
1080 group_fd = -1; 1165 group_fd = -1;
1081 for (counter = 0; counter < nr_counters; counter++) 1166 for (counter = 0; counter < nr_counters; counter++)
@@ -1131,7 +1216,10 @@ static const struct option options[] = {
1131 "system-wide collection from all CPUs"), 1216 "system-wide collection from all CPUs"),
1132 OPT_INTEGER('C', "CPU", &profile_cpu, 1217 OPT_INTEGER('C', "CPU", &profile_cpu,
1133 "CPU to profile on"), 1218 "CPU to profile on"),
1134 OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"), 1219 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1220 "file", "vmlinux pathname"),
1221 OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
1222 "hide kernel symbols"),
1135 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1223 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
1136 "number of mmap data pages"), 1224 "number of mmap data pages"),
1137 OPT_INTEGER('r', "realtime", &realtime_prio, 1225 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -1154,6 +1242,8 @@ static const struct option options[] = {
1154 "profile at this frequency"), 1242 "profile at this frequency"),
1155 OPT_INTEGER('E', "entries", &print_entries, 1243 OPT_INTEGER('E', "entries", &print_entries,
1156 "display this many functions"), 1244 "display this many functions"),
1245 OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols,
1246 "hide user symbols"),
1157 OPT_BOOLEAN('v', "verbose", &verbose, 1247 OPT_BOOLEAN('v', "verbose", &verbose,
1158 "be more verbose (show counter open errors, etc)"), 1248 "be more verbose (show counter open errors, etc)"),
1159 OPT_END() 1249 OPT_END()
@@ -1163,19 +1253,12 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1163{ 1253{
1164 int counter; 1254 int counter;
1165 1255
1166 symbol__init();
1167
1168 page_size = sysconf(_SC_PAGE_SIZE); 1256 page_size = sysconf(_SC_PAGE_SIZE);
1169 1257
1170 argc = parse_options(argc, argv, options, top_usage, 0); 1258 argc = parse_options(argc, argv, options, top_usage, 0);
1171 if (argc) 1259 if (argc)
1172 usage_with_options(top_usage, options); 1260 usage_with_options(top_usage, options);
1173 1261
1174 if (freq) {
1175 default_interval = freq;
1176 freq = 1;
1177 }
1178
1179 /* CPU and PID are mutually exclusive */ 1262 /* CPU and PID are mutually exclusive */
1180 if (target_pid != -1 && profile_cpu != -1) { 1263 if (target_pid != -1 && profile_cpu != -1) {
1181 printf("WARNING: PID switch overriding CPU\n"); 1264 printf("WARNING: PID switch overriding CPU\n");
@@ -1186,13 +1269,31 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1186 if (!nr_counters) 1269 if (!nr_counters)
1187 nr_counters = 1; 1270 nr_counters = 1;
1188 1271
1272 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1273 (nr_counters + 1) * sizeof(unsigned long));
1274 if (symbol_conf.vmlinux_name == NULL)
1275 symbol_conf.try_vmlinux_path = true;
1276 if (symbol__init(&symbol_conf) < 0)
1277 return -1;
1278
1189 if (delay_secs < 1) 1279 if (delay_secs < 1)
1190 delay_secs = 1; 1280 delay_secs = 1;
1191 1281
1192 parse_symbols();
1193 parse_source(sym_filter_entry); 1282 parse_source(sym_filter_entry);
1194 1283
1195 /* 1284 /*
1285 * User specified count overrides default frequency.
1286 */
1287 if (default_interval)
1288 freq = 0;
1289 else if (freq) {
1290 default_interval = freq;
1291 } else {
1292 fprintf(stderr, "frequency and count are zero, aborting\n");
1293 exit(EXIT_FAILURE);
1294 }
1295
1296 /*
1196 * Fill in the ones not specifically initialized via -c: 1297 * Fill in the ones not specifically initialized via -c:
1197 */ 1298 */
1198 for (counter = 0; counter < nr_counters; counter++) { 1299 for (counter = 0; counter < nr_counters; counter++) {
@@ -1209,5 +1310,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1209 if (target_pid != -1 || profile_cpu != -1) 1310 if (target_pid != -1 || profile_cpu != -1)
1210 nr_cpus = 1; 1311 nr_cpus = 1;
1211 1312
1313 get_term_dimensions(&winsize);
1314 if (print_entries == 0) {
1315 update_print_entries(&winsize);
1316 signal(SIGWINCH, sig_winch_handler);
1317 }
1318
1212 return __cmd_top(); 1319 return __cmd_top();
1213} 1320}