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.c221
1 files changed, 121 insertions, 100 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ae15f046c405..1e67ab9c7ebc 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -21,6 +21,7 @@
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/color.h" 23#include "util/color.h"
24#include "util/evsel.h"
24#include "util/session.h" 25#include "util/session.h"
25#include "util/symbol.h" 26#include "util/symbol.h"
26#include "util/thread.h" 27#include "util/thread.h"
@@ -29,6 +30,7 @@
29#include "util/parse-options.h" 30#include "util/parse-options.h"
30#include "util/parse-events.h" 31#include "util/parse-events.h"
31#include "util/cpumap.h" 32#include "util/cpumap.h"
33#include "util/xyarray.h"
32 34
33#include "util/debug.h" 35#include "util/debug.h"
34 36
@@ -55,7 +57,7 @@
55#include <linux/unistd.h> 57#include <linux/unistd.h>
56#include <linux/types.h> 58#include <linux/types.h>
57 59
58static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 60#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
59 61
60static bool system_wide = false; 62static bool system_wide = false;
61 63
@@ -66,10 +68,9 @@ static int print_entries;
66 68
67static int target_pid = -1; 69static int target_pid = -1;
68static int target_tid = -1; 70static int target_tid = -1;
69static pid_t *all_tids = NULL; 71static struct thread_map *threads;
70static int thread_num = 0;
71static bool inherit = false; 72static bool inherit = false;
72static int nr_cpus = 0; 73static struct cpu_map *cpus;
73static int realtime_prio = 0; 74static int realtime_prio = 0;
74static bool group = false; 75static bool group = false;
75static unsigned int page_size; 76static unsigned int page_size;
@@ -100,6 +101,7 @@ struct sym_entry *sym_filter_entry = NULL;
100struct sym_entry *sym_filter_entry_sched = NULL; 101struct sym_entry *sym_filter_entry_sched = NULL;
101static int sym_pcnt_filter = 5; 102static int sym_pcnt_filter = 5;
102static int sym_counter = 0; 103static int sym_counter = 0;
104static struct perf_evsel *sym_evsel = NULL;
103static int display_weighted = -1; 105static int display_weighted = -1;
104static const char *cpu_list; 106static const char *cpu_list;
105 107
@@ -353,7 +355,7 @@ static void show_details(struct sym_entry *syme)
353 return; 355 return;
354 356
355 symbol = sym_entry__symbol(syme); 357 symbol = sym_entry__symbol(syme);
356 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 358 printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
357 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 359 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
358 360
359 pthread_mutex_lock(&syme->src->lock); 361 pthread_mutex_lock(&syme->src->lock);
@@ -460,7 +462,8 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
460static void print_sym_table(void) 462static void print_sym_table(void)
461{ 463{
462 int printed = 0, j; 464 int printed = 0, j;
463 int counter, snap = !display_weighted ? sym_counter : 0; 465 struct perf_evsel *counter;
466 int snap = !display_weighted ? sym_counter : 0;
464 float samples_per_sec = samples/delay_secs; 467 float samples_per_sec = samples/delay_secs;
465 float ksamples_per_sec = kernel_samples/delay_secs; 468 float ksamples_per_sec = kernel_samples/delay_secs;
466 float us_samples_per_sec = (us_samples)/delay_secs; 469 float us_samples_per_sec = (us_samples)/delay_secs;
@@ -532,7 +535,9 @@ static void print_sym_table(void)
532 } 535 }
533 536
534 if (nr_counters == 1 || !display_weighted) { 537 if (nr_counters == 1 || !display_weighted) {
535 printf("%Ld", (u64)attrs[0].sample_period); 538 struct perf_evsel *first;
539 first = list_entry(evsel_list.next, struct perf_evsel, node);
540 printf("%Ld", first->attr.sample_period);
536 if (freq) 541 if (freq)
537 printf("Hz "); 542 printf("Hz ");
538 else 543 else
@@ -540,9 +545,9 @@ static void print_sym_table(void)
540 } 545 }
541 546
542 if (!display_weighted) 547 if (!display_weighted)
543 printf("%s", event_name(sym_counter)); 548 printf("%s", event_name(sym_evsel));
544 else for (counter = 0; counter < nr_counters; counter++) { 549 else list_for_each_entry(counter, &evsel_list, node) {
545 if (counter) 550 if (counter->idx)
546 printf("/"); 551 printf("/");
547 552
548 printf("%s", event_name(counter)); 553 printf("%s", event_name(counter));
@@ -558,12 +563,12 @@ static void print_sym_table(void)
558 printf(" (all"); 563 printf(" (all");
559 564
560 if (cpu_list) 565 if (cpu_list)
561 printf(", CPU%s: %s)\n", nr_cpus > 1 ? "s" : "", cpu_list); 566 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
562 else { 567 else {
563 if (target_tid != -1) 568 if (target_tid != -1)
564 printf(")\n"); 569 printf(")\n");
565 else 570 else
566 printf(", %d CPU%s)\n", nr_cpus, nr_cpus > 1 ? "s" : ""); 571 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
567 } 572 }
568 573
569 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 574 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -739,7 +744,7 @@ static void print_mapped_keys(void)
739 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 744 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
740 745
741 if (nr_counters > 1) 746 if (nr_counters > 1)
742 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 747 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
743 748
744 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 749 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
745 750
@@ -826,19 +831,23 @@ static void handle_keypress(struct perf_session *session, int c)
826 break; 831 break;
827 case 'E': 832 case 'E':
828 if (nr_counters > 1) { 833 if (nr_counters > 1) {
829 int i;
830
831 fprintf(stderr, "\nAvailable events:"); 834 fprintf(stderr, "\nAvailable events:");
832 for (i = 0; i < nr_counters; i++) 835
833 fprintf(stderr, "\n\t%d %s", i, event_name(i)); 836 list_for_each_entry(sym_evsel, &evsel_list, node)
837 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
834 838
835 prompt_integer(&sym_counter, "Enter details event counter"); 839 prompt_integer(&sym_counter, "Enter details event counter");
836 840
837 if (sym_counter >= nr_counters) { 841 if (sym_counter >= nr_counters) {
838 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0)); 842 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
839 sym_counter = 0; 843 sym_counter = 0;
844 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
840 sleep(1); 845 sleep(1);
846 break;
841 } 847 }
848 list_for_each_entry(sym_evsel, &evsel_list, node)
849 if (sym_evsel->idx == sym_counter)
850 break;
842 } else sym_counter = 0; 851 } else sym_counter = 0;
843 break; 852 break;
844 case 'f': 853 case 'f':
@@ -978,7 +987,8 @@ static int symbol_filter(struct map *map, struct symbol *sym)
978 987
979static void event__process_sample(const event_t *self, 988static void event__process_sample(const event_t *self,
980 struct sample_data *sample, 989 struct sample_data *sample,
981 struct perf_session *session, int counter) 990 struct perf_session *session,
991 struct perf_evsel *evsel)
982{ 992{
983 u64 ip = self->ip.ip; 993 u64 ip = self->ip.ip;
984 struct sym_entry *syme; 994 struct sym_entry *syme;
@@ -1071,9 +1081,9 @@ static void event__process_sample(const event_t *self,
1071 1081
1072 syme = symbol__priv(al.sym); 1082 syme = symbol__priv(al.sym);
1073 if (!syme->skip) { 1083 if (!syme->skip) {
1074 syme->count[counter]++; 1084 syme->count[evsel->idx]++;
1075 syme->origin = origin; 1085 syme->origin = origin;
1076 record_precise_ip(syme, counter, ip); 1086 record_precise_ip(syme, evsel->idx, ip);
1077 pthread_mutex_lock(&active_symbols_lock); 1087 pthread_mutex_lock(&active_symbols_lock);
1078 if (list_empty(&syme->node) || !syme->node.next) 1088 if (list_empty(&syme->node) || !syme->node.next)
1079 __list_insert_active_sym(syme); 1089 __list_insert_active_sym(syme);
@@ -1082,12 +1092,24 @@ static void event__process_sample(const event_t *self,
1082} 1092}
1083 1093
1084struct mmap_data { 1094struct mmap_data {
1085 int counter;
1086 void *base; 1095 void *base;
1087 int mask; 1096 int mask;
1088 unsigned int prev; 1097 unsigned int prev;
1089}; 1098};
1090 1099
1100static 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
1107static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1108{
1109 xyarray__delete(evsel->priv);
1110 evsel->priv = NULL;
1111}
1112
1091static unsigned int mmap_read_head(struct mmap_data *md) 1113static unsigned int mmap_read_head(struct mmap_data *md)
1092{ 1114{
1093 struct perf_event_mmap_page *pc = md->base; 1115 struct perf_event_mmap_page *pc = md->base;
@@ -1100,8 +1122,11 @@ static unsigned int mmap_read_head(struct mmap_data *md)
1100} 1122}
1101 1123
1102static void perf_session__mmap_read_counter(struct perf_session *self, 1124static void perf_session__mmap_read_counter(struct perf_session *self,
1103 struct mmap_data *md) 1125 struct perf_evsel *evsel,
1126 int cpu, int thread_idx)
1104{ 1127{
1128 struct xyarray *mmap_array = evsel->priv;
1129 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1105 unsigned int head = mmap_read_head(md); 1130 unsigned int head = mmap_read_head(md);
1106 unsigned int old = md->prev; 1131 unsigned int old = md->prev;
1107 unsigned char *data = md->base + page_size; 1132 unsigned char *data = md->base + page_size;
@@ -1155,7 +1180,7 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1155 1180
1156 event__parse_sample(event, self, &sample); 1181 event__parse_sample(event, self, &sample);
1157 if (event->header.type == PERF_RECORD_SAMPLE) 1182 if (event->header.type == PERF_RECORD_SAMPLE)
1158 event__process_sample(event, &sample, self, md->counter); 1183 event__process_sample(event, &sample, self, evsel);
1159 else 1184 else
1160 event__process(event, &sample, self); 1185 event__process(event, &sample, self);
1161 old += size; 1186 old += size;
@@ -1165,36 +1190,39 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1165} 1190}
1166 1191
1167static struct pollfd *event_array; 1192static struct pollfd *event_array;
1168static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1169 1193
1170static void perf_session__mmap_read(struct perf_session *self) 1194static void perf_session__mmap_read(struct perf_session *self)
1171{ 1195{
1172 int i, counter, thread_index; 1196 struct perf_evsel *counter;
1197 int i, thread_index;
1173 1198
1174 for (i = 0; i < nr_cpus; i++) { 1199 for (i = 0; i < cpus->nr; i++) {
1175 for (counter = 0; counter < nr_counters; counter++) 1200 list_for_each_entry(counter, &evsel_list, node) {
1176 for (thread_index = 0; 1201 for (thread_index = 0;
1177 thread_index < thread_num; 1202 thread_index < threads->nr;
1178 thread_index++) { 1203 thread_index++) {
1179 perf_session__mmap_read_counter(self, 1204 perf_session__mmap_read_counter(self,
1180 &mmap_array[i][counter][thread_index]); 1205 counter, i, thread_index);
1181 } 1206 }
1207 }
1182 } 1208 }
1183} 1209}
1184 1210
1185int nr_poll; 1211int nr_poll;
1186int group_fd; 1212int group_fd;
1187 1213
1188static void start_counter(int i, int counter) 1214static void start_counter(int i, struct perf_evsel *evsel)
1189{ 1215{
1216 struct xyarray *mmap_array = evsel->priv;
1217 struct mmap_data *mm;
1190 struct perf_event_attr *attr; 1218 struct perf_event_attr *attr;
1191 int cpu = -1; 1219 int cpu = -1;
1192 int thread_index; 1220 int thread_index;
1193 1221
1194 if (target_tid == -1) 1222 if (target_tid == -1)
1195 cpu = cpumap[i]; 1223 cpu = cpus->map[i];
1196 1224
1197 attr = attrs + counter; 1225 attr = &evsel->attr;
1198 1226
1199 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1227 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1200 1228
@@ -1207,12 +1235,12 @@ static void start_counter(int i, int counter)
1207 attr->inherit = (cpu < 0) && inherit; 1235 attr->inherit = (cpu < 0) && inherit;
1208 attr->mmap = 1; 1236 attr->mmap = 1;
1209 1237
1210 for (thread_index = 0; thread_index < thread_num; thread_index++) { 1238 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
1211try_again: 1239try_again:
1212 fd[i][counter][thread_index] = sys_perf_event_open(attr, 1240 FD(evsel, i, thread_index) = sys_perf_event_open(attr,
1213 all_tids[thread_index], cpu, group_fd, 0); 1241 threads->map[thread_index], cpu, group_fd, 0);
1214 1242
1215 if (fd[i][counter][thread_index] < 0) { 1243 if (FD(evsel, i, thread_index) < 0) {
1216 int err = errno; 1244 int err = errno;
1217 1245
1218 if (err == EPERM || err == EACCES) 1246 if (err == EPERM || err == EACCES)
@@ -1236,29 +1264,29 @@ try_again:
1236 } 1264 }
1237 printf("\n"); 1265 printf("\n");
1238 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 1266 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
1239 fd[i][counter][thread_index], strerror(err)); 1267 FD(evsel, i, thread_index), strerror(err));
1240 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1268 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1241 exit(-1); 1269 exit(-1);
1242 } 1270 }
1243 assert(fd[i][counter][thread_index] >= 0); 1271 assert(FD(evsel, i, thread_index) >= 0);
1244 fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK); 1272 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1245 1273
1246 /* 1274 /*
1247 * First counter acts as the group leader: 1275 * First counter acts as the group leader:
1248 */ 1276 */
1249 if (group && group_fd == -1) 1277 if (group && group_fd == -1)
1250 group_fd = fd[i][counter][thread_index]; 1278 group_fd = FD(evsel, i, thread_index);
1251 1279
1252 event_array[nr_poll].fd = fd[i][counter][thread_index]; 1280 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1253 event_array[nr_poll].events = POLLIN; 1281 event_array[nr_poll].events = POLLIN;
1254 nr_poll++; 1282 nr_poll++;
1255 1283
1256 mmap_array[i][counter][thread_index].counter = counter; 1284 mm = xyarray__entry(mmap_array, i, thread_index);
1257 mmap_array[i][counter][thread_index].prev = 0; 1285 mm->prev = 0;
1258 mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1; 1286 mm->mask = mmap_pages*page_size - 1;
1259 mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, 1287 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1260 PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0); 1288 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1261 if (mmap_array[i][counter][thread_index].base == MAP_FAILED) 1289 if (mm->base == MAP_FAILED)
1262 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 1290 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1263 } 1291 }
1264} 1292}
@@ -1266,8 +1294,8 @@ try_again:
1266static int __cmd_top(void) 1294static int __cmd_top(void)
1267{ 1295{
1268 pthread_t thread; 1296 pthread_t thread;
1269 int i, counter; 1297 struct perf_evsel *counter;
1270 int ret; 1298 int i, ret;
1271 /* 1299 /*
1272 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1300 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1273 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1301 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
@@ -1281,9 +1309,9 @@ static int __cmd_top(void)
1281 else 1309 else
1282 event__synthesize_threads(event__process, session); 1310 event__synthesize_threads(event__process, session);
1283 1311
1284 for (i = 0; i < nr_cpus; i++) { 1312 for (i = 0; i < cpus->nr; i++) {
1285 group_fd = -1; 1313 group_fd = -1;
1286 for (counter = 0; counter < nr_counters; counter++) 1314 list_for_each_entry(counter, &evsel_list, node)
1287 start_counter(i, counter); 1315 start_counter(i, counter);
1288 } 1316 }
1289 1317
@@ -1372,8 +1400,8 @@ static const struct option options[] = {
1372 1400
1373int cmd_top(int argc, const char **argv, const char *prefix __used) 1401int cmd_top(int argc, const char **argv, const char *prefix __used)
1374{ 1402{
1375 int counter; 1403 struct perf_evsel *pos;
1376 int i,j; 1404 int status = -ENOMEM;
1377 1405
1378 page_size = sysconf(_SC_PAGE_SIZE); 1406 page_size = sysconf(_SC_PAGE_SIZE);
1379 1407
@@ -1381,34 +1409,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1381 if (argc) 1409 if (argc)
1382 usage_with_options(top_usage, options); 1410 usage_with_options(top_usage, options);
1383 1411
1384 if (target_pid != -1) { 1412 if (target_pid != -1)
1385 target_tid = target_pid; 1413 target_tid = target_pid;
1386 thread_num = find_all_tid(target_pid, &all_tids);
1387 if (thread_num <= 0) {
1388 fprintf(stderr, "Can't find all threads of pid %d\n",
1389 target_pid);
1390 usage_with_options(top_usage, options);
1391 }
1392 } else {
1393 all_tids=malloc(sizeof(pid_t));
1394 if (!all_tids)
1395 return -ENOMEM;
1396 1414
1397 all_tids[0] = target_tid; 1415 threads = thread_map__new(target_pid, target_tid);
1398 thread_num = 1; 1416 if (threads == NULL) {
1417 pr_err("Problems finding threads of monitor\n");
1418 usage_with_options(top_usage, options);
1399 } 1419 }
1400 1420
1401 for (i = 0; i < MAX_NR_CPUS; i++) { 1421 event_array = malloc((sizeof(struct pollfd) *
1402 for (j = 0; j < MAX_COUNTERS; j++) { 1422 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1403 fd[i][j] = malloc(sizeof(int)*thread_num);
1404 mmap_array[i][j] = zalloc(
1405 sizeof(struct mmap_data)*thread_num);
1406 if (!fd[i][j] || !mmap_array[i][j])
1407 return -ENOMEM;
1408 }
1409 }
1410 event_array = malloc(
1411 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
1412 if (!event_array) 1423 if (!event_array)
1413 return -ENOMEM; 1424 return -ENOMEM;
1414 1425
@@ -1419,15 +1430,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1419 cpu_list = NULL; 1430 cpu_list = NULL;
1420 } 1431 }
1421 1432
1422 if (!nr_counters) 1433 if (!nr_counters && perf_evsel_list__create_default() < 0) {
1423 nr_counters = 1; 1434 pr_err("Not enough memory for event selector list\n");
1424 1435 return -ENOMEM;
1425 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1436 }
1426 (nr_counters + 1) * sizeof(unsigned long));
1427
1428 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1429 if (symbol__init() < 0)
1430 return -1;
1431 1437
1432 if (delay_secs < 1) 1438 if (delay_secs < 1)
1433 delay_secs = 1; 1439 delay_secs = 1;
@@ -1444,23 +1450,33 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1444 exit(EXIT_FAILURE); 1450 exit(EXIT_FAILURE);
1445 } 1451 }
1446 1452
1447 /* 1453 if (target_tid != -1)
1448 * Fill in the ones not specifically initialized via -c: 1454 cpus = cpu_map__dummy_new();
1449 */ 1455 else
1450 for (counter = 0; counter < nr_counters; counter++) { 1456 cpus = cpu_map__new(cpu_list);
1451 if (attrs[counter].sample_period) 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)
1452 continue; 1469 continue;
1453 1470
1454 attrs[counter].sample_period = default_interval; 1471 pos->attr.sample_period = default_interval;
1455 } 1472 }
1456 1473
1457 if (target_tid != -1) 1474 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1458 nr_cpus = 1; 1475 (nr_counters + 1) * sizeof(unsigned long));
1459 else
1460 nr_cpus = read_cpu_map(cpu_list);
1461 1476
1462 if (nr_cpus < 1) 1477 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1463 usage_with_options(top_usage, options); 1478 if (symbol__init() < 0)
1479 return -1;
1464 1480
1465 get_term_dimensions(&winsize); 1481 get_term_dimensions(&winsize);
1466 if (print_entries == 0) { 1482 if (print_entries == 0) {
@@ -1468,5 +1484,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1468 signal(SIGWINCH, sig_winch_handler); 1484 signal(SIGWINCH, sig_winch_handler);
1469 } 1485 }
1470 1486
1471 return __cmd_top(); 1487 status = __cmd_top();
1488out_free_fd:
1489 list_for_each_entry(pos, &evsel_list, node)
1490 perf_evsel__free_mmap(pos);
1491
1492 return status;
1472} 1493}