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:
Arnaldo Carvalho de Melo 2016-04-14 14:48:07 -03:00
parent bbf86c43ea
commit 91d7b2de31
9 changed files with 33 additions and 22 deletions

View File

@ -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) {

View File

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

View File

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

View File

@ -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);
}
}

View File

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

View File

@ -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 @@ static int thread__resolve_callchain_sample(struct thread *thread,
#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);
}

View File

@ -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,

View File

@ -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");

View File

@ -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");