Commit 300176af authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-urgent-for-mingo' of...

Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ed9eb845 c09e31cc
...@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) ...@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
* 30.00% 10.00% perf perf [.] cmd_record * 30.00% 10.00% perf perf [.] cmd_record
* 20.00% 0.00% bash libc [.] malloc * 20.00% 0.00% bash libc [.] malloc
* 10.00% 10.00% bash [kernel] [k] page_fault * 10.00% 10.00% bash [kernel] [k] page_fault
* 10.00% 10.00% perf [kernel] [k] schedule * 10.00% 10.00% bash bash [.] xmalloc
* 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
* 10.00% 10.00% perf [kernel] [k] page_fault * 10.00% 10.00% perf [kernel] [k] page_fault
* 10.00% 10.00% perf libc [.] free
* 10.00% 10.00% perf libc [.] malloc * 10.00% 10.00% perf libc [.] malloc
* 10.00% 10.00% bash bash [.] xmalloc * 10.00% 10.00% perf [kernel] [k] schedule
* 10.00% 10.00% perf libc [.] free
* 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
*/ */
struct result expected[] = { struct result expected[] = {
{ 7000, 2000, "perf", "perf", "main" }, { 7000, 2000, "perf", "perf", "main" },
...@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) ...@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
{ 3000, 1000, "perf", "perf", "cmd_record" }, { 3000, 1000, "perf", "perf", "cmd_record" },
{ 2000, 0, "bash", "libc", "malloc" }, { 2000, 0, "bash", "libc", "malloc" },
{ 1000, 1000, "bash", "[kernel]", "page_fault" }, { 1000, 1000, "bash", "[kernel]", "page_fault" },
{ 1000, 1000, "perf", "[kernel]", "schedule" }, { 1000, 1000, "bash", "bash", "xmalloc" },
{ 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
{ 1000, 1000, "perf", "[kernel]", "page_fault" }, { 1000, 1000, "perf", "[kernel]", "page_fault" },
{ 1000, 1000, "perf", "[kernel]", "schedule" },
{ 1000, 1000, "perf", "libc", "free" }, { 1000, 1000, "perf", "libc", "free" },
{ 1000, 1000, "perf", "libc", "malloc" }, { 1000, 1000, "perf", "libc", "malloc" },
{ 1000, 1000, "bash", "bash", "xmalloc" }, { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
}; };
symbol_conf.use_callchain = false; symbol_conf.use_callchain = false;
...@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
* malloc * malloc
* main * main
* *
* 10.00% 10.00% perf [kernel] [k] schedule * 10.00% 10.00% bash bash [.] xmalloc
* | * |
* --- schedule * --- xmalloc
* run_command * malloc
* xmalloc <--- NOTE: there's a cycle
* malloc
* xmalloc
* main * main
* *
* 10.00% 0.00% perf [kernel] [k] sys_perf_event_open * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
...@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
* run_command * run_command
* main * main
* *
* 10.00% 10.00% perf [kernel] [k] schedule
* |
* --- schedule
* run_command
* main
*
* 10.00% 10.00% perf libc [.] free * 10.00% 10.00% perf libc [.] free
* | * |
* --- free * --- free
...@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
* run_command * run_command
* main * main
* *
* 10.00% 10.00% bash bash [.] xmalloc
* |
* --- xmalloc
* malloc
* xmalloc <--- NOTE: there's a cycle
* malloc
* xmalloc
* main
*
*/ */
struct result expected[] = { struct result expected[] = {
{ 7000, 2000, "perf", "perf", "main" }, { 7000, 2000, "perf", "perf", "main" },
...@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
{ 3000, 1000, "perf", "perf", "cmd_record" }, { 3000, 1000, "perf", "perf", "cmd_record" },
{ 2000, 0, "bash", "libc", "malloc" }, { 2000, 0, "bash", "libc", "malloc" },
{ 1000, 1000, "bash", "[kernel]", "page_fault" }, { 1000, 1000, "bash", "[kernel]", "page_fault" },
{ 1000, 1000, "perf", "[kernel]", "schedule" }, { 1000, 1000, "bash", "bash", "xmalloc" },
{ 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
{ 1000, 1000, "perf", "[kernel]", "page_fault" }, { 1000, 1000, "perf", "[kernel]", "page_fault" },
{ 1000, 1000, "perf", "[kernel]", "schedule" },
{ 1000, 1000, "perf", "libc", "free" }, { 1000, 1000, "perf", "libc", "free" },
{ 1000, 1000, "perf", "libc", "malloc" }, { 1000, 1000, "perf", "libc", "malloc" },
{ 1000, 1000, "bash", "bash", "xmalloc" },
}; };
struct callchain_result expected_callchain[] = { struct callchain_result expected_callchain[] = {
{ {
...@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
{ "bash", "main" }, }, { "bash", "main" }, },
}, },
{ {
3, { { "[kernel]", "schedule" }, 6, { { "bash", "xmalloc" },
{ "perf", "run_command" }, { "libc", "malloc" },
{ "perf", "main" }, }, { "bash", "xmalloc" },
{ "libc", "malloc" },
{ "bash", "xmalloc" },
{ "bash", "main" }, },
}, },
{ {
3, { { "[kernel]", "sys_perf_event_open" }, 3, { { "[kernel]", "sys_perf_event_open" },
...@@ -637,6 +640,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -637,6 +640,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
{ "perf", "run_command" }, { "perf", "run_command" },
{ "perf", "main" }, }, { "perf", "main" }, },
}, },
{
3, { { "[kernel]", "schedule" },
{ "perf", "run_command" },
{ "perf", "main" }, },
},
{ {
4, { { "libc", "free" }, 4, { { "libc", "free" },
{ "perf", "cmd_record" }, { "perf", "cmd_record" },
...@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) ...@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
{ "perf", "run_command" }, { "perf", "run_command" },
{ "perf", "main" }, }, { "perf", "main" }, },
}, },
{
6, { { "bash", "xmalloc" },
{ "libc", "malloc" },
{ "bash", "xmalloc" },
{ "libc", "malloc" },
{ "bash", "xmalloc" },
{ "bash", "main" }, },
},
}; };
symbol_conf.use_callchain = true; symbol_conf.use_callchain = true;
......
...@@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, ...@@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
bool need_percent; bool need_percent;
node = rb_first(root); node = rb_first(root);
need_percent = !!rb_next(node); need_percent = node && rb_next(node);
while (node) { while (node) {
struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
......
...@@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, ...@@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
if (ret) if (ret)
return ret; return ret;
if (a->thread != b->thread || !symbol_conf.use_callchain)
return 0;
ret = b->callchain->max_depth - a->callchain->max_depth; ret = b->callchain->max_depth - a->callchain->max_depth;
} }
return ret; return ret;
......
...@@ -841,3 +841,33 @@ char *callchain_list__sym_name(struct callchain_list *cl, ...@@ -841,3 +841,33 @@ char *callchain_list__sym_name(struct callchain_list *cl,
return bf; return bf;
} }
static void free_callchain_node(struct callchain_node *node)
{
struct callchain_list *list, *tmp;
struct callchain_node *child;
struct rb_node *n;
list_for_each_entry_safe(list, tmp, &node->val, list) {
list_del(&list->list);
free(list);
}
n = rb_first(&node->rb_root_in);
while (n) {
child = container_of(n, struct callchain_node, rb_node_in);
n = rb_next(n);
rb_erase(&child->rb_node_in, &node->rb_root_in);
free_callchain_node(child);
free(child);
}
}
void free_callchain(struct callchain_root *root)
{
if (!symbol_conf.use_callchain)
return;
free_callchain_node(&root->node);
}
...@@ -198,4 +198,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, ...@@ -198,4 +198,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
char *callchain_list__sym_name(struct callchain_list *cl, char *callchain_list__sym_name(struct callchain_list *cl,
char *bf, size_t bfsize, bool show_dso); char *bf, size_t bfsize, bool show_dso);
void free_callchain(struct callchain_root *root);
#endif /* __PERF_CALLCHAIN_H */ #endif /* __PERF_CALLCHAIN_H */
...@@ -947,6 +947,7 @@ void hist_entry__free(struct hist_entry *he) ...@@ -947,6 +947,7 @@ void hist_entry__free(struct hist_entry *he)
zfree(&he->mem_info); zfree(&he->mem_info);
zfree(&he->stat_acc); zfree(&he->stat_acc);
free_srcline(he->srcline); free_srcline(he->srcline);
free_callchain(he->callchain);
free(he); free(he);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment