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.c283
1 files changed, 85 insertions, 198 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b6998e055767..ce2e50c891c7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -21,10 +21,12 @@
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/color.h" 23#include "util/color.h"
24#include "util/evlist.h"
24#include "util/evsel.h" 25#include "util/evsel.h"
25#include "util/session.h" 26#include "util/session.h"
26#include "util/symbol.h" 27#include "util/symbol.h"
27#include "util/thread.h" 28#include "util/thread.h"
29#include "util/thread_map.h"
28#include "util/util.h" 30#include "util/util.h"
29#include <linux/rbtree.h> 31#include <linux/rbtree.h>
30#include "util/parse-options.h" 32#include "util/parse-options.h"
@@ -60,6 +62,8 @@
60 62
61#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 63#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
62 64
65struct perf_evlist *evsel_list;
66
63static bool system_wide = false; 67static bool system_wide = false;
64 68
65static int default_interval = 0; 69static int default_interval = 0;
@@ -75,7 +79,7 @@ static struct cpu_map *cpus;
75static int realtime_prio = 0; 79static int realtime_prio = 0;
76static bool group = false; 80static bool group = false;
77static unsigned int page_size; 81static unsigned int page_size;
78static unsigned int mmap_pages = 16; 82static unsigned int mmap_pages = 128;
79static int freq = 1000; /* 1 KHz */ 83static int freq = 1000; /* 1 KHz */
80 84
81static int delay_secs = 2; 85static int delay_secs = 2;
@@ -267,7 +271,7 @@ static void __zero_source_counters(struct sym_entry *syme)
267 271
268 line = syme->src->lines; 272 line = syme->src->lines;
269 while (line) { 273 while (line) {
270 for (i = 0; i < nr_counters; i++) 274 for (i = 0; i < evsel_list->nr_entries; i++)
271 line->count[i] = 0; 275 line->count[i] = 0;
272 line = line->next; 276 line = line->next;
273 } 277 }
@@ -414,7 +418,7 @@ static double sym_weight(const struct sym_entry *sym)
414 if (!display_weighted) 418 if (!display_weighted)
415 return weight; 419 return weight;
416 420
417 for (counter = 1; counter < nr_counters-1; counter++) 421 for (counter = 1; counter < evsel_list->nr_entries - 1; counter++)
418 weight *= sym->count[counter]; 422 weight *= sym->count[counter];
419 423
420 weight /= (sym->count[counter] + 1); 424 weight /= (sym->count[counter] + 1);
@@ -501,7 +505,7 @@ static void print_sym_table(void)
501 rb_insert_active_sym(&tmp, syme); 505 rb_insert_active_sym(&tmp, syme);
502 sum_ksamples += syme->snap_count; 506 sum_ksamples += syme->snap_count;
503 507
504 for (j = 0; j < nr_counters; j++) 508 for (j = 0; j < evsel_list->nr_entries; j++)
505 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; 509 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
506 } else 510 } else
507 list_remove_active_sym(syme); 511 list_remove_active_sym(syme);
@@ -535,9 +539,9 @@ static void print_sym_table(void)
535 esamples_percent); 539 esamples_percent);
536 } 540 }
537 541
538 if (nr_counters == 1 || !display_weighted) { 542 if (evsel_list->nr_entries == 1 || !display_weighted) {
539 struct perf_evsel *first; 543 struct perf_evsel *first;
540 first = list_entry(evsel_list.next, struct perf_evsel, node); 544 first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
541 printf("%" PRIu64, (uint64_t)first->attr.sample_period); 545 printf("%" PRIu64, (uint64_t)first->attr.sample_period);
542 if (freq) 546 if (freq)
543 printf("Hz "); 547 printf("Hz ");
@@ -547,7 +551,7 @@ static void print_sym_table(void)
547 551
548 if (!display_weighted) 552 if (!display_weighted)
549 printf("%s", event_name(sym_evsel)); 553 printf("%s", event_name(sym_evsel));
550 else list_for_each_entry(counter, &evsel_list, node) { 554 else list_for_each_entry(counter, &evsel_list->entries, node) {
551 if (counter->idx) 555 if (counter->idx)
552 printf("/"); 556 printf("/");
553 557
@@ -606,7 +610,7 @@ static void print_sym_table(void)
606 sym_width = winsize.ws_col - dso_width - 29; 610 sym_width = winsize.ws_col - dso_width - 29;
607 } 611 }
608 putchar('\n'); 612 putchar('\n');
609 if (nr_counters == 1) 613 if (evsel_list->nr_entries == 1)
610 printf(" samples pcnt"); 614 printf(" samples pcnt");
611 else 615 else
612 printf(" weight samples pcnt"); 616 printf(" weight samples pcnt");
@@ -615,7 +619,7 @@ static void print_sym_table(void)
615 printf(" RIP "); 619 printf(" RIP ");
616 printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); 620 printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
617 printf(" %s _______ _____", 621 printf(" %s _______ _____",
618 nr_counters == 1 ? " " : "______"); 622 evsel_list->nr_entries == 1 ? " " : "______");
619 if (verbose) 623 if (verbose)
620 printf(" ________________"); 624 printf(" ________________");
621 printf(" %-*.*s", sym_width, sym_width, graph_line); 625 printf(" %-*.*s", sym_width, sym_width, graph_line);
@@ -634,7 +638,7 @@ static void print_sym_table(void)
634 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 638 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
635 sum_ksamples)); 639 sum_ksamples));
636 640
637 if (nr_counters == 1 || !display_weighted) 641 if (evsel_list->nr_entries == 1 || !display_weighted)
638 printf("%20.2f ", syme->weight); 642 printf("%20.2f ", syme->weight);
639 else 643 else
640 printf("%9.1f %10ld ", syme->weight, syme->snap_count); 644 printf("%9.1f %10ld ", syme->weight, syme->snap_count);
@@ -744,7 +748,7 @@ static void print_mapped_keys(void)
744 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); 748 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
745 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 749 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
746 750
747 if (nr_counters > 1) 751 if (evsel_list->nr_entries > 1)
748 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); 752 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
749 753
750 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 754 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
@@ -753,7 +757,7 @@ static void print_mapped_keys(void)
753 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 757 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
754 fprintf(stdout, "\t[S] stop annotation.\n"); 758 fprintf(stdout, "\t[S] stop annotation.\n");
755 759
756 if (nr_counters > 1) 760 if (evsel_list->nr_entries > 1)
757 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 761 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
758 762
759 fprintf(stdout, 763 fprintf(stdout,
@@ -783,7 +787,7 @@ static int key_mapped(int c)
783 return 1; 787 return 1;
784 case 'E': 788 case 'E':
785 case 'w': 789 case 'w':
786 return nr_counters > 1 ? 1 : 0; 790 return evsel_list->nr_entries > 1 ? 1 : 0;
787 default: 791 default:
788 break; 792 break;
789 } 793 }
@@ -831,22 +835,22 @@ static void handle_keypress(struct perf_session *session, int c)
831 signal(SIGWINCH, SIG_DFL); 835 signal(SIGWINCH, SIG_DFL);
832 break; 836 break;
833 case 'E': 837 case 'E':
834 if (nr_counters > 1) { 838 if (evsel_list->nr_entries > 1) {
835 fprintf(stderr, "\nAvailable events:"); 839 fprintf(stderr, "\nAvailable events:");
836 840
837 list_for_each_entry(sym_evsel, &evsel_list, node) 841 list_for_each_entry(sym_evsel, &evsel_list->entries, node)
838 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); 842 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
839 843
840 prompt_integer(&sym_counter, "Enter details event counter"); 844 prompt_integer(&sym_counter, "Enter details event counter");
841 845
842 if (sym_counter >= nr_counters) { 846 if (sym_counter >= evsel_list->nr_entries) {
843 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); 847 sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node);
844 sym_counter = 0; 848 sym_counter = 0;
845 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); 849 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
846 sleep(1); 850 sleep(1);
847 break; 851 break;
848 } 852 }
849 list_for_each_entry(sym_evsel, &evsel_list, node) 853 list_for_each_entry(sym_evsel, &evsel_list->entries, node)
850 if (sym_evsel->idx == sym_counter) 854 if (sym_evsel->idx == sym_counter)
851 break; 855 break;
852 } else sym_counter = 0; 856 } else sym_counter = 0;
@@ -930,6 +934,7 @@ repeat:
930/* Tag samples to be skipped. */ 934/* Tag samples to be skipped. */
931static const char *skip_symbols[] = { 935static const char *skip_symbols[] = {
932 "default_idle", 936 "default_idle",
937 "native_safe_halt",
933 "cpu_idle", 938 "cpu_idle",
934 "enter_idle", 939 "enter_idle",
935 "exit_idle", 940 "exit_idle",
@@ -988,8 +993,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
988 993
989static void event__process_sample(const event_t *self, 994static void event__process_sample(const event_t *self,
990 struct sample_data *sample, 995 struct sample_data *sample,
991 struct perf_session *session, 996 struct perf_session *session)
992 struct perf_evsel *evsel)
993{ 997{
994 u64 ip = self->ip.ip; 998 u64 ip = self->ip.ip;
995 struct sym_entry *syme; 999 struct sym_entry *syme;
@@ -1082,8 +1086,12 @@ static void event__process_sample(const event_t *self,
1082 1086
1083 syme = symbol__priv(al.sym); 1087 syme = symbol__priv(al.sym);
1084 if (!syme->skip) { 1088 if (!syme->skip) {
1085 syme->count[evsel->idx]++; 1089 struct perf_evsel *evsel;
1090
1086 syme->origin = origin; 1091 syme->origin = origin;
1092 evsel = perf_evlist__id2evsel(evsel_list, sample->id);
1093 assert(evsel != NULL);
1094 syme->count[evsel->idx]++;
1087 record_precise_ip(syme, evsel->idx, ip); 1095 record_precise_ip(syme, evsel->idx, ip);
1088 pthread_mutex_lock(&active_symbols_lock); 1096 pthread_mutex_lock(&active_symbols_lock);
1089 if (list_empty(&syme->node) || !syme->node.next) 1097 if (list_empty(&syme->node) || !syme->node.next)
@@ -1092,156 +1100,52 @@ static void event__process_sample(const event_t *self,
1092 } 1100 }
1093} 1101}
1094 1102
1095struct mmap_data { 1103static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu)
1096 void *base;
1097 int mask;
1098 unsigned int prev;
1099};
1100
1101static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1102 int ncpus, int nthreads)
1103{
1104 evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1105 return evsel->priv != NULL ? 0 : -ENOMEM;
1106}
1107
1108static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1109{
1110 xyarray__delete(evsel->priv);
1111 evsel->priv = NULL;
1112}
1113
1114static unsigned int mmap_read_head(struct mmap_data *md)
1115{
1116 struct perf_event_mmap_page *pc = md->base;
1117 int head;
1118
1119 head = pc->data_head;
1120 rmb();
1121
1122 return head;
1123}
1124
1125static void perf_session__mmap_read_counter(struct perf_session *self,
1126 struct perf_evsel *evsel,
1127 int cpu, int thread_idx)
1128{ 1104{
1129 struct xyarray *mmap_array = evsel->priv;
1130 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1131 unsigned int head = mmap_read_head(md);
1132 unsigned int old = md->prev;
1133 unsigned char *data = md->base + page_size;
1134 struct sample_data sample; 1105 struct sample_data sample;
1135 int diff; 1106 event_t *event;
1136
1137 /*
1138 * If we're further behind than half the buffer, there's a chance
1139 * the writer will bite our tail and mess up the samples under us.
1140 *
1141 * If we somehow ended up ahead of the head, we got messed up.
1142 *
1143 * In either case, truncate and restart at head.
1144 */
1145 diff = head - old;
1146 if (diff > md->mask / 2 || diff < 0) {
1147 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
1148
1149 /*
1150 * head points to a known good entry, start there.
1151 */
1152 old = head;
1153 }
1154
1155 for (; old != head;) {
1156 event_t *event = (event_t *)&data[old & md->mask];
1157 1107
1158 event_t event_copy; 1108 while ((event = perf_evlist__read_on_cpu(evsel_list, cpu)) != NULL) {
1159 1109 perf_session__parse_sample(self, event, &sample);
1160 size_t size = event->header.size;
1161
1162 /*
1163 * Event straddles the mmap boundary -- header should always
1164 * be inside due to u64 alignment of output.
1165 */
1166 if ((old & md->mask) + size != ((old + size) & md->mask)) {
1167 unsigned int offset = old;
1168 unsigned int len = min(sizeof(*event), size), cpy;
1169 void *dst = &event_copy;
1170
1171 do {
1172 cpy = min(md->mask + 1 - (offset & md->mask), len);
1173 memcpy(dst, &data[offset & md->mask], cpy);
1174 offset += cpy;
1175 dst += cpy;
1176 len -= cpy;
1177 } while (len);
1178
1179 event = &event_copy;
1180 }
1181 1110
1182 event__parse_sample(event, self, &sample);
1183 if (event->header.type == PERF_RECORD_SAMPLE) 1111 if (event->header.type == PERF_RECORD_SAMPLE)
1184 event__process_sample(event, &sample, self, evsel); 1112 event__process_sample(event, &sample, self);
1185 else 1113 else
1186 event__process(event, &sample, self); 1114 event__process(event, &sample, self);
1187 old += size;
1188 } 1115 }
1189
1190 md->prev = old;
1191} 1116}
1192 1117
1193static struct pollfd *event_array;
1194
1195static void perf_session__mmap_read(struct perf_session *self) 1118static void perf_session__mmap_read(struct perf_session *self)
1196{ 1119{
1197 struct perf_evsel *counter; 1120 int i;
1198 int i, thread_index;
1199
1200 for (i = 0; i < cpus->nr; i++) {
1201 list_for_each_entry(counter, &evsel_list, node) {
1202 for (thread_index = 0;
1203 thread_index < threads->nr;
1204 thread_index++) {
1205 perf_session__mmap_read_counter(self,
1206 counter, i, thread_index);
1207 }
1208 }
1209 }
1210}
1211 1121
1212int nr_poll; 1122 for (i = 0; i < cpus->nr; i++)
1213int group_fd; 1123 perf_session__mmap_read_cpu(self, i);
1124}
1214 1125
1215static void start_counter(int i, struct perf_evsel *evsel) 1126static void start_counters(struct perf_evlist *evlist)
1216{ 1127{
1217 struct xyarray *mmap_array = evsel->priv; 1128 struct perf_evsel *counter;
1218 struct mmap_data *mm;
1219 struct perf_event_attr *attr;
1220 int cpu = -1;
1221 int thread_index;
1222
1223 if (target_tid == -1)
1224 cpu = cpus->map[i];
1225 1129
1226 attr = &evsel->attr; 1130 list_for_each_entry(counter, &evlist->entries, node) {
1131 struct perf_event_attr *attr = &counter->attr;
1227 1132
1228 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1133 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1229 1134
1230 if (freq) { 1135 if (freq) {
1231 attr->sample_type |= PERF_SAMPLE_PERIOD; 1136 attr->sample_type |= PERF_SAMPLE_PERIOD;
1232 attr->freq = 1; 1137 attr->freq = 1;
1233 attr->sample_freq = freq; 1138 attr->sample_freq = freq;
1234 } 1139 }
1235 1140
1236 attr->inherit = (cpu < 0) && inherit; 1141 if (evlist->nr_entries > 1) {
1237 attr->mmap = 1; 1142 attr->sample_type |= PERF_SAMPLE_ID;
1143 attr->read_format |= PERF_FORMAT_ID;
1144 }
1238 1145
1239 for (thread_index = 0; thread_index < threads->nr; thread_index++) { 1146 attr->mmap = 1;
1240try_again: 1147try_again:
1241 FD(evsel, i, thread_index) = sys_perf_event_open(attr, 1148 if (perf_evsel__open(counter, cpus, threads, group, inherit) < 0) {
1242 threads->map[thread_index], cpu, group_fd, 0);
1243
1244 if (FD(evsel, i, thread_index) < 0) {
1245 int err = errno; 1149 int err = errno;
1246 1150
1247 if (err == EPERM || err == EACCES) 1151 if (err == EPERM || err == EACCES)
@@ -1253,8 +1157,8 @@ try_again:
1253 * based cpu-clock-tick sw counter, which 1157 * based cpu-clock-tick sw counter, which
1254 * is always available even if no PMU support: 1158 * is always available even if no PMU support:
1255 */ 1159 */
1256 if (attr->type == PERF_TYPE_HARDWARE 1160 if (attr->type == PERF_TYPE_HARDWARE &&
1257 && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 1161 attr->config == PERF_COUNT_HW_CPU_CYCLES) {
1258 1162
1259 if (verbose) 1163 if (verbose)
1260 warning(" ... trying to fall back to cpu-clock-ticks\n"); 1164 warning(" ... trying to fall back to cpu-clock-ticks\n");
@@ -1264,39 +1168,23 @@ try_again:
1264 goto try_again; 1168 goto try_again;
1265 } 1169 }
1266 printf("\n"); 1170 printf("\n");
1267 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 1171 error("sys_perf_event_open() syscall returned with %d "
1268 FD(evsel, i, thread_index), strerror(err)); 1172 "(%s). /bin/dmesg may provide additional information.\n",
1173 err, strerror(err));
1269 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1174 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1270 exit(-1); 1175 exit(-1);
1271 } 1176 }
1272 assert(FD(evsel, i, thread_index) >= 0);
1273 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1274
1275 /*
1276 * First counter acts as the group leader:
1277 */
1278 if (group && group_fd == -1)
1279 group_fd = FD(evsel, i, thread_index);
1280
1281 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1282 event_array[nr_poll].events = POLLIN;
1283 nr_poll++;
1284
1285 mm = xyarray__entry(mmap_array, i, thread_index);
1286 mm->prev = 0;
1287 mm->mask = mmap_pages*page_size - 1;
1288 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1289 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1290 if (mm->base == MAP_FAILED)
1291 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1292 } 1177 }
1178
1179 if (perf_evlist__mmap(evlist, cpus, threads, mmap_pages, true) < 0)
1180 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1293} 1181}
1294 1182
1295static int __cmd_top(void) 1183static int __cmd_top(void)
1296{ 1184{
1297 pthread_t thread; 1185 pthread_t thread;
1298 struct perf_evsel *counter; 1186 struct perf_evsel *first;
1299 int i, ret; 1187 int ret;
1300 /* 1188 /*
1301 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1189 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1302 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1190 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
@@ -1310,14 +1198,12 @@ static int __cmd_top(void)
1310 else 1198 else
1311 event__synthesize_threads(event__process, session); 1199 event__synthesize_threads(event__process, session);
1312 1200
1313 for (i = 0; i < cpus->nr; i++) { 1201 start_counters(evsel_list);
1314 group_fd = -1; 1202 first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
1315 list_for_each_entry(counter, &evsel_list, node) 1203 perf_session__set_sample_type(session, first->attr.sample_type);
1316 start_counter(i, counter);
1317 }
1318 1204
1319 /* Wait for a minimal set of events before starting the snapshot */ 1205 /* Wait for a minimal set of events before starting the snapshot */
1320 poll(&event_array[0], nr_poll, 100); 1206 poll(evsel_list->pollfd, evsel_list->nr_fds, 100);
1321 1207
1322 perf_session__mmap_read(session); 1208 perf_session__mmap_read(session);
1323 1209
@@ -1342,7 +1228,7 @@ static int __cmd_top(void)
1342 perf_session__mmap_read(session); 1228 perf_session__mmap_read(session);
1343 1229
1344 if (hits == samples) 1230 if (hits == samples)
1345 ret = poll(event_array, nr_poll, 100); 1231 ret = poll(evsel_list->pollfd, evsel_list->nr_fds, 100);
1346 } 1232 }
1347 1233
1348 return 0; 1234 return 0;
@@ -1354,7 +1240,7 @@ static const char * const top_usage[] = {
1354}; 1240};
1355 1241
1356static const struct option options[] = { 1242static const struct option options[] = {
1357 OPT_CALLBACK('e', "event", NULL, "event", 1243 OPT_CALLBACK('e', "event", &evsel_list, "event",
1358 "event selector. use 'perf list' to list available events", 1244 "event selector. use 'perf list' to list available events",
1359 parse_events), 1245 parse_events),
1360 OPT_INTEGER('c', "count", &default_interval, 1246 OPT_INTEGER('c', "count", &default_interval,
@@ -1404,6 +1290,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1404 struct perf_evsel *pos; 1290 struct perf_evsel *pos;
1405 int status = -ENOMEM; 1291 int status = -ENOMEM;
1406 1292
1293 evsel_list = perf_evlist__new();
1294 if (evsel_list == NULL)
1295 return -ENOMEM;
1296
1407 page_size = sysconf(_SC_PAGE_SIZE); 1297 page_size = sysconf(_SC_PAGE_SIZE);
1408 1298
1409 argc = parse_options(argc, argv, options, top_usage, 0); 1299 argc = parse_options(argc, argv, options, top_usage, 0);
@@ -1419,11 +1309,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1419 usage_with_options(top_usage, options); 1309 usage_with_options(top_usage, options);
1420 } 1310 }
1421 1311
1422 event_array = malloc((sizeof(struct pollfd) *
1423 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1424 if (!event_array)
1425 return -ENOMEM;
1426
1427 /* CPU and PID are mutually exclusive */ 1312 /* CPU and PID are mutually exclusive */
1428 if (target_tid > 0 && cpu_list) { 1313 if (target_tid > 0 && cpu_list) {
1429 printf("WARNING: PID switch overriding CPU\n"); 1314 printf("WARNING: PID switch overriding CPU\n");
@@ -1431,7 +1316,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1431 cpu_list = NULL; 1316 cpu_list = NULL;
1432 } 1317 }
1433 1318
1434 if (!nr_counters && perf_evsel_list__create_default() < 0) { 1319 if (!evsel_list->nr_entries &&
1320 perf_evlist__add_default(evsel_list) < 0) {
1435 pr_err("Not enough memory for event selector list\n"); 1321 pr_err("Not enough memory for event selector list\n");
1436 return -ENOMEM; 1322 return -ENOMEM;
1437 } 1323 }
@@ -1459,9 +1345,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1459 if (cpus == NULL) 1345 if (cpus == NULL)
1460 usage_with_options(top_usage, options); 1346 usage_with_options(top_usage, options);
1461 1347
1462 list_for_each_entry(pos, &evsel_list, node) { 1348 list_for_each_entry(pos, &evsel_list->entries, node) {
1463 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 || 1349 if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1464 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1465 goto out_free_fd; 1350 goto out_free_fd;
1466 /* 1351 /*
1467 * Fill in the ones not specifically initialized via -c: 1352 * Fill in the ones not specifically initialized via -c:
@@ -1472,10 +1357,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1472 pos->attr.sample_period = default_interval; 1357 pos->attr.sample_period = default_interval;
1473 } 1358 }
1474 1359
1475 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); 1360 if (perf_evlist__alloc_pollfd(evsel_list, cpus->nr, threads->nr) < 0 ||
1361 perf_evlist__alloc_mmap(evsel_list, cpus->nr) < 0)
1362 goto out_free_fd;
1363
1364 sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node);
1476 1365
1477 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1366 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1478 (nr_counters + 1) * sizeof(unsigned long)); 1367 (evsel_list->nr_entries + 1) * sizeof(unsigned long));
1479 1368
1480 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1369 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1481 if (symbol__init() < 0) 1370 if (symbol__init() < 0)
@@ -1489,9 +1378,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1489 1378
1490 status = __cmd_top(); 1379 status = __cmd_top();
1491out_free_fd: 1380out_free_fd:
1492 list_for_each_entry(pos, &evsel_list, node) 1381 perf_evlist__delete(evsel_list);
1493 perf_evsel__free_mmap(pos);
1494 perf_evsel_list__delete();
1495 1382
1496 return status; 1383 return status;
1497} 1384}