diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-11 17:56:53 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-22 16:56:28 -0500 |
commit | 361c99a661a78ed22264649440e87fe4fe8da1f2 (patch) | |
tree | a60bc86f132608f2d41c800760b41f6f54f8e7af /tools/perf/builtin-top.c | |
parent | 00e99a49f6f3a6b5a84ba8bf8f632c9b974bea7a (diff) |
perf evsel: Introduce perf_evlist
Killing two more perf wide global variables: nr_counters and evsel_list
as a list_head.
There are more operations that will need more fields in perf_evlist,
like the pollfd for polling all the fds in a list of evsel instances.
Use option->value to pass the evsel_list to parse_{events,filters}.
LKML-Reference: <new-submission>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b6998e055767..216b62ed4b89 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/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" |
@@ -60,6 +61,8 @@ | |||
60 | 61 | ||
61 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 62 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
62 | 63 | ||
64 | struct perf_evlist *evsel_list; | ||
65 | |||
63 | static bool system_wide = false; | 66 | static bool system_wide = false; |
64 | 67 | ||
65 | static int default_interval = 0; | 68 | static int default_interval = 0; |
@@ -267,7 +270,7 @@ static void __zero_source_counters(struct sym_entry *syme) | |||
267 | 270 | ||
268 | line = syme->src->lines; | 271 | line = syme->src->lines; |
269 | while (line) { | 272 | while (line) { |
270 | for (i = 0; i < nr_counters; i++) | 273 | for (i = 0; i < evsel_list->nr_entries; i++) |
271 | line->count[i] = 0; | 274 | line->count[i] = 0; |
272 | line = line->next; | 275 | line = line->next; |
273 | } | 276 | } |
@@ -414,7 +417,7 @@ static double sym_weight(const struct sym_entry *sym) | |||
414 | if (!display_weighted) | 417 | if (!display_weighted) |
415 | return weight; | 418 | return weight; |
416 | 419 | ||
417 | for (counter = 1; counter < nr_counters-1; counter++) | 420 | for (counter = 1; counter < evsel_list->nr_entries - 1; counter++) |
418 | weight *= sym->count[counter]; | 421 | weight *= sym->count[counter]; |
419 | 422 | ||
420 | weight /= (sym->count[counter] + 1); | 423 | weight /= (sym->count[counter] + 1); |
@@ -501,7 +504,7 @@ static void print_sym_table(void) | |||
501 | rb_insert_active_sym(&tmp, syme); | 504 | rb_insert_active_sym(&tmp, syme); |
502 | sum_ksamples += syme->snap_count; | 505 | sum_ksamples += syme->snap_count; |
503 | 506 | ||
504 | for (j = 0; j < nr_counters; j++) | 507 | for (j = 0; j < evsel_list->nr_entries; j++) |
505 | syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; | 508 | syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; |
506 | } else | 509 | } else |
507 | list_remove_active_sym(syme); | 510 | list_remove_active_sym(syme); |
@@ -535,9 +538,9 @@ static void print_sym_table(void) | |||
535 | esamples_percent); | 538 | esamples_percent); |
536 | } | 539 | } |
537 | 540 | ||
538 | if (nr_counters == 1 || !display_weighted) { | 541 | if (evsel_list->nr_entries == 1 || !display_weighted) { |
539 | struct perf_evsel *first; | 542 | struct perf_evsel *first; |
540 | first = list_entry(evsel_list.next, struct perf_evsel, node); | 543 | first = list_entry(evsel_list->entries.next, struct perf_evsel, node); |
541 | printf("%" PRIu64, (uint64_t)first->attr.sample_period); | 544 | printf("%" PRIu64, (uint64_t)first->attr.sample_period); |
542 | if (freq) | 545 | if (freq) |
543 | printf("Hz "); | 546 | printf("Hz "); |
@@ -547,7 +550,7 @@ static void print_sym_table(void) | |||
547 | 550 | ||
548 | if (!display_weighted) | 551 | if (!display_weighted) |
549 | printf("%s", event_name(sym_evsel)); | 552 | printf("%s", event_name(sym_evsel)); |
550 | else list_for_each_entry(counter, &evsel_list, node) { | 553 | else list_for_each_entry(counter, &evsel_list->entries, node) { |
551 | if (counter->idx) | 554 | if (counter->idx) |
552 | printf("/"); | 555 | printf("/"); |
553 | 556 | ||
@@ -606,7 +609,7 @@ static void print_sym_table(void) | |||
606 | sym_width = winsize.ws_col - dso_width - 29; | 609 | sym_width = winsize.ws_col - dso_width - 29; |
607 | } | 610 | } |
608 | putchar('\n'); | 611 | putchar('\n'); |
609 | if (nr_counters == 1) | 612 | if (evsel_list->nr_entries == 1) |
610 | printf(" samples pcnt"); | 613 | printf(" samples pcnt"); |
611 | else | 614 | else |
612 | printf(" weight samples pcnt"); | 615 | printf(" weight samples pcnt"); |
@@ -615,7 +618,7 @@ static void print_sym_table(void) | |||
615 | printf(" RIP "); | 618 | printf(" RIP "); |
616 | printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); | 619 | printf(" %-*.*s DSO\n", sym_width, sym_width, "function"); |
617 | printf(" %s _______ _____", | 620 | printf(" %s _______ _____", |
618 | nr_counters == 1 ? " " : "______"); | 621 | evsel_list->nr_entries == 1 ? " " : "______"); |
619 | if (verbose) | 622 | if (verbose) |
620 | printf(" ________________"); | 623 | printf(" ________________"); |
621 | printf(" %-*.*s", sym_width, sym_width, graph_line); | 624 | printf(" %-*.*s", sym_width, sym_width, graph_line); |
@@ -634,7 +637,7 @@ static void print_sym_table(void) | |||
634 | pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / | 637 | pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / |
635 | sum_ksamples)); | 638 | sum_ksamples)); |
636 | 639 | ||
637 | if (nr_counters == 1 || !display_weighted) | 640 | if (evsel_list->nr_entries == 1 || !display_weighted) |
638 | printf("%20.2f ", syme->weight); | 641 | printf("%20.2f ", syme->weight); |
639 | else | 642 | else |
640 | printf("%9.1f %10ld ", syme->weight, syme->snap_count); | 643 | printf("%9.1f %10ld ", syme->weight, syme->snap_count); |
@@ -744,7 +747,7 @@ static void print_mapped_keys(void) | |||
744 | fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); | 747 | 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); | 748 | fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); |
746 | 749 | ||
747 | if (nr_counters > 1) | 750 | if (evsel_list->nr_entries > 1) |
748 | fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); | 751 | fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel)); |
749 | 752 | ||
750 | fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); | 753 | fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); |
@@ -753,7 +756,7 @@ static void print_mapped_keys(void) | |||
753 | fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); | 756 | fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); |
754 | fprintf(stdout, "\t[S] stop annotation.\n"); | 757 | fprintf(stdout, "\t[S] stop annotation.\n"); |
755 | 758 | ||
756 | if (nr_counters > 1) | 759 | if (evsel_list->nr_entries > 1) |
757 | fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); | 760 | fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); |
758 | 761 | ||
759 | fprintf(stdout, | 762 | fprintf(stdout, |
@@ -783,7 +786,7 @@ static int key_mapped(int c) | |||
783 | return 1; | 786 | return 1; |
784 | case 'E': | 787 | case 'E': |
785 | case 'w': | 788 | case 'w': |
786 | return nr_counters > 1 ? 1 : 0; | 789 | return evsel_list->nr_entries > 1 ? 1 : 0; |
787 | default: | 790 | default: |
788 | break; | 791 | break; |
789 | } | 792 | } |
@@ -831,22 +834,22 @@ static void handle_keypress(struct perf_session *session, int c) | |||
831 | signal(SIGWINCH, SIG_DFL); | 834 | signal(SIGWINCH, SIG_DFL); |
832 | break; | 835 | break; |
833 | case 'E': | 836 | case 'E': |
834 | if (nr_counters > 1) { | 837 | if (evsel_list->nr_entries > 1) { |
835 | fprintf(stderr, "\nAvailable events:"); | 838 | fprintf(stderr, "\nAvailable events:"); |
836 | 839 | ||
837 | list_for_each_entry(sym_evsel, &evsel_list, node) | 840 | list_for_each_entry(sym_evsel, &evsel_list->entries, node) |
838 | fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); | 841 | fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel)); |
839 | 842 | ||
840 | prompt_integer(&sym_counter, "Enter details event counter"); | 843 | prompt_integer(&sym_counter, "Enter details event counter"); |
841 | 844 | ||
842 | if (sym_counter >= nr_counters) { | 845 | if (sym_counter >= evsel_list->nr_entries) { |
843 | sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); | 846 | sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node); |
844 | sym_counter = 0; | 847 | sym_counter = 0; |
845 | fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); | 848 | fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel)); |
846 | sleep(1); | 849 | sleep(1); |
847 | break; | 850 | break; |
848 | } | 851 | } |
849 | list_for_each_entry(sym_evsel, &evsel_list, node) | 852 | list_for_each_entry(sym_evsel, &evsel_list->entries, node) |
850 | if (sym_evsel->idx == sym_counter) | 853 | if (sym_evsel->idx == sym_counter) |
851 | break; | 854 | break; |
852 | } else sym_counter = 0; | 855 | } else sym_counter = 0; |
@@ -1198,7 +1201,7 @@ static void perf_session__mmap_read(struct perf_session *self) | |||
1198 | int i, thread_index; | 1201 | int i, thread_index; |
1199 | 1202 | ||
1200 | for (i = 0; i < cpus->nr; i++) { | 1203 | for (i = 0; i < cpus->nr; i++) { |
1201 | list_for_each_entry(counter, &evsel_list, node) { | 1204 | list_for_each_entry(counter, &evsel_list->entries, node) { |
1202 | for (thread_index = 0; | 1205 | for (thread_index = 0; |
1203 | thread_index < threads->nr; | 1206 | thread_index < threads->nr; |
1204 | thread_index++) { | 1207 | thread_index++) { |
@@ -1312,7 +1315,7 @@ static int __cmd_top(void) | |||
1312 | 1315 | ||
1313 | for (i = 0; i < cpus->nr; i++) { | 1316 | for (i = 0; i < cpus->nr; i++) { |
1314 | group_fd = -1; | 1317 | group_fd = -1; |
1315 | list_for_each_entry(counter, &evsel_list, node) | 1318 | list_for_each_entry(counter, &evsel_list->entries, node) |
1316 | start_counter(i, counter); | 1319 | start_counter(i, counter); |
1317 | } | 1320 | } |
1318 | 1321 | ||
@@ -1354,7 +1357,7 @@ static const char * const top_usage[] = { | |||
1354 | }; | 1357 | }; |
1355 | 1358 | ||
1356 | static const struct option options[] = { | 1359 | static const struct option options[] = { |
1357 | OPT_CALLBACK('e', "event", NULL, "event", | 1360 | OPT_CALLBACK('e', "event", &evsel_list, "event", |
1358 | "event selector. use 'perf list' to list available events", | 1361 | "event selector. use 'perf list' to list available events", |
1359 | parse_events), | 1362 | parse_events), |
1360 | OPT_INTEGER('c', "count", &default_interval, | 1363 | OPT_INTEGER('c', "count", &default_interval, |
@@ -1404,6 +1407,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1404 | struct perf_evsel *pos; | 1407 | struct perf_evsel *pos; |
1405 | int status = -ENOMEM; | 1408 | int status = -ENOMEM; |
1406 | 1409 | ||
1410 | evsel_list = perf_evlist__new(); | ||
1411 | if (evsel_list == NULL) | ||
1412 | return -ENOMEM; | ||
1413 | |||
1407 | page_size = sysconf(_SC_PAGE_SIZE); | 1414 | page_size = sysconf(_SC_PAGE_SIZE); |
1408 | 1415 | ||
1409 | argc = parse_options(argc, argv, options, top_usage, 0); | 1416 | argc = parse_options(argc, argv, options, top_usage, 0); |
@@ -1431,7 +1438,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1431 | cpu_list = NULL; | 1438 | cpu_list = NULL; |
1432 | } | 1439 | } |
1433 | 1440 | ||
1434 | if (!nr_counters && perf_evsel_list__create_default() < 0) { | 1441 | if (!evsel_list->nr_entries && |
1442 | perf_evlist__add_default(evsel_list) < 0) { | ||
1435 | pr_err("Not enough memory for event selector list\n"); | 1443 | pr_err("Not enough memory for event selector list\n"); |
1436 | return -ENOMEM; | 1444 | return -ENOMEM; |
1437 | } | 1445 | } |
@@ -1459,7 +1467,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1459 | if (cpus == NULL) | 1467 | if (cpus == NULL) |
1460 | usage_with_options(top_usage, options); | 1468 | usage_with_options(top_usage, options); |
1461 | 1469 | ||
1462 | list_for_each_entry(pos, &evsel_list, node) { | 1470 | list_for_each_entry(pos, &evsel_list->entries, node) { |
1463 | if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 || | 1471 | if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 || |
1464 | perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) | 1472 | perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0) |
1465 | goto out_free_fd; | 1473 | goto out_free_fd; |
@@ -1472,10 +1480,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1472 | pos->attr.sample_period = default_interval; | 1480 | pos->attr.sample_period = default_interval; |
1473 | } | 1481 | } |
1474 | 1482 | ||
1475 | sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node); | 1483 | sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node); |
1476 | 1484 | ||
1477 | symbol_conf.priv_size = (sizeof(struct sym_entry) + | 1485 | symbol_conf.priv_size = (sizeof(struct sym_entry) + |
1478 | (nr_counters + 1) * sizeof(unsigned long)); | 1486 | (evsel_list->nr_entries + 1) * sizeof(unsigned long)); |
1479 | 1487 | ||
1480 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); | 1488 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
1481 | if (symbol__init() < 0) | 1489 | if (symbol__init() < 0) |
@@ -1489,9 +1497,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1489 | 1497 | ||
1490 | status = __cmd_top(); | 1498 | status = __cmd_top(); |
1491 | out_free_fd: | 1499 | out_free_fd: |
1492 | list_for_each_entry(pos, &evsel_list, node) | 1500 | list_for_each_entry(pos, &evsel_list->entries, node) |
1493 | perf_evsel__free_mmap(pos); | 1501 | perf_evsel__free_mmap(pos); |
1494 | perf_evsel_list__delete(); | 1502 | perf_evlist__delete(evsel_list); |
1495 | 1503 | ||
1496 | return status; | 1504 | return status; |
1497 | } | 1505 | } |