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 | |
| 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>
| -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; | ||
