Commit 492fef21 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf lock contention: Factor out lock_contention_get_name()

The lock_contention_get_name() returns a name for the lock stat entry
based on the current aggregation mode.  As it's called sequentially in a
single thread, it can return the address of a static buffer for symbol
and offset of the caller.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Cc: bpf@vger.kernel.org
Link: https://lore.kernel.org/r/20230203021324.143540-2-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 7105311c
......@@ -163,9 +163,70 @@ int lock_contention_stop(void)
return 0;
}
static const char *lock_contention_get_name(struct lock_contention *con,
struct contention_key *key,
u64 *stack_trace)
{
int idx = 0;
u64 addr;
const char *name = "";
static char name_buf[KSYM_NAME_LEN];
struct symbol *sym;
struct map *kmap;
struct machine *machine = con->machine;
if (con->aggr_mode == LOCK_AGGR_TASK) {
struct contention_task_data task;
int pid = key->aggr_key;
int task_fd = bpf_map__fd(skel->maps.task_data);
/* do not update idle comm which contains CPU number */
if (pid) {
struct thread *t = __machine__findnew_thread(machine, /*pid=*/-1, pid);
if (t == NULL)
return name;
if (!bpf_map_lookup_elem(task_fd, &pid, &task) &&
thread__set_comm(t, task.comm, /*timestamp=*/0))
name = task.comm;
}
return name;
}
if (con->aggr_mode == LOCK_AGGR_ADDR) {
sym = machine__find_kernel_symbol(machine, key->aggr_key, &kmap);
if (sym)
name = sym->name;
return name;
}
/* LOCK_AGGR_CALLER: skip lock internal functions */
while (machine__is_lock_function(machine, stack_trace[idx]) &&
idx < con->max_stack - 1)
idx++;
addr = stack_trace[idx];
sym = machine__find_kernel_symbol(machine, addr, &kmap);
if (sym) {
unsigned long offset;
offset = kmap->map_ip(kmap, addr) - sym->start;
if (offset == 0)
return sym->name;
snprintf(name_buf, sizeof(name_buf), "%s+%#lx", sym->name, offset);
} else {
snprintf(name_buf, sizeof(name_buf), "%#lx", (unsigned long)addr);
}
return name_buf;
}
int lock_contention_read(struct lock_contention *con)
{
int fd, stack, task_fd, err = 0;
int fd, stack, err = 0;
struct contention_key *prev_key, key;
struct contention_data data = {};
struct lock_stat *st = NULL;
......@@ -175,7 +236,6 @@ int lock_contention_read(struct lock_contention *con)
fd = bpf_map__fd(skel->maps.lock_stat);
stack = bpf_map__fd(skel->maps.stacks);
task_fd = bpf_map__fd(skel->maps.task_data);
con->lost = skel->bss->lost;
......@@ -195,9 +255,6 @@ int lock_contention_read(struct lock_contention *con)
prev_key = NULL;
while (!bpf_map_get_next_key(fd, prev_key, &key)) {
struct map *kmap;
struct symbol *sym;
int idx = 0;
s32 stack_id;
/* to handle errors in the loop body */
......@@ -219,61 +276,19 @@ int lock_contention_read(struct lock_contention *con)
st->flags = data.flags;
st->addr = key.aggr_key;
if (con->aggr_mode == LOCK_AGGR_TASK) {
struct contention_task_data task;
struct thread *t;
int pid = key.aggr_key;
/* do not update idle comm which contains CPU number */
if (st->addr) {
bpf_map_lookup_elem(task_fd, &pid, &task);
t = __machine__findnew_thread(machine, /*pid=*/-1, pid);
thread__set_comm(t, task.comm, /*timestamp=*/0);
}
goto next;
}
if (con->aggr_mode == LOCK_AGGR_ADDR) {
sym = machine__find_kernel_symbol(machine, st->addr, &kmap);
if (sym)
st->name = strdup(sym->name);
goto next;
}
stack_id = key.aggr_key;
bpf_map_lookup_elem(stack, &stack_id, stack_trace);
/* skip lock internal functions */
while (machine__is_lock_function(machine, stack_trace[idx]) &&
idx < con->max_stack - 1)
idx++;
st->addr = stack_trace[idx];
sym = machine__find_kernel_symbol(machine, st->addr, &kmap);
if (sym) {
unsigned long offset;
int ret = 0;
offset = kmap->map_ip(kmap, st->addr) - sym->start;
if (offset)
ret = asprintf(&st->name, "%s+%#lx", sym->name, offset);
else
st->name = strdup(sym->name);
if (ret < 0 || st->name == NULL)
break;
} else if (asprintf(&st->name, "%#lx", (unsigned long)st->addr) < 0) {
st->name = strdup(lock_contention_get_name(con, &key, stack_trace));
if (st->name == NULL)
break;
}
if (con->save_callstack) {
st->callstack = memdup(stack_trace, stack_size);
if (st->callstack == NULL)
break;
}
next:
hlist_add_head(&st->hash_entry, con->result);
prev_key = &key;
......
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