perf callchain: Start moving away from global per thread cursors
The recent perf_evsel__fprintf_callchain() move to evsel.c added several new symbol requirements to the python binding, for instance: # perf test -v python 16: Try 'import perf' in python, checking link problems : --- start --- test child forked, pid 18030 Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: /tmp/build/perf/python/perf.so: undefined symbol: callchain_cursor test child finished with -1 ---- end ---- Try 'import perf' in python, checking link problems: FAILED! # This would require linking against callchain.c to access to the global callchain_cursor variables. Since lots of functions already receive as a parameter a callchain_cursor struct pointer, make that be the case for some more function so that we can start phasing out usage of yet another global variable. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/n/tip-djko3097eyg2rn66v2qcqfvn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
bbf86c43ea
commit
91d7b2de31
@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
|
||||
}
|
||||
|
||||
al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);
|
||||
sample__resolve_callchain(sample, NULL, evsel, &al, 16);
|
||||
sample__resolve_callchain(sample, &callchain_cursor, NULL, evsel, &al, 16);
|
||||
|
||||
callchain_cursor_commit(&callchain_cursor);
|
||||
while (true) {
|
||||
|
@ -788,7 +788,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
|
||||
int sample__resolve_callchain(struct perf_sample *sample,
|
||||
struct callchain_cursor *cursor, struct symbol **parent,
|
||||
struct perf_evsel *evsel, struct addr_location *al,
|
||||
int max_stack)
|
||||
{
|
||||
@ -797,7 +798,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
|
||||
|
||||
if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
|
||||
sort__has_parent) {
|
||||
return thread__resolve_callchain(al->thread, evsel, sample,
|
||||
return thread__resolve_callchain(al->thread, cursor, evsel, sample,
|
||||
parent, al, max_stack);
|
||||
}
|
||||
return 0;
|
||||
|
@ -212,7 +212,8 @@ struct hist_entry;
|
||||
int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
|
||||
int record_callchain_opt(const struct option *opt, const char *arg, int unset);
|
||||
|
||||
int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
|
||||
int sample__resolve_callchain(struct perf_sample *sample,
|
||||
struct callchain_cursor *cursor, struct symbol **parent,
|
||||
struct perf_evsel *evsel, struct addr_location *al,
|
||||
int max_stack);
|
||||
int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
|
||||
|
@ -2349,6 +2349,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
|
||||
FILE *fp)
|
||||
{
|
||||
int printed = 0;
|
||||
struct callchain_cursor cursor;
|
||||
struct callchain_cursor_node *node;
|
||||
int print_ip = print_opts & EVSEL__PRINT_IP;
|
||||
int print_sym = print_opts & EVSEL__PRINT_SYM;
|
||||
@ -2362,14 +2363,14 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
|
||||
if (sample->callchain) {
|
||||
struct addr_location node_al;
|
||||
|
||||
if (thread__resolve_callchain(al->thread, evsel,
|
||||
if (thread__resolve_callchain(al->thread, &cursor, evsel,
|
||||
sample, NULL, NULL,
|
||||
stack_depth) != 0) {
|
||||
if (verbose)
|
||||
error("Failed to resolve callchain. Skipping\n");
|
||||
return printed;
|
||||
}
|
||||
callchain_cursor_commit(&callchain_cursor);
|
||||
callchain_cursor_commit(&cursor);
|
||||
|
||||
if (print_symoffset)
|
||||
node_al = *al;
|
||||
@ -2377,7 +2378,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
|
||||
while (stack_depth) {
|
||||
u64 addr = 0;
|
||||
|
||||
node = callchain_cursor_current(&callchain_cursor);
|
||||
node = callchain_cursor_current(&cursor);
|
||||
if (!node)
|
||||
break;
|
||||
|
||||
@ -2420,7 +2421,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
|
||||
|
||||
stack_depth--;
|
||||
next:
|
||||
callchain_cursor_advance(&callchain_cursor);
|
||||
callchain_cursor_advance(&cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -953,7 +953,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
|
||||
{
|
||||
int err, err2;
|
||||
|
||||
err = sample__resolve_callchain(iter->sample, &iter->parent,
|
||||
err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
|
||||
iter->evsel, al, max_stack_depth);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -1599,6 +1599,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
||||
}
|
||||
|
||||
static int add_callchain_ip(struct thread *thread,
|
||||
struct callchain_cursor *cursor,
|
||||
struct symbol **parent,
|
||||
struct addr_location *root_al,
|
||||
u8 *cpumode,
|
||||
@ -1630,7 +1631,7 @@ static int add_callchain_ip(struct thread *thread,
|
||||
* It seems the callchain is corrupted.
|
||||
* Discard all.
|
||||
*/
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
callchain_cursor_reset(cursor);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -1648,13 +1649,13 @@ static int add_callchain_ip(struct thread *thread,
|
||||
/* Treat this symbol as the root,
|
||||
forgetting its callees. */
|
||||
*root_al = al;
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
callchain_cursor_reset(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol_conf.hide_unresolved && al.sym == NULL)
|
||||
return 0;
|
||||
return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
|
||||
return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
|
||||
}
|
||||
|
||||
struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
|
||||
@ -1724,6 +1725,7 @@ static int remove_loops(struct branch_entry *l, int nr)
|
||||
* negative error code on other errors.
|
||||
*/
|
||||
static int resolve_lbr_callchain_sample(struct thread *thread,
|
||||
struct callchain_cursor *cursor,
|
||||
struct perf_sample *sample,
|
||||
struct symbol **parent,
|
||||
struct addr_location *root_al,
|
||||
@ -1778,7 +1780,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
|
||||
ip = lbr_stack->entries[0].to;
|
||||
}
|
||||
|
||||
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
|
||||
err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
|
||||
if (err)
|
||||
return (err < 0) ? err : 0;
|
||||
}
|
||||
@ -1789,6 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
|
||||
}
|
||||
|
||||
static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
struct callchain_cursor *cursor,
|
||||
struct perf_evsel *evsel,
|
||||
struct perf_sample *sample,
|
||||
struct symbol **parent,
|
||||
@ -1803,10 +1806,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
int skip_idx = -1;
|
||||
int first_call = 0;
|
||||
|
||||
callchain_cursor_reset(&callchain_cursor);
|
||||
callchain_cursor_reset(cursor);
|
||||
|
||||
if (has_branch_callstack(evsel)) {
|
||||
err = resolve_lbr_callchain_sample(thread, sample, parent,
|
||||
err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
|
||||
root_al, max_stack);
|
||||
if (err)
|
||||
return (err < 0) ? err : 0;
|
||||
@ -1863,10 +1866,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
nr = remove_loops(be, nr);
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
err = add_callchain_ip(thread, parent, root_al,
|
||||
err = add_callchain_ip(thread, cursor, parent, root_al,
|
||||
NULL, be[i].to);
|
||||
if (!err)
|
||||
err = add_callchain_ip(thread, parent, root_al,
|
||||
err = add_callchain_ip(thread, cursor, parent, root_al,
|
||||
NULL, be[i].from);
|
||||
if (err == -EINVAL)
|
||||
break;
|
||||
@ -1896,7 +1899,7 @@ check_calls:
|
||||
#endif
|
||||
ip = chain->ips[j];
|
||||
|
||||
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
|
||||
err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
|
||||
|
||||
if (err)
|
||||
return (err < 0) ? err : 0;
|
||||
@ -1916,13 +1919,14 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
|
||||
}
|
||||
|
||||
int thread__resolve_callchain(struct thread *thread,
|
||||
struct callchain_cursor *cursor,
|
||||
struct perf_evsel *evsel,
|
||||
struct perf_sample *sample,
|
||||
struct symbol **parent,
|
||||
struct addr_location *root_al,
|
||||
int max_stack)
|
||||
{
|
||||
int ret = thread__resolve_callchain_sample(thread, evsel,
|
||||
int ret = thread__resolve_callchain_sample(thread, cursor, evsel,
|
||||
sample, parent,
|
||||
root_al, max_stack);
|
||||
if (ret)
|
||||
@ -1938,7 +1942,7 @@ int thread__resolve_callchain(struct thread *thread,
|
||||
(!sample->user_stack.size))
|
||||
return 0;
|
||||
|
||||
return unwind__get_entries(unwind_entry, &callchain_cursor,
|
||||
return unwind__get_entries(unwind_entry, cursor,
|
||||
thread, sample, max_stack);
|
||||
|
||||
}
|
||||
|
@ -141,7 +141,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
|
||||
struct addr_location *al);
|
||||
struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
||||
struct addr_location *al);
|
||||
|
||||
struct callchain_cursor;
|
||||
|
||||
int thread__resolve_callchain(struct thread *thread,
|
||||
struct callchain_cursor *cursor,
|
||||
struct perf_evsel *evsel,
|
||||
struct perf_sample *sample,
|
||||
struct symbol **parent,
|
||||
|
@ -263,7 +263,7 @@ static SV *perl_process_callchain(struct perf_sample *sample,
|
||||
if (!symbol_conf.use_callchain || !sample->callchain)
|
||||
goto exit;
|
||||
|
||||
if (thread__resolve_callchain(al->thread, evsel,
|
||||
if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
|
||||
sample, NULL, NULL,
|
||||
PERF_MAX_STACK_DEPTH) != 0) {
|
||||
pr_err("Failed to resolve callchain. Skipping\n");
|
||||
|
@ -323,7 +323,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
|
||||
if (!symbol_conf.use_callchain || !sample->callchain)
|
||||
goto exit;
|
||||
|
||||
if (thread__resolve_callchain(al->thread, evsel,
|
||||
if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
|
||||
sample, NULL, NULL,
|
||||
scripting_max_stack) != 0) {
|
||||
pr_err("Failed to resolve callchain. Skipping\n");
|
||||
|
Loading…
Reference in New Issue
Block a user