Commit 300176af031a2b1b9cb08ce1459845dcb2fac1b9

Authored by Ingo Molnar

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/g…

…it/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo:

 - Free callchains when hist entries are deleted, plugging a massive leak in
   'top -g', where hist_entries (and its callchains) are decayed over time. (Namhyung Kim)

 - Fix segfault when showing callchain in the hists browser (report & top) (Namhyung Kim)

 - Fix children sort key behavior, and also the 'perf test 32' test that
   was failing due to reliance on undefined behaviour (Namhyung Kim)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

Showing 6 changed files Side-by-side Diff

tools/perf/tests/hists_cumulate.c
... ... @@ -454,12 +454,12 @@
454 454 * 30.00% 10.00% perf perf [.] cmd_record
455 455 * 20.00% 0.00% bash libc [.] malloc
456 456 * 10.00% 10.00% bash [kernel] [k] page_fault
457   - * 10.00% 10.00% perf [kernel] [k] schedule
458   - * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
  457 + * 10.00% 10.00% bash bash [.] xmalloc
459 458 * 10.00% 10.00% perf [kernel] [k] page_fault
460   - * 10.00% 10.00% perf libc [.] free
461 459 * 10.00% 10.00% perf libc [.] malloc
462   - * 10.00% 10.00% bash bash [.] xmalloc
  460 + * 10.00% 10.00% perf [kernel] [k] schedule
  461 + * 10.00% 10.00% perf libc [.] free
  462 + * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
463 463 */
464 464 struct result expected[] = {
465 465 { 7000, 2000, "perf", "perf", "main" },
466 466  
467 467  
... ... @@ -468,12 +468,12 @@
468 468 { 3000, 1000, "perf", "perf", "cmd_record" },
469 469 { 2000, 0, "bash", "libc", "malloc" },
470 470 { 1000, 1000, "bash", "[kernel]", "page_fault" },
471   - { 1000, 1000, "perf", "[kernel]", "schedule" },
472   - { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
  471 + { 1000, 1000, "bash", "bash", "xmalloc" },
473 472 { 1000, 1000, "perf", "[kernel]", "page_fault" },
  473 + { 1000, 1000, "perf", "[kernel]", "schedule" },
474 474 { 1000, 1000, "perf", "libc", "free" },
475 475 { 1000, 1000, "perf", "libc", "malloc" },
476   - { 1000, 1000, "bash", "bash", "xmalloc" },
  476 + { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
477 477 };
478 478  
479 479 symbol_conf.use_callchain = false;
480 480  
... ... @@ -537,10 +537,13 @@
537 537 * malloc
538 538 * main
539 539 *
540   - * 10.00% 10.00% perf [kernel] [k] schedule
  540 + * 10.00% 10.00% bash bash [.] xmalloc
541 541 * |
542   - * --- schedule
543   - * run_command
  542 + * --- xmalloc
  543 + * malloc
  544 + * xmalloc <--- NOTE: there's a cycle
  545 + * malloc
  546 + * xmalloc
544 547 * main
545 548 *
546 549 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
... ... @@ -556,6 +559,12 @@
556 559 * run_command
557 560 * main
558 561 *
  562 + * 10.00% 10.00% perf [kernel] [k] schedule
  563 + * |
  564 + * --- schedule
  565 + * run_command
  566 + * main
  567 + *
559 568 * 10.00% 10.00% perf libc [.] free
560 569 * |
561 570 * --- free
... ... @@ -570,15 +579,6 @@
570 579 * run_command
571 580 * main
572 581 *
573   - * 10.00% 10.00% bash bash [.] xmalloc
574   - * |
575   - * --- xmalloc
576   - * malloc
577   - * xmalloc <--- NOTE: there's a cycle
578   - * malloc
579   - * xmalloc
580   - * main
581   - *
582 582 */
583 583 struct result expected[] = {
584 584 { 7000, 2000, "perf", "perf", "main" },
585 585  
586 586  
... ... @@ -587,12 +587,12 @@
587 587 { 3000, 1000, "perf", "perf", "cmd_record" },
588 588 { 2000, 0, "bash", "libc", "malloc" },
589 589 { 1000, 1000, "bash", "[kernel]", "page_fault" },
590   - { 1000, 1000, "perf", "[kernel]", "schedule" },
  590 + { 1000, 1000, "bash", "bash", "xmalloc" },
591 591 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
592 592 { 1000, 1000, "perf", "[kernel]", "page_fault" },
  593 + { 1000, 1000, "perf", "[kernel]", "schedule" },
593 594 { 1000, 1000, "perf", "libc", "free" },
594 595 { 1000, 1000, "perf", "libc", "malloc" },
595   - { 1000, 1000, "bash", "bash", "xmalloc" },
596 596 };
597 597 struct callchain_result expected_callchain[] = {
598 598 {
... ... @@ -622,9 +622,12 @@
622 622 { "bash", "main" }, },
623 623 },
624 624 {
625   - 3, { { "[kernel]", "schedule" },
626   - { "perf", "run_command" },
627   - { "perf", "main" }, },
  625 + 6, { { "bash", "xmalloc" },
  626 + { "libc", "malloc" },
  627 + { "bash", "xmalloc" },
  628 + { "libc", "malloc" },
  629 + { "bash", "xmalloc" },
  630 + { "bash", "main" }, },
628 631 },
629 632 {
630 633 3, { { "[kernel]", "sys_perf_event_open" },
... ... @@ -638,6 +641,11 @@
638 641 { "perf", "main" }, },
639 642 },
640 643 {
  644 + 3, { { "[kernel]", "schedule" },
  645 + { "perf", "run_command" },
  646 + { "perf", "main" }, },
  647 + },
  648 + {
641 649 4, { { "libc", "free" },
642 650 { "perf", "cmd_record" },
643 651 { "perf", "run_command" },
... ... @@ -648,14 +656,6 @@
648 656 { "perf", "cmd_record" },
649 657 { "perf", "run_command" },
650 658 { "perf", "main" }, },
651   - },
652   - {
653   - 6, { { "bash", "xmalloc" },
654   - { "libc", "malloc" },
655   - { "bash", "xmalloc" },
656   - { "libc", "malloc" },
657   - { "bash", "xmalloc" },
658   - { "bash", "main" }, },
659 659 },
660 660 };
661 661  
tools/perf/ui/browsers/hists.c
... ... @@ -550,7 +550,7 @@
550 550 bool need_percent;
551 551  
552 552 node = rb_first(root);
553   - need_percent = !!rb_next(node);
  553 + need_percent = node && rb_next(node);
554 554  
555 555 while (node) {
556 556 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
tools/perf/ui/hist.c
... ... @@ -204,6 +204,9 @@
204 204 if (ret)
205 205 return ret;
206 206  
  207 + if (a->thread != b->thread || !symbol_conf.use_callchain)
  208 + return 0;
  209 +
207 210 ret = b->callchain->max_depth - a->callchain->max_depth;
208 211 }
209 212 return ret;
tools/perf/util/callchain.c
... ... @@ -841,4 +841,34 @@
841 841  
842 842 return bf;
843 843 }
  844 +
  845 +static void free_callchain_node(struct callchain_node *node)
  846 +{
  847 + struct callchain_list *list, *tmp;
  848 + struct callchain_node *child;
  849 + struct rb_node *n;
  850 +
  851 + list_for_each_entry_safe(list, tmp, &node->val, list) {
  852 + list_del(&list->list);
  853 + free(list);
  854 + }
  855 +
  856 + n = rb_first(&node->rb_root_in);
  857 + while (n) {
  858 + child = container_of(n, struct callchain_node, rb_node_in);
  859 + n = rb_next(n);
  860 + rb_erase(&child->rb_node_in, &node->rb_root_in);
  861 +
  862 + free_callchain_node(child);
  863 + free(child);
  864 + }
  865 +}
  866 +
  867 +void free_callchain(struct callchain_root *root)
  868 +{
  869 + if (!symbol_conf.use_callchain)
  870 + return;
  871 +
  872 + free_callchain_node(&root->node);
  873 +}
tools/perf/util/callchain.h
... ... @@ -198,5 +198,7 @@
198 198 char *callchain_list__sym_name(struct callchain_list *cl,
199 199 char *bf, size_t bfsize, bool show_dso);
200 200  
  201 +void free_callchain(struct callchain_root *root);
  202 +
201 203 #endif /* __PERF_CALLCHAIN_H */
tools/perf/util/hist.c
... ... @@ -947,6 +947,7 @@
947 947 zfree(&he->mem_info);
948 948 zfree(&he->stat_acc);
949 949 free_srcline(he->srcline);
  950 + free_callchain(he->callchain);
950 951 free(he);
951 952 }
952 953