diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-30 11:25:53 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-31 11:07:42 -0500 |
commit | 11859e821761e9738c4d8a0e7d6ca1cc2e0d37e8 (patch) | |
tree | 952564a6f569dd284a3194d6d3a455fe6da2dde1 /tools/perf | |
parent | 152fefa921535665f95840c08062844ab2f5593e (diff) |
perf top: Stop using exit()
Just return to the perf main() routine so that an unified exit path can
be followed and resources released, helping in finding memory leaks.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ro8oeodo96490nrhcph57atr@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-top.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 7978c8117b7f..903e4f4a3047 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -68,6 +68,8 @@ | |||
68 | #include <linux/unistd.h> | 68 | #include <linux/unistd.h> |
69 | #include <linux/types.h> | 69 | #include <linux/types.h> |
70 | 70 | ||
71 | static volatile int done; | ||
72 | |||
71 | static void perf_top__update_print_entries(struct perf_top *top) | 73 | static void perf_top__update_print_entries(struct perf_top *top) |
72 | { | 74 | { |
73 | if (top->print_entries > 9) | 75 | if (top->print_entries > 9) |
@@ -431,8 +433,10 @@ static int perf_top__key_mapped(struct perf_top *top, int c) | |||
431 | return 0; | 433 | return 0; |
432 | } | 434 | } |
433 | 435 | ||
434 | static void perf_top__handle_keypress(struct perf_top *top, int c) | 436 | static bool perf_top__handle_keypress(struct perf_top *top, int c) |
435 | { | 437 | { |
438 | bool ret = true; | ||
439 | |||
436 | if (!perf_top__key_mapped(top, c)) { | 440 | if (!perf_top__key_mapped(top, c)) { |
437 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; | 441 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; |
438 | struct termios tc, save; | 442 | struct termios tc, save; |
@@ -453,7 +457,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) | |||
453 | 457 | ||
454 | tcsetattr(0, TCSAFLUSH, &save); | 458 | tcsetattr(0, TCSAFLUSH, &save); |
455 | if (!perf_top__key_mapped(top, c)) | 459 | if (!perf_top__key_mapped(top, c)) |
456 | return; | 460 | return ret; |
457 | } | 461 | } |
458 | 462 | ||
459 | switch (c) { | 463 | switch (c) { |
@@ -515,7 +519,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) | |||
515 | printf("exiting.\n"); | 519 | printf("exiting.\n"); |
516 | if (top->dump_symtab) | 520 | if (top->dump_symtab) |
517 | perf_session__fprintf_dsos(top->session, stderr); | 521 | perf_session__fprintf_dsos(top->session, stderr); |
518 | exit(0); | 522 | ret = false; |
523 | break; | ||
519 | case 's': | 524 | case 's': |
520 | perf_top__prompt_symbol(top, "Enter details symbol"); | 525 | perf_top__prompt_symbol(top, "Enter details symbol"); |
521 | break; | 526 | break; |
@@ -538,6 +543,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) | |||
538 | default: | 543 | default: |
539 | break; | 544 | break; |
540 | } | 545 | } |
546 | |||
547 | return ret; | ||
541 | } | 548 | } |
542 | 549 | ||
543 | static void perf_top__sort_new_samples(void *arg) | 550 | static void perf_top__sort_new_samples(void *arg) |
@@ -579,8 +586,7 @@ static void *display_thread_tui(void *arg) | |||
579 | perf_evlist__tui_browse_hists(top->evlist, help, &hbt, | 586 | perf_evlist__tui_browse_hists(top->evlist, help, &hbt, |
580 | &top->session->header.env); | 587 | &top->session->header.env); |
581 | 588 | ||
582 | exit_browser(0); | 589 | done = 1; |
583 | exit(0); | ||
584 | return NULL; | 590 | return NULL; |
585 | } | 591 | } |
586 | 592 | ||
@@ -604,7 +610,7 @@ repeat: | |||
604 | /* trash return*/ | 610 | /* trash return*/ |
605 | getc(stdin); | 611 | getc(stdin); |
606 | 612 | ||
607 | while (1) { | 613 | while (!done) { |
608 | perf_top__print_sym_table(top); | 614 | perf_top__print_sym_table(top); |
609 | /* | 615 | /* |
610 | * Either timeout expired or we got an EINTR due to SIGWINCH, | 616 | * Either timeout expired or we got an EINTR due to SIGWINCH, |
@@ -618,15 +624,14 @@ repeat: | |||
618 | continue; | 624 | continue; |
619 | /* Fall trhu */ | 625 | /* Fall trhu */ |
620 | default: | 626 | default: |
621 | goto process_hotkey; | 627 | c = getc(stdin); |
628 | tcsetattr(0, TCSAFLUSH, &save); | ||
629 | |||
630 | if (perf_top__handle_keypress(top, c)) | ||
631 | goto repeat; | ||
632 | done = 1; | ||
622 | } | 633 | } |
623 | } | 634 | } |
624 | process_hotkey: | ||
625 | c = getc(stdin); | ||
626 | tcsetattr(0, TCSAFLUSH, &save); | ||
627 | |||
628 | perf_top__handle_keypress(top, c); | ||
629 | goto repeat; | ||
630 | 635 | ||
631 | return NULL; | 636 | return NULL; |
632 | } | 637 | } |
@@ -705,7 +710,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
705 | } | 710 | } |
706 | 711 | ||
707 | if (!machine) { | 712 | if (!machine) { |
708 | pr_err("%u unprocessable samples recorded.\n", | 713 | pr_err("%u unprocessable samples recorded.\r", |
709 | top->session->stats.nr_unprocessable_samples++); | 714 | top->session->stats.nr_unprocessable_samples++); |
710 | return; | 715 | return; |
711 | } | 716 | } |
@@ -868,7 +873,7 @@ static void perf_top__mmap_read(struct perf_top *top) | |||
868 | perf_top__mmap_read_idx(top, i); | 873 | perf_top__mmap_read_idx(top, i); |
869 | } | 874 | } |
870 | 875 | ||
871 | static void perf_top__start_counters(struct perf_top *top) | 876 | static int perf_top__start_counters(struct perf_top *top) |
872 | { | 877 | { |
873 | char msg[512]; | 878 | char msg[512]; |
874 | struct perf_evsel *counter; | 879 | struct perf_evsel *counter; |
@@ -900,11 +905,10 @@ try_again: | |||
900 | goto out_err; | 905 | goto out_err; |
901 | } | 906 | } |
902 | 907 | ||
903 | return; | 908 | return 0; |
904 | 909 | ||
905 | out_err: | 910 | out_err: |
906 | exit_browser(0); | 911 | return -1; |
907 | exit(0); | ||
908 | } | 912 | } |
909 | 913 | ||
910 | static int perf_top__setup_sample_type(struct perf_top *top) | 914 | static int perf_top__setup_sample_type(struct perf_top *top) |
@@ -948,7 +952,11 @@ static int __cmd_top(struct perf_top *top) | |||
948 | else | 952 | else |
949 | perf_event__synthesize_threads(&top->tool, perf_event__process, | 953 | perf_event__synthesize_threads(&top->tool, perf_event__process, |
950 | &top->session->machines.host); | 954 | &top->session->machines.host); |
951 | perf_top__start_counters(top); | 955 | |
956 | ret = perf_top__start_counters(top); | ||
957 | if (ret) | ||
958 | goto out_delete; | ||
959 | |||
952 | top->session->evlist = top->evlist; | 960 | top->session->evlist = top->evlist; |
953 | perf_session__set_id_hdr_size(top->session); | 961 | perf_session__set_id_hdr_size(top->session); |
954 | 962 | ||
@@ -968,10 +976,11 @@ static int __cmd_top(struct perf_top *top) | |||
968 | 976 | ||
969 | perf_top__mmap_read(top); | 977 | perf_top__mmap_read(top); |
970 | 978 | ||
979 | ret = -1; | ||
971 | if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : | 980 | if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : |
972 | display_thread), top)) { | 981 | display_thread), top)) { |
973 | ui__error("Could not create display thread.\n"); | 982 | ui__error("Could not create display thread.\n"); |
974 | exit(-1); | 983 | goto out_delete; |
975 | } | 984 | } |
976 | 985 | ||
977 | if (top->realtime_prio) { | 986 | if (top->realtime_prio) { |
@@ -980,11 +989,11 @@ static int __cmd_top(struct perf_top *top) | |||
980 | param.sched_priority = top->realtime_prio; | 989 | param.sched_priority = top->realtime_prio; |
981 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { | 990 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { |
982 | ui__error("Could not set realtime priority.\n"); | 991 | ui__error("Could not set realtime priority.\n"); |
983 | exit(-1); | 992 | goto out_delete; |
984 | } | 993 | } |
985 | } | 994 | } |
986 | 995 | ||
987 | while (1) { | 996 | while (!done) { |
988 | u64 hits = top->samples; | 997 | u64 hits = top->samples; |
989 | 998 | ||
990 | perf_top__mmap_read(top); | 999 | perf_top__mmap_read(top); |
@@ -993,11 +1002,12 @@ static int __cmd_top(struct perf_top *top) | |||
993 | ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); | 1002 | ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); |
994 | } | 1003 | } |
995 | 1004 | ||
1005 | ret = 0; | ||
996 | out_delete: | 1006 | out_delete: |
997 | perf_session__delete(top->session); | 1007 | perf_session__delete(top->session); |
998 | top->session = NULL; | 1008 | top->session = NULL; |
999 | 1009 | ||
1000 | return 0; | 1010 | return ret; |
1001 | } | 1011 | } |
1002 | 1012 | ||
1003 | static int | 1013 | static int |