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.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent bbf86c43
...@@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample) ...@@ -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); 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); callchain_cursor_commit(&callchain_cursor);
while (true) { while (true) {
......
...@@ -788,7 +788,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor, ...@@ -788,7 +788,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
return 0; 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, struct perf_evsel *evsel, struct addr_location *al,
int max_stack) int max_stack)
{ {
...@@ -797,7 +798,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent ...@@ -797,7 +798,7 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
sort__has_parent) { sort__has_parent) {
return thread__resolve_callchain(al->thread, evsel, sample, return thread__resolve_callchain(al->thread, cursor, evsel, sample,
parent, al, max_stack); parent, al, max_stack);
} }
return 0; return 0;
......
...@@ -212,7 +212,8 @@ struct hist_entry; ...@@ -212,7 +212,8 @@ struct hist_entry;
int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 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 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, struct perf_evsel *evsel, struct addr_location *al,
int max_stack); int max_stack);
int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); 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 * ...@@ -2349,6 +2349,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
FILE *fp) FILE *fp)
{ {
int printed = 0; int printed = 0;
struct callchain_cursor cursor;
struct callchain_cursor_node *node; struct callchain_cursor_node *node;
int print_ip = print_opts & EVSEL__PRINT_IP; int print_ip = print_opts & EVSEL__PRINT_IP;
int print_sym = print_opts & EVSEL__PRINT_SYM; int print_sym = print_opts & EVSEL__PRINT_SYM;
...@@ -2362,14 +2363,14 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * ...@@ -2362,14 +2363,14 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
if (sample->callchain) { if (sample->callchain) {
struct addr_location node_al; struct addr_location node_al;
if (thread__resolve_callchain(al->thread, evsel, if (thread__resolve_callchain(al->thread, &cursor, evsel,
sample, NULL, NULL, sample, NULL, NULL,
stack_depth) != 0) { stack_depth) != 0) {
if (verbose) if (verbose)
error("Failed to resolve callchain. Skipping\n"); error("Failed to resolve callchain. Skipping\n");
return printed; return printed;
} }
callchain_cursor_commit(&callchain_cursor); callchain_cursor_commit(&cursor);
if (print_symoffset) if (print_symoffset)
node_al = *al; node_al = *al;
...@@ -2377,7 +2378,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * ...@@ -2377,7 +2378,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
while (stack_depth) { while (stack_depth) {
u64 addr = 0; u64 addr = 0;
node = callchain_cursor_current(&callchain_cursor); node = callchain_cursor_current(&cursor);
if (!node) if (!node)
break; break;
...@@ -2420,7 +2421,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample * ...@@ -2420,7 +2421,7 @@ int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *
stack_depth--; stack_depth--;
next: 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, ...@@ -953,7 +953,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
{ {
int err, err2; 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); iter->evsel, al, max_stack_depth);
if (err) if (err)
return err; return err;
......
...@@ -1599,6 +1599,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, ...@@ -1599,6 +1599,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
} }
static int add_callchain_ip(struct thread *thread, static int add_callchain_ip(struct thread *thread,
struct callchain_cursor *cursor,
struct symbol **parent, struct symbol **parent,
struct addr_location *root_al, struct addr_location *root_al,
u8 *cpumode, u8 *cpumode,
...@@ -1630,7 +1631,7 @@ static int add_callchain_ip(struct thread *thread, ...@@ -1630,7 +1631,7 @@ static int add_callchain_ip(struct thread *thread,
* It seems the callchain is corrupted. * It seems the callchain is corrupted.
* Discard all. * Discard all.
*/ */
callchain_cursor_reset(&callchain_cursor); callchain_cursor_reset(cursor);
return 1; return 1;
} }
return 0; return 0;
...@@ -1648,13 +1649,13 @@ static int add_callchain_ip(struct thread *thread, ...@@ -1648,13 +1649,13 @@ static int add_callchain_ip(struct thread *thread,
/* Treat this symbol as the root, /* Treat this symbol as the root,
forgetting its callees. */ forgetting its callees. */
*root_al = al; *root_al = al;
callchain_cursor_reset(&callchain_cursor); callchain_cursor_reset(cursor);
} }
} }
if (symbol_conf.hide_unresolved && al.sym == NULL) if (symbol_conf.hide_unresolved && al.sym == NULL)
return 0; 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, struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
...@@ -1724,6 +1725,7 @@ static int remove_loops(struct branch_entry *l, int nr) ...@@ -1724,6 +1725,7 @@ static int remove_loops(struct branch_entry *l, int nr)
* negative error code on other errors. * negative error code on other errors.
*/ */
static int resolve_lbr_callchain_sample(struct thread *thread, static int resolve_lbr_callchain_sample(struct thread *thread,
struct callchain_cursor *cursor,
struct perf_sample *sample, struct perf_sample *sample,
struct symbol **parent, struct symbol **parent,
struct addr_location *root_al, struct addr_location *root_al,
...@@ -1778,7 +1780,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, ...@@ -1778,7 +1780,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
ip = lbr_stack->entries[0].to; 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) if (err)
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
} }
...@@ -1789,6 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, ...@@ -1789,6 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
} }
static int thread__resolve_callchain_sample(struct thread *thread, static int thread__resolve_callchain_sample(struct thread *thread,
struct callchain_cursor *cursor,
struct perf_evsel *evsel, struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
struct symbol **parent, struct symbol **parent,
...@@ -1803,10 +1806,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, ...@@ -1803,10 +1806,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
int skip_idx = -1; int skip_idx = -1;
int first_call = 0; int first_call = 0;
callchain_cursor_reset(&callchain_cursor); callchain_cursor_reset(cursor);
if (has_branch_callstack(evsel)) { 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); root_al, max_stack);
if (err) if (err)
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
...@@ -1863,10 +1866,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, ...@@ -1863,10 +1866,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
nr = remove_loops(be, nr); nr = remove_loops(be, nr);
for (i = 0; i < nr; i++) { 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); NULL, be[i].to);
if (!err) if (!err)
err = add_callchain_ip(thread, parent, root_al, err = add_callchain_ip(thread, cursor, parent, root_al,
NULL, be[i].from); NULL, be[i].from);
if (err == -EINVAL) if (err == -EINVAL)
break; break;
...@@ -1896,7 +1899,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, ...@@ -1896,7 +1899,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
#endif #endif
ip = chain->ips[j]; 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) if (err)
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
...@@ -1916,13 +1919,14 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) ...@@ -1916,13 +1919,14 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
} }
int thread__resolve_callchain(struct thread *thread, int thread__resolve_callchain(struct thread *thread,
struct callchain_cursor *cursor,
struct perf_evsel *evsel, struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
struct symbol **parent, struct symbol **parent,
struct addr_location *root_al, struct addr_location *root_al,
int max_stack) int max_stack)
{ {
int ret = thread__resolve_callchain_sample(thread, evsel, int ret = thread__resolve_callchain_sample(thread, cursor, evsel,
sample, parent, sample, parent,
root_al, max_stack); root_al, max_stack);
if (ret) if (ret)
...@@ -1938,7 +1942,7 @@ int thread__resolve_callchain(struct thread *thread, ...@@ -1938,7 +1942,7 @@ int thread__resolve_callchain(struct thread *thread,
(!sample->user_stack.size)) (!sample->user_stack.size))
return 0; return 0;
return unwind__get_entries(unwind_entry, &callchain_cursor, return unwind__get_entries(unwind_entry, cursor,
thread, sample, max_stack); thread, sample, max_stack);
} }
......
...@@ -141,7 +141,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, ...@@ -141,7 +141,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
struct addr_location *al); struct addr_location *al);
struct mem_info *sample__resolve_mem(struct perf_sample *sample, struct mem_info *sample__resolve_mem(struct perf_sample *sample,
struct addr_location *al); struct addr_location *al);
struct callchain_cursor;
int thread__resolve_callchain(struct thread *thread, int thread__resolve_callchain(struct thread *thread,
struct callchain_cursor *cursor,
struct perf_evsel *evsel, struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
struct symbol **parent, struct symbol **parent,
......
...@@ -263,7 +263,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, ...@@ -263,7 +263,7 @@ static SV *perl_process_callchain(struct perf_sample *sample,
if (!symbol_conf.use_callchain || !sample->callchain) if (!symbol_conf.use_callchain || !sample->callchain)
goto exit; goto exit;
if (thread__resolve_callchain(al->thread, evsel, if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
sample, NULL, NULL, sample, NULL, NULL,
PERF_MAX_STACK_DEPTH) != 0) { PERF_MAX_STACK_DEPTH) != 0) {
pr_err("Failed to resolve callchain. Skipping\n"); pr_err("Failed to resolve callchain. Skipping\n");
......
...@@ -323,7 +323,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, ...@@ -323,7 +323,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
if (!symbol_conf.use_callchain || !sample->callchain) if (!symbol_conf.use_callchain || !sample->callchain)
goto exit; goto exit;
if (thread__resolve_callchain(al->thread, evsel, if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
sample, NULL, NULL, sample, NULL, NULL,
scripting_max_stack) != 0) { scripting_max_stack) != 0) {
pr_err("Failed to resolve callchain. Skipping\n"); pr_err("Failed to resolve callchain. Skipping\n");
......
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