mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 22:22:08 +02:00
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: Namhyung 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.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
7105311c2d
commit
492fef218a
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user