Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
[pandora-kernel.git] / tools / perf / builtin-top.c
1 /*
2  * builtin-top.c
3  *
4  * Builtin top command: Display a continuously updated profile of
5  * any workload, CPU or specific PID.
6  *
7  * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
8  *
9  * Improvements and fixes by:
10  *
11  *   Arjan van de Ven <arjan@linux.intel.com>
12  *   Yanmin Zhang <yanmin.zhang@intel.com>
13  *   Wu Fengguang <fengguang.wu@intel.com>
14  *   Mike Galbraith <efault@gmx.de>
15  *   Paul Mackerras <paulus@samba.org>
16  *
17  * Released under the GPL v2. (and only v2, not any later version)
18  */
19 #include "builtin.h"
20
21 #include "perf.h"
22
23 #include "util/color.h"
24 #include "util/evsel.h"
25 #include "util/session.h"
26 #include "util/symbol.h"
27 #include "util/thread.h"
28 #include "util/util.h"
29 #include <linux/rbtree.h>
30 #include "util/parse-options.h"
31 #include "util/parse-events.h"
32 #include "util/cpumap.h"
33 #include "util/xyarray.h"
34
35 #include "util/debug.h"
36
37 #include <assert.h>
38 #include <fcntl.h>
39
40 #include <stdio.h>
41 #include <termios.h>
42 #include <unistd.h>
43
44 #include <errno.h>
45 #include <time.h>
46 #include <sched.h>
47 #include <pthread.h>
48
49 #include <sys/syscall.h>
50 #include <sys/ioctl.h>
51 #include <sys/poll.h>
52 #include <sys/prctl.h>
53 #include <sys/wait.h>
54 #include <sys/uio.h>
55 #include <sys/mman.h>
56
57 #include <linux/unistd.h>
58 #include <linux/types.h>
59
60 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
61
62 static bool                     system_wide                     =  false;
63
64 static int                      default_interval                =      0;
65
66 static int                      count_filter                    =      5;
67 static int                      print_entries;
68
69 static int                      target_pid                      =     -1;
70 static int                      target_tid                      =     -1;
71 static struct thread_map        *threads;
72 static bool                     inherit                         =  false;
73 static struct cpu_map           *cpus;
74 static int                      realtime_prio                   =      0;
75 static bool                     group                           =  false;
76 static unsigned int             page_size;
77 static unsigned int             mmap_pages                      =     16;
78 static int                      freq                            =   1000; /* 1 KHz */
79
80 static int                      delay_secs                      =      2;
81 static bool                     zero                            =  false;
82 static bool                     dump_symtab                     =  false;
83
84 static bool                     hide_kernel_symbols             =  false;
85 static bool                     hide_user_symbols               =  false;
86 static struct winsize           winsize;
87
88 /*
89  * Source
90  */
91
92 struct source_line {
93         u64                     eip;
94         unsigned long           count[MAX_COUNTERS];
95         char                    *line;
96         struct source_line      *next;
97 };
98
99 static const char               *sym_filter                     =   NULL;
100 struct sym_entry                *sym_filter_entry               =   NULL;
101 struct sym_entry                *sym_filter_entry_sched         =   NULL;
102 static int                      sym_pcnt_filter                 =      5;
103 static int                      sym_counter                     =      0;
104 static struct perf_evsel        *sym_evsel                      =   NULL;
105 static int                      display_weighted                =     -1;
106 static const char               *cpu_list;
107
108 /*
109  * Symbols
110  */
111
112 struct sym_entry_source {
113         struct source_line      *source;
114         struct source_line      *lines;
115         struct source_line      **lines_tail;
116         pthread_mutex_t         lock;
117 };
118
119 struct sym_entry {
120         struct rb_node          rb_node;
121         struct list_head        node;
122         unsigned long           snap_count;
123         double                  weight;
124         int                     skip;
125         u16                     name_len;
126         u8                      origin;
127         struct map              *map;
128         struct sym_entry_source *src;
129         unsigned long           count[0];
130 };
131
132 /*
133  * Source functions
134  */
135
136 static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
137 {
138        return ((void *)self) + symbol_conf.priv_size;
139 }
140
141 void get_term_dimensions(struct winsize *ws)
142 {
143         char *s = getenv("LINES");
144
145         if (s != NULL) {
146                 ws->ws_row = atoi(s);
147                 s = getenv("COLUMNS");
148                 if (s != NULL) {
149                         ws->ws_col = atoi(s);
150                         if (ws->ws_row && ws->ws_col)
151                                 return;
152                 }
153         }
154 #ifdef TIOCGWINSZ
155         if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
156             ws->ws_row && ws->ws_col)
157                 return;
158 #endif
159         ws->ws_row = 25;
160         ws->ws_col = 80;
161 }
162
163 static void update_print_entries(struct winsize *ws)
164 {
165         print_entries = ws->ws_row;
166
167         if (print_entries > 9)
168                 print_entries -= 9;
169 }
170
171 static void sig_winch_handler(int sig __used)
172 {
173         get_term_dimensions(&winsize);
174         update_print_entries(&winsize);
175 }
176
177 static int parse_source(struct sym_entry *syme)
178 {
179         struct symbol *sym;
180         struct sym_entry_source *source;
181         struct map *map;
182         FILE *file;
183         char command[PATH_MAX*2];
184         const char *path;
185         u64 len;
186
187         if (!syme)
188                 return -1;
189
190         sym = sym_entry__symbol(syme);
191         map = syme->map;
192
193         /*
194          * We can't annotate with just /proc/kallsyms
195          */
196         if (map->dso->origin == DSO__ORIG_KERNEL)
197                 return -1;
198
199         if (syme->src == NULL) {
200                 syme->src = zalloc(sizeof(*source));
201                 if (syme->src == NULL)
202                         return -1;
203                 pthread_mutex_init(&syme->src->lock, NULL);
204         }
205
206         source = syme->src;
207
208         if (source->lines) {
209                 pthread_mutex_lock(&source->lock);
210                 goto out_assign;
211         }
212         path = map->dso->long_name;
213
214         len = sym->end - sym->start;
215
216         sprintf(command,
217                 "objdump --start-address=%#0*Lx --stop-address=%#0*Lx -dS %s",
218                 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
219                 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
220
221         file = popen(command, "r");
222         if (!file)
223                 return -1;
224
225         pthread_mutex_lock(&source->lock);
226         source->lines_tail = &source->lines;
227         while (!feof(file)) {
228                 struct source_line *src;
229                 size_t dummy = 0;
230                 char *c, *sep;
231
232                 src = malloc(sizeof(struct source_line));
233                 assert(src != NULL);
234                 memset(src, 0, sizeof(struct source_line));
235
236                 if (getline(&src->line, &dummy, file) < 0)
237                         break;
238                 if (!src->line)
239                         break;
240
241                 c = strchr(src->line, '\n');
242                 if (c)
243                         *c = 0;
244
245                 src->next = NULL;
246                 *source->lines_tail = src;
247                 source->lines_tail = &src->next;
248
249                 src->eip = strtoull(src->line, &sep, 16);
250                 if (*sep == ':')
251                         src->eip = map__objdump_2ip(map, src->eip);
252                 else /* this line has no ip info (e.g. source line) */
253                         src->eip = 0;
254         }
255         pclose(file);
256 out_assign:
257         sym_filter_entry = syme;
258         pthread_mutex_unlock(&source->lock);
259         return 0;
260 }
261
262 static void __zero_source_counters(struct sym_entry *syme)
263 {
264         int i;
265         struct source_line *line;
266
267         line = syme->src->lines;
268         while (line) {
269                 for (i = 0; i < nr_counters; i++)
270                         line->count[i] = 0;
271                 line = line->next;
272         }
273 }
274
275 static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
276 {
277         struct source_line *line;
278
279         if (syme != sym_filter_entry)
280                 return;
281
282         if (pthread_mutex_trylock(&syme->src->lock))
283                 return;
284
285         if (syme->src == NULL || syme->src->source == NULL)
286                 goto out_unlock;
287
288         for (line = syme->src->lines; line; line = line->next) {
289                 /* skip lines without IP info */
290                 if (line->eip == 0)
291                         continue;
292                 if (line->eip == ip) {
293                         line->count[counter]++;
294                         break;
295                 }
296                 if (line->eip > ip)
297                         break;
298         }
299 out_unlock:
300         pthread_mutex_unlock(&syme->src->lock);
301 }
302
303 #define PATTERN_LEN             (BITS_PER_LONG / 4 + 2)
304
305 static void lookup_sym_source(struct sym_entry *syme)
306 {
307         struct symbol *symbol = sym_entry__symbol(syme);
308         struct source_line *line;
309         char pattern[PATTERN_LEN + 1];
310
311         sprintf(pattern, "%0*Lx <", BITS_PER_LONG / 4,
312                 map__rip_2objdump(syme->map, symbol->start));
313
314         pthread_mutex_lock(&syme->src->lock);
315         for (line = syme->src->lines; line; line = line->next) {
316                 if (memcmp(line->line, pattern, PATTERN_LEN) == 0) {
317                         syme->src->source = line;
318                         break;
319                 }
320         }
321         pthread_mutex_unlock(&syme->src->lock);
322 }
323
324 static void show_lines(struct source_line *queue, int count, int total)
325 {
326         int i;
327         struct source_line *line;
328
329         line = queue;
330         for (i = 0; i < count; i++) {
331                 float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
332
333                 printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line);
334                 line = line->next;
335         }
336 }
337
338 #define TRACE_COUNT     3
339
340 static void show_details(struct sym_entry *syme)
341 {
342         struct symbol *symbol;
343         struct source_line *line;
344         struct source_line *line_queue = NULL;
345         int displayed = 0;
346         int line_queue_count = 0, total = 0, more = 0;
347
348         if (!syme)
349                 return;
350
351         if (!syme->src->source)
352                 lookup_sym_source(syme);
353
354         if (!syme->src->source)
355                 return;
356
357         symbol = sym_entry__symbol(syme);
358         printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
359         printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
360
361         pthread_mutex_lock(&syme->src->lock);
362         line = syme->src->source;
363         while (line) {
364                 total += line->count[sym_counter];
365                 line = line->next;
366         }
367
368         line = syme->src->source;
369         while (line) {
370                 float pcnt = 0.0;
371
372                 if (!line_queue_count)
373                         line_queue = line;
374                 line_queue_count++;
375
376                 if (line->count[sym_counter])
377                         pcnt = 100.0 * line->count[sym_counter] / (float)total;
378                 if (pcnt >= (float)sym_pcnt_filter) {
379                         if (displayed <= print_entries)
380                                 show_lines(line_queue, line_queue_count, total);
381                         else more++;
382                         displayed += line_queue_count;
383                         line_queue_count = 0;
384                         line_queue = NULL;
385                 } else if (line_queue_count > TRACE_COUNT) {
386                         line_queue = line_queue->next;
387                         line_queue_count--;
388                 }
389
390                 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
391                 line = line->next;
392         }
393         pthread_mutex_unlock(&syme->src->lock);
394         if (more)
395                 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
396 }
397
398 /*
399  * Symbols will be added here in event__process_sample and will get out
400  * after decayed.
401  */
402 static LIST_HEAD(active_symbols);
403 static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER;
404
405 /*
406  * Ordering weight: count-1 * count-2 * ... / count-n
407  */
408 static double sym_weight(const struct sym_entry *sym)
409 {
410         double weight = sym->snap_count;
411         int counter;
412
413         if (!display_weighted)
414                 return weight;
415
416         for (counter = 1; counter < nr_counters-1; counter++)
417                 weight *= sym->count[counter];
418
419         weight /= (sym->count[counter] + 1);
420
421         return weight;
422 }
423
424 static long                     samples;
425 static long                     kernel_samples, us_samples;
426 static long                     exact_samples;
427 static long                     guest_us_samples, guest_kernel_samples;
428 static const char               CONSOLE_CLEAR[] = "\e[H\e[2J";
429
430 static void __list_insert_active_sym(struct sym_entry *syme)
431 {
432         list_add(&syme->node, &active_symbols);
433 }
434
435 static void list_remove_active_sym(struct sym_entry *syme)
436 {
437         pthread_mutex_lock(&active_symbols_lock);
438         list_del_init(&syme->node);
439         pthread_mutex_unlock(&active_symbols_lock);
440 }
441
442 static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
443 {
444         struct rb_node **p = &tree->rb_node;
445         struct rb_node *parent = NULL;
446         struct sym_entry *iter;
447
448         while (*p != NULL) {
449                 parent = *p;
450                 iter = rb_entry(parent, struct sym_entry, rb_node);
451
452                 if (se->weight > iter->weight)
453                         p = &(*p)->rb_left;
454                 else
455                         p = &(*p)->rb_right;
456         }
457
458         rb_link_node(&se->rb_node, parent, p);
459         rb_insert_color(&se->rb_node, tree);
460 }
461
462 static void print_sym_table(void)
463 {
464         int printed = 0, j;
465         struct perf_evsel *counter;
466         int snap = !display_weighted ? sym_counter : 0;
467         float samples_per_sec = samples/delay_secs;
468         float ksamples_per_sec = kernel_samples/delay_secs;
469         float us_samples_per_sec = (us_samples)/delay_secs;
470         float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs;
471         float guest_us_samples_per_sec = (guest_us_samples)/delay_secs;
472         float esamples_percent = (100.0*exact_samples)/samples;
473         float sum_ksamples = 0.0;
474         struct sym_entry *syme, *n;
475         struct rb_root tmp = RB_ROOT;
476         struct rb_node *nd;
477         int sym_width = 0, dso_width = 0, dso_short_width = 0;
478         const int win_width = winsize.ws_col - 1;
479
480         samples = us_samples = kernel_samples = exact_samples = 0;
481         guest_kernel_samples = guest_us_samples = 0;
482
483         /* Sort the active symbols */
484         pthread_mutex_lock(&active_symbols_lock);
485         syme = list_entry(active_symbols.next, struct sym_entry, node);
486         pthread_mutex_unlock(&active_symbols_lock);
487
488         list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
489                 syme->snap_count = syme->count[snap];
490                 if (syme->snap_count != 0) {
491
492                         if ((hide_user_symbols &&
493                              syme->origin == PERF_RECORD_MISC_USER) ||
494                             (hide_kernel_symbols &&
495                              syme->origin == PERF_RECORD_MISC_KERNEL)) {
496                                 list_remove_active_sym(syme);
497                                 continue;
498                         }
499                         syme->weight = sym_weight(syme);
500                         rb_insert_active_sym(&tmp, syme);
501                         sum_ksamples += syme->snap_count;
502
503                         for (j = 0; j < nr_counters; j++)
504                                 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
505                 } else
506                         list_remove_active_sym(syme);
507         }
508
509         puts(CONSOLE_CLEAR);
510
511         printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
512         if (!perf_guest) {
513                 printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%%"
514                         "  exact: %4.1f%% [",
515                         samples_per_sec,
516                         100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
517                                          samples_per_sec)),
518                         esamples_percent);
519         } else {
520                 printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%% us:%4.1f%%"
521                         " guest kernel:%4.1f%% guest us:%4.1f%%"
522                         " exact: %4.1f%% [",
523                         samples_per_sec,
524                         100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) /
525                                           samples_per_sec)),
526                         100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) /
527                                           samples_per_sec)),
528                         100.0 - (100.0 * ((samples_per_sec -
529                                                 guest_kernel_samples_per_sec) /
530                                           samples_per_sec)),
531                         100.0 - (100.0 * ((samples_per_sec -
532                                            guest_us_samples_per_sec) /
533                                           samples_per_sec)),
534                         esamples_percent);
535         }
536
537         if (nr_counters == 1 || !display_weighted) {
538                 struct perf_evsel *first;
539                 first = list_entry(evsel_list.next, struct perf_evsel, node);
540                 printf("%Ld", first->attr.sample_period);
541                 if (freq)
542                         printf("Hz ");
543                 else
544                         printf(" ");
545         }
546
547         if (!display_weighted)
548                 printf("%s", event_name(sym_evsel));
549         else list_for_each_entry(counter, &evsel_list, node) {
550                 if (counter->idx)
551                         printf("/");
552
553                 printf("%s", event_name(counter));
554         }
555
556         printf( "], ");
557
558         if (target_pid != -1)
559                 printf(" (target_pid: %d", target_pid);
560         else if (target_tid != -1)
561                 printf(" (target_tid: %d", target_tid);
562         else
563                 printf(" (all");
564
565         if (cpu_list)
566                 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
567         else {
568                 if (target_tid != -1)
569                         printf(")\n");
570                 else
571                         printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
572         }
573
574         printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
575
576         if (sym_filter_entry) {
577                 show_details(sym_filter_entry);
578                 return;
579         }
580
581         /*
582          * Find the longest symbol name that will be displayed
583          */
584         for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
585                 syme = rb_entry(nd, struct sym_entry, rb_node);
586                 if (++printed > print_entries ||
587                     (int)syme->snap_count < count_filter)
588                         continue;
589
590                 if (syme->map->dso->long_name_len > dso_width)
591                         dso_width = syme->map->dso->long_name_len;
592
593                 if (syme->map->dso->short_name_len > dso_short_width)
594                         dso_short_width = syme->map->dso->short_name_len;
595
596                 if (syme->name_len > sym_width)
597                         sym_width = syme->name_len;
598         }
599
600         printed = 0;
601
602         if (sym_width + dso_width > winsize.ws_col - 29) {
603                 dso_width = dso_short_width;
604                 if (sym_width + dso_width > winsize.ws_col - 29)
605                         sym_width = winsize.ws_col - dso_width - 29;
606         }
607         putchar('\n');
608         if (nr_counters == 1)
609                 printf("             samples  pcnt");
610         else
611                 printf("   weight    samples  pcnt");
612
613         if (verbose)
614                 printf("         RIP       ");
615         printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
616         printf("   %s    _______ _____",
617                nr_counters == 1 ? "      " : "______");
618         if (verbose)
619                 printf(" ________________");
620         printf(" %-*.*s", sym_width, sym_width, graph_line);
621         printf(" %-*.*s", dso_width, dso_width, graph_line);
622         puts("\n");
623
624         for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
625                 struct symbol *sym;
626                 double pcnt;
627
628                 syme = rb_entry(nd, struct sym_entry, rb_node);
629                 sym = sym_entry__symbol(syme);
630                 if (++printed > print_entries || (int)syme->snap_count < count_filter)
631                         continue;
632
633                 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
634                                          sum_ksamples));
635
636                 if (nr_counters == 1 || !display_weighted)
637                         printf("%20.2f ", syme->weight);
638                 else
639                         printf("%9.1f %10ld ", syme->weight, syme->snap_count);
640
641                 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
642                 if (verbose)
643                         printf(" %016llx", sym->start);
644                 printf(" %-*.*s", sym_width, sym_width, sym->name);
645                 printf(" %-*.*s\n", dso_width, dso_width,
646                        dso_width >= syme->map->dso->long_name_len ?
647                                         syme->map->dso->long_name :
648                                         syme->map->dso->short_name);
649         }
650 }
651
652 static void prompt_integer(int *target, const char *msg)
653 {
654         char *buf = malloc(0), *p;
655         size_t dummy = 0;
656         int tmp;
657
658         fprintf(stdout, "\n%s: ", msg);
659         if (getline(&buf, &dummy, stdin) < 0)
660                 return;
661
662         p = strchr(buf, '\n');
663         if (p)
664                 *p = 0;
665
666         p = buf;
667         while(*p) {
668                 if (!isdigit(*p))
669                         goto out_free;
670                 p++;
671         }
672         tmp = strtoul(buf, NULL, 10);
673         *target = tmp;
674 out_free:
675         free(buf);
676 }
677
678 static void prompt_percent(int *target, const char *msg)
679 {
680         int tmp = 0;
681
682         prompt_integer(&tmp, msg);
683         if (tmp >= 0 && tmp <= 100)
684                 *target = tmp;
685 }
686
687 static void prompt_symbol(struct sym_entry **target, const char *msg)
688 {
689         char *buf = malloc(0), *p;
690         struct sym_entry *syme = *target, *n, *found = NULL;
691         size_t dummy = 0;
692
693         /* zero counters of active symbol */
694         if (syme) {
695                 pthread_mutex_lock(&syme->src->lock);
696                 __zero_source_counters(syme);
697                 *target = NULL;
698                 pthread_mutex_unlock(&syme->src->lock);
699         }
700
701         fprintf(stdout, "\n%s: ", msg);
702         if (getline(&buf, &dummy, stdin) < 0)
703                 goto out_free;
704
705         p = strchr(buf, '\n');
706         if (p)
707                 *p = 0;
708
709         pthread_mutex_lock(&active_symbols_lock);
710         syme = list_entry(active_symbols.next, struct sym_entry, node);
711         pthread_mutex_unlock(&active_symbols_lock);
712
713         list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
714                 struct symbol *sym = sym_entry__symbol(syme);
715
716                 if (!strcmp(buf, sym->name)) {
717                         found = syme;
718                         break;
719                 }
720         }
721
722         if (!found) {
723                 fprintf(stderr, "Sorry, %s is not active.\n", buf);
724                 sleep(1);
725                 return;
726         } else
727                 parse_source(found);
728
729 out_free:
730         free(buf);
731 }
732
733 static void print_mapped_keys(void)
734 {
735         char *name = NULL;
736
737         if (sym_filter_entry) {
738                 struct symbol *sym = sym_entry__symbol(sym_filter_entry);
739                 name = sym->name;
740         }
741
742         fprintf(stdout, "\nMapped keys:\n");
743         fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", delay_secs);
744         fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", print_entries);
745
746         if (nr_counters > 1)
747                 fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(sym_evsel));
748
749         fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", count_filter);
750
751         fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
752         fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
753         fprintf(stdout, "\t[S]     stop annotation.\n");
754
755         if (nr_counters > 1)
756                 fprintf(stdout, "\t[w]     toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
757
758         fprintf(stdout,
759                 "\t[K]     hide kernel_symbols symbols.     \t(%s)\n",
760                 hide_kernel_symbols ? "yes" : "no");
761         fprintf(stdout,
762                 "\t[U]     hide user symbols.               \t(%s)\n",
763                 hide_user_symbols ? "yes" : "no");
764         fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", zero ? 1 : 0);
765         fprintf(stdout, "\t[qQ]    quit.\n");
766 }
767
768 static int key_mapped(int c)
769 {
770         switch (c) {
771                 case 'd':
772                 case 'e':
773                 case 'f':
774                 case 'z':
775                 case 'q':
776                 case 'Q':
777                 case 'K':
778                 case 'U':
779                 case 'F':
780                 case 's':
781                 case 'S':
782                         return 1;
783                 case 'E':
784                 case 'w':
785                         return nr_counters > 1 ? 1 : 0;
786                 default:
787                         break;
788         }
789
790         return 0;
791 }
792
793 static void handle_keypress(struct perf_session *session, int c)
794 {
795         if (!key_mapped(c)) {
796                 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
797                 struct termios tc, save;
798
799                 print_mapped_keys();
800                 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
801                 fflush(stdout);
802
803                 tcgetattr(0, &save);
804                 tc = save;
805                 tc.c_lflag &= ~(ICANON | ECHO);
806                 tc.c_cc[VMIN] = 0;
807                 tc.c_cc[VTIME] = 0;
808                 tcsetattr(0, TCSANOW, &tc);
809
810                 poll(&stdin_poll, 1, -1);
811                 c = getc(stdin);
812
813                 tcsetattr(0, TCSAFLUSH, &save);
814                 if (!key_mapped(c))
815                         return;
816         }
817
818         switch (c) {
819                 case 'd':
820                         prompt_integer(&delay_secs, "Enter display delay");
821                         if (delay_secs < 1)
822                                 delay_secs = 1;
823                         break;
824                 case 'e':
825                         prompt_integer(&print_entries, "Enter display entries (lines)");
826                         if (print_entries == 0) {
827                                 sig_winch_handler(SIGWINCH);
828                                 signal(SIGWINCH, sig_winch_handler);
829                         } else
830                                 signal(SIGWINCH, SIG_DFL);
831                         break;
832                 case 'E':
833                         if (nr_counters > 1) {
834                                 fprintf(stderr, "\nAvailable events:");
835
836                                 list_for_each_entry(sym_evsel, &evsel_list, node)
837                                         fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
838
839                                 prompt_integer(&sym_counter, "Enter details event counter");
840
841                                 if (sym_counter >= nr_counters) {
842                                         sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
843                                         sym_counter = 0;
844                                         fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
845                                         sleep(1);
846                                         break;
847                                 }
848                                 list_for_each_entry(sym_evsel, &evsel_list, node)
849                                         if (sym_evsel->idx == sym_counter)
850                                                 break;
851                         } else sym_counter = 0;
852                         break;
853                 case 'f':
854                         prompt_integer(&count_filter, "Enter display event count filter");
855                         break;
856                 case 'F':
857                         prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
858                         break;
859                 case 'K':
860                         hide_kernel_symbols = !hide_kernel_symbols;
861                         break;
862                 case 'q':
863                 case 'Q':
864                         printf("exiting.\n");
865                         if (dump_symtab)
866                                 perf_session__fprintf_dsos(session, stderr);
867                         exit(0);
868                 case 's':
869                         prompt_symbol(&sym_filter_entry, "Enter details symbol");
870                         break;
871                 case 'S':
872                         if (!sym_filter_entry)
873                                 break;
874                         else {
875                                 struct sym_entry *syme = sym_filter_entry;
876
877                                 pthread_mutex_lock(&syme->src->lock);
878                                 sym_filter_entry = NULL;
879                                 __zero_source_counters(syme);
880                                 pthread_mutex_unlock(&syme->src->lock);
881                         }
882                         break;
883                 case 'U':
884                         hide_user_symbols = !hide_user_symbols;
885                         break;
886                 case 'w':
887                         display_weighted = ~display_weighted;
888                         break;
889                 case 'z':
890                         zero = !zero;
891                         break;
892                 default:
893                         break;
894         }
895 }
896
897 static void *display_thread(void *arg __used)
898 {
899         struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
900         struct termios tc, save;
901         int delay_msecs, c;
902         struct perf_session *session = (struct perf_session *) arg;
903
904         tcgetattr(0, &save);
905         tc = save;
906         tc.c_lflag &= ~(ICANON | ECHO);
907         tc.c_cc[VMIN] = 0;
908         tc.c_cc[VTIME] = 0;
909
910 repeat:
911         delay_msecs = delay_secs * 1000;
912         tcsetattr(0, TCSANOW, &tc);
913         /* trash return*/
914         getc(stdin);
915
916         do {
917                 print_sym_table();
918         } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
919
920         c = getc(stdin);
921         tcsetattr(0, TCSAFLUSH, &save);
922
923         handle_keypress(session, c);
924         goto repeat;
925
926         return NULL;
927 }
928
929 /* Tag samples to be skipped. */
930 static const char *skip_symbols[] = {
931         "default_idle",
932         "cpu_idle",
933         "enter_idle",
934         "exit_idle",
935         "mwait_idle",
936         "mwait_idle_with_hints",
937         "poll_idle",
938         "ppc64_runlatch_off",
939         "pseries_dedicated_idle_sleep",
940         NULL
941 };
942
943 static int symbol_filter(struct map *map, struct symbol *sym)
944 {
945         struct sym_entry *syme;
946         const char *name = sym->name;
947         int i;
948
949         /*
950          * ppc64 uses function descriptors and appends a '.' to the
951          * start of every instruction address. Remove it.
952          */
953         if (name[0] == '.')
954                 name++;
955
956         if (!strcmp(name, "_text") ||
957             !strcmp(name, "_etext") ||
958             !strcmp(name, "_sinittext") ||
959             !strncmp("init_module", name, 11) ||
960             !strncmp("cleanup_module", name, 14) ||
961             strstr(name, "_text_start") ||
962             strstr(name, "_text_end"))
963                 return 1;
964
965         syme = symbol__priv(sym);
966         syme->map = map;
967         syme->src = NULL;
968
969         if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
970                 /* schedule initial sym_filter_entry setup */
971                 sym_filter_entry_sched = syme;
972                 sym_filter = NULL;
973         }
974
975         for (i = 0; skip_symbols[i]; i++) {
976                 if (!strcmp(skip_symbols[i], name)) {
977                         syme->skip = 1;
978                         break;
979                 }
980         }
981
982         if (!syme->skip)
983                 syme->name_len = strlen(sym->name);
984
985         return 0;
986 }
987
988 static void event__process_sample(const event_t *self,
989                                   struct sample_data *sample,
990                                   struct perf_session *session,
991                                   struct perf_evsel *evsel)
992 {
993         u64 ip = self->ip.ip;
994         struct sym_entry *syme;
995         struct addr_location al;
996         struct machine *machine;
997         u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
998
999         ++samples;
1000
1001         switch (origin) {
1002         case PERF_RECORD_MISC_USER:
1003                 ++us_samples;
1004                 if (hide_user_symbols)
1005                         return;
1006                 machine = perf_session__find_host_machine(session);
1007                 break;
1008         case PERF_RECORD_MISC_KERNEL:
1009                 ++kernel_samples;
1010                 if (hide_kernel_symbols)
1011                         return;
1012                 machine = perf_session__find_host_machine(session);
1013                 break;
1014         case PERF_RECORD_MISC_GUEST_KERNEL:
1015                 ++guest_kernel_samples;
1016                 machine = perf_session__find_machine(session, self->ip.pid);
1017                 break;
1018         case PERF_RECORD_MISC_GUEST_USER:
1019                 ++guest_us_samples;
1020                 /*
1021                  * TODO: we don't process guest user from host side
1022                  * except simple counting.
1023                  */
1024                 return;
1025         default:
1026                 return;
1027         }
1028
1029         if (!machine && perf_guest) {
1030                 pr_err("Can't find guest [%d]'s kernel information\n",
1031                         self->ip.pid);
1032                 return;
1033         }
1034
1035         if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1036                 exact_samples++;
1037
1038         if (event__preprocess_sample(self, session, &al, sample,
1039                                      symbol_filter) < 0 ||
1040             al.filtered)
1041                 return;
1042
1043         if (al.sym == NULL) {
1044                 /*
1045                  * As we do lazy loading of symtabs we only will know if the
1046                  * specified vmlinux file is invalid when we actually have a
1047                  * hit in kernel space and then try to load it. So if we get
1048                  * here and there are _no_ symbols in the DSO backing the
1049                  * kernel map, bail out.
1050                  *
1051                  * We may never get here, for instance, if we use -K/
1052                  * --hide-kernel-symbols, even if the user specifies an
1053                  * invalid --vmlinux ;-)
1054                  */
1055                 if (al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
1056                     RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
1057                         pr_err("The %s file can't be used\n",
1058                                symbol_conf.vmlinux_name);
1059                         exit(1);
1060                 }
1061
1062                 return;
1063         }
1064
1065         /* let's see, whether we need to install initial sym_filter_entry */
1066         if (sym_filter_entry_sched) {
1067                 sym_filter_entry = sym_filter_entry_sched;
1068                 sym_filter_entry_sched = NULL;
1069                 if (parse_source(sym_filter_entry) < 0) {
1070                         struct symbol *sym = sym_entry__symbol(sym_filter_entry);
1071
1072                         pr_err("Can't annotate %s", sym->name);
1073                         if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
1074                                 pr_err(": No vmlinux file was found in the path:\n");
1075                                 machine__fprintf_vmlinux_path(machine, stderr);
1076                         } else
1077                                 pr_err(".\n");
1078                         exit(1);
1079                 }
1080         }
1081
1082         syme = symbol__priv(al.sym);
1083         if (!syme->skip) {
1084                 syme->count[evsel->idx]++;
1085                 syme->origin = origin;
1086                 record_precise_ip(syme, evsel->idx, ip);
1087                 pthread_mutex_lock(&active_symbols_lock);
1088                 if (list_empty(&syme->node) || !syme->node.next)
1089                         __list_insert_active_sym(syme);
1090                 pthread_mutex_unlock(&active_symbols_lock);
1091         }
1092 }
1093
1094 struct mmap_data {
1095         void                    *base;
1096         int                     mask;
1097         unsigned int            prev;
1098 };
1099
1100 static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1101                                              int ncpus, int nthreads)
1102 {
1103         evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1104         return evsel->priv != NULL ? 0 : -ENOMEM;
1105 }
1106
1107 static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1108 {
1109         xyarray__delete(evsel->priv);
1110         evsel->priv = NULL;
1111 }
1112
1113 static unsigned int mmap_read_head(struct mmap_data *md)
1114 {
1115         struct perf_event_mmap_page *pc = md->base;
1116         int head;
1117
1118         head = pc->data_head;
1119         rmb();
1120
1121         return head;
1122 }
1123
1124 static void perf_session__mmap_read_counter(struct perf_session *self,
1125                                             struct perf_evsel *evsel,
1126                                             int cpu, int thread_idx)
1127 {
1128         struct xyarray *mmap_array = evsel->priv;
1129         struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1130         unsigned int head = mmap_read_head(md);
1131         unsigned int old = md->prev;
1132         unsigned char *data = md->base + page_size;
1133         struct sample_data sample;
1134         int diff;
1135
1136         /*
1137          * If we're further behind than half the buffer, there's a chance
1138          * the writer will bite our tail and mess up the samples under us.
1139          *
1140          * If we somehow ended up ahead of the head, we got messed up.
1141          *
1142          * In either case, truncate and restart at head.
1143          */
1144         diff = head - old;
1145         if (diff > md->mask / 2 || diff < 0) {
1146                 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
1147
1148                 /*
1149                  * head points to a known good entry, start there.
1150                  */
1151                 old = head;
1152         }
1153
1154         for (; old != head;) {
1155                 event_t *event = (event_t *)&data[old & md->mask];
1156
1157                 event_t event_copy;
1158
1159                 size_t size = event->header.size;
1160
1161                 /*
1162                  * Event straddles the mmap boundary -- header should always
1163                  * be inside due to u64 alignment of output.
1164                  */
1165                 if ((old & md->mask) + size != ((old + size) & md->mask)) {
1166                         unsigned int offset = old;
1167                         unsigned int len = min(sizeof(*event), size), cpy;
1168                         void *dst = &event_copy;
1169
1170                         do {
1171                                 cpy = min(md->mask + 1 - (offset & md->mask), len);
1172                                 memcpy(dst, &data[offset & md->mask], cpy);
1173                                 offset += cpy;
1174                                 dst += cpy;
1175                                 len -= cpy;
1176                         } while (len);
1177
1178                         event = &event_copy;
1179                 }
1180
1181                 event__parse_sample(event, self, &sample);
1182                 if (event->header.type == PERF_RECORD_SAMPLE)
1183                         event__process_sample(event, &sample, self, evsel);
1184                 else
1185                         event__process(event, &sample, self);
1186                 old += size;
1187         }
1188
1189         md->prev = old;
1190 }
1191
1192 static struct pollfd *event_array;
1193
1194 static void perf_session__mmap_read(struct perf_session *self)
1195 {
1196         struct perf_evsel *counter;
1197         int i, thread_index;
1198
1199         for (i = 0; i < cpus->nr; i++) {
1200                 list_for_each_entry(counter, &evsel_list, node) {
1201                         for (thread_index = 0;
1202                                 thread_index < threads->nr;
1203                                 thread_index++) {
1204                                 perf_session__mmap_read_counter(self,
1205                                         counter, i, thread_index);
1206                         }
1207                 }
1208         }
1209 }
1210
1211 int nr_poll;
1212 int group_fd;
1213
1214 static void start_counter(int i, struct perf_evsel *evsel)
1215 {
1216         struct xyarray *mmap_array = evsel->priv;
1217         struct mmap_data *mm;
1218         struct perf_event_attr *attr;
1219         int cpu = -1;
1220         int thread_index;
1221
1222         if (target_tid == -1)
1223                 cpu = cpus->map[i];
1224
1225         attr = &evsel->attr;
1226
1227         attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1228
1229         if (freq) {
1230                 attr->sample_type       |= PERF_SAMPLE_PERIOD;
1231                 attr->freq              = 1;
1232                 attr->sample_freq       = freq;
1233         }
1234
1235         attr->inherit           = (cpu < 0) && inherit;
1236         attr->mmap              = 1;
1237
1238         for (thread_index = 0; thread_index < threads->nr; thread_index++) {
1239 try_again:
1240                 FD(evsel, i, thread_index) = sys_perf_event_open(attr,
1241                                 threads->map[thread_index], cpu, group_fd, 0);
1242
1243                 if (FD(evsel, i, thread_index) < 0) {
1244                         int err = errno;
1245
1246                         if (err == EPERM || err == EACCES)
1247                                 die("Permission error - are you root?\n"
1248                                         "\t Consider tweaking"
1249                                         " /proc/sys/kernel/perf_event_paranoid.\n");
1250                         /*
1251                          * If it's cycles then fall back to hrtimer
1252                          * based cpu-clock-tick sw counter, which
1253                          * is always available even if no PMU support:
1254                          */
1255                         if (attr->type == PERF_TYPE_HARDWARE
1256                                         && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
1257
1258                                 if (verbose)
1259                                         warning(" ... trying to fall back to cpu-clock-ticks\n");
1260
1261                                 attr->type = PERF_TYPE_SOFTWARE;
1262                                 attr->config = PERF_COUNT_SW_CPU_CLOCK;
1263                                 goto try_again;
1264                         }
1265                         printf("\n");
1266                         error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
1267                                         FD(evsel, i, thread_index), strerror(err));
1268                         die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1269                         exit(-1);
1270                 }
1271                 assert(FD(evsel, i, thread_index) >= 0);
1272                 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1273
1274                 /*
1275                  * First counter acts as the group leader:
1276                  */
1277                 if (group && group_fd == -1)
1278                         group_fd = FD(evsel, i, thread_index);
1279
1280                 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1281                 event_array[nr_poll].events = POLLIN;
1282                 nr_poll++;
1283
1284                 mm = xyarray__entry(mmap_array, i, thread_index);
1285                 mm->prev = 0;
1286                 mm->mask = mmap_pages*page_size - 1;
1287                 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1288                                 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1289                 if (mm->base == MAP_FAILED)
1290                         die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1291         }
1292 }
1293
1294 static int __cmd_top(void)
1295 {
1296         pthread_t thread;
1297         struct perf_evsel *counter;
1298         int i, ret;
1299         /*
1300          * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1301          * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1302          */
1303         struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
1304         if (session == NULL)
1305                 return -ENOMEM;
1306
1307         if (target_tid != -1)
1308                 event__synthesize_thread(target_tid, event__process, session);
1309         else
1310                 event__synthesize_threads(event__process, session);
1311
1312         for (i = 0; i < cpus->nr; i++) {
1313                 group_fd = -1;
1314                 list_for_each_entry(counter, &evsel_list, node)
1315                         start_counter(i, counter);
1316         }
1317
1318         /* Wait for a minimal set of events before starting the snapshot */
1319         poll(&event_array[0], nr_poll, 100);
1320
1321         perf_session__mmap_read(session);
1322
1323         if (pthread_create(&thread, NULL, display_thread, session)) {
1324                 printf("Could not create display thread.\n");
1325                 exit(-1);
1326         }
1327
1328         if (realtime_prio) {
1329                 struct sched_param param;
1330
1331                 param.sched_priority = realtime_prio;
1332                 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
1333                         printf("Could not set realtime priority.\n");
1334                         exit(-1);
1335                 }
1336         }
1337
1338         while (1) {
1339                 int hits = samples;
1340
1341                 perf_session__mmap_read(session);
1342
1343                 if (hits == samples)
1344                         ret = poll(event_array, nr_poll, 100);
1345         }
1346
1347         return 0;
1348 }
1349
1350 static const char * const top_usage[] = {
1351         "perf top [<options>]",
1352         NULL
1353 };
1354
1355 static const struct option options[] = {
1356         OPT_CALLBACK('e', "event", NULL, "event",
1357                      "event selector. use 'perf list' to list available events",
1358                      parse_events),
1359         OPT_INTEGER('c', "count", &default_interval,
1360                     "event period to sample"),
1361         OPT_INTEGER('p', "pid", &target_pid,
1362                     "profile events on existing process id"),
1363         OPT_INTEGER('t', "tid", &target_tid,
1364                     "profile events on existing thread id"),
1365         OPT_BOOLEAN('a', "all-cpus", &system_wide,
1366                             "system-wide collection from all CPUs"),
1367         OPT_STRING('C', "cpu", &cpu_list, "cpu",
1368                     "list of cpus to monitor"),
1369         OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1370                    "file", "vmlinux pathname"),
1371         OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
1372                     "hide kernel symbols"),
1373         OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
1374         OPT_INTEGER('r', "realtime", &realtime_prio,
1375                     "collect data with this RT SCHED_FIFO priority"),
1376         OPT_INTEGER('d', "delay", &delay_secs,
1377                     "number of seconds to delay between refreshes"),
1378         OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
1379                             "dump the symbol table used for profiling"),
1380         OPT_INTEGER('f', "count-filter", &count_filter,
1381                     "only display functions with more events than this"),
1382         OPT_BOOLEAN('g', "group", &group,
1383                             "put the counters into a counter group"),
1384         OPT_BOOLEAN('i', "inherit", &inherit,
1385                     "child tasks inherit counters"),
1386         OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
1387                     "symbol to annotate"),
1388         OPT_BOOLEAN('z', "zero", &zero,
1389                     "zero history across updates"),
1390         OPT_INTEGER('F', "freq", &freq,
1391                     "profile at this frequency"),
1392         OPT_INTEGER('E', "entries", &print_entries,
1393                     "display this many functions"),
1394         OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols,
1395                     "hide user symbols"),
1396         OPT_INCR('v', "verbose", &verbose,
1397                     "be more verbose (show counter open errors, etc)"),
1398         OPT_END()
1399 };
1400
1401 int cmd_top(int argc, const char **argv, const char *prefix __used)
1402 {
1403         struct perf_evsel *pos;
1404         int status = -ENOMEM;
1405
1406         page_size = sysconf(_SC_PAGE_SIZE);
1407
1408         argc = parse_options(argc, argv, options, top_usage, 0);
1409         if (argc)
1410                 usage_with_options(top_usage, options);
1411
1412         if (target_pid != -1)
1413                 target_tid = target_pid;
1414
1415         threads = thread_map__new(target_pid, target_tid);
1416         if (threads == NULL) {
1417                 pr_err("Problems finding threads of monitor\n");
1418                 usage_with_options(top_usage, options);
1419         }
1420
1421         event_array = malloc((sizeof(struct pollfd) *
1422                               MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1423         if (!event_array)
1424                 return -ENOMEM;
1425
1426         /* CPU and PID are mutually exclusive */
1427         if (target_tid > 0 && cpu_list) {
1428                 printf("WARNING: PID switch overriding CPU\n");
1429                 sleep(1);
1430                 cpu_list = NULL;
1431         }
1432
1433         if (!nr_counters && perf_evsel_list__create_default() < 0) {
1434                 pr_err("Not enough memory for event selector list\n");
1435                 return -ENOMEM;
1436         }
1437
1438         if (delay_secs < 1)
1439                 delay_secs = 1;
1440
1441         /*
1442          * User specified count overrides default frequency.
1443          */
1444         if (default_interval)
1445                 freq = 0;
1446         else if (freq) {
1447                 default_interval = freq;
1448         } else {
1449                 fprintf(stderr, "frequency and count are zero, aborting\n");
1450                 exit(EXIT_FAILURE);
1451         }
1452
1453         if (target_tid != -1)
1454                 cpus = cpu_map__dummy_new();
1455         else
1456                 cpus = cpu_map__new(cpu_list);
1457
1458         if (cpus == NULL)
1459                 usage_with_options(top_usage, options);
1460
1461         list_for_each_entry(pos, &evsel_list, node) {
1462                 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
1463                     perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1464                         goto out_free_fd;
1465                 /*
1466                  * Fill in the ones not specifically initialized via -c:
1467                  */
1468                 if (pos->attr.sample_period)
1469                         continue;
1470
1471                 pos->attr.sample_period = default_interval;
1472         }
1473
1474         sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
1475
1476         symbol_conf.priv_size = (sizeof(struct sym_entry) +
1477                                  (nr_counters + 1) * sizeof(unsigned long));
1478
1479         symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1480         if (symbol__init() < 0)
1481                 return -1;
1482
1483         get_term_dimensions(&winsize);
1484         if (print_entries == 0) {
1485                 update_print_entries(&winsize);
1486                 signal(SIGWINCH, sig_winch_handler);
1487         }
1488
1489         status = __cmd_top();
1490 out_free_fd:
1491         list_for_each_entry(pos, &evsel_list, node)
1492                 perf_evsel__free_mmap(pos);
1493         perf_evsel_list__delete();
1494
1495         return status;
1496 }