Skip to content

Commit 492fef2

Browse files
namhyungacmel
authored andcommitted
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>
1 parent 7105311 commit 492fef2

1 file changed

Lines changed: 65 additions & 50 deletions

File tree

tools/perf/util/bpf_lock_contention.c

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,70 @@ int lock_contention_stop(void)
163163
return 0;
164164
}
165165

166+
static const char *lock_contention_get_name(struct lock_contention *con,
167+
struct contention_key *key,
168+
u64 *stack_trace)
169+
{
170+
int idx = 0;
171+
u64 addr;
172+
const char *name = "";
173+
static char name_buf[KSYM_NAME_LEN];
174+
struct symbol *sym;
175+
struct map *kmap;
176+
struct machine *machine = con->machine;
177+
178+
if (con->aggr_mode == LOCK_AGGR_TASK) {
179+
struct contention_task_data task;
180+
int pid = key->aggr_key;
181+
int task_fd = bpf_map__fd(skel->maps.task_data);
182+
183+
/* do not update idle comm which contains CPU number */
184+
if (pid) {
185+
struct thread *t = __machine__findnew_thread(machine, /*pid=*/-1, pid);
186+
187+
if (t == NULL)
188+
return name;
189+
if (!bpf_map_lookup_elem(task_fd, &pid, &task) &&
190+
thread__set_comm(t, task.comm, /*timestamp=*/0))
191+
name = task.comm;
192+
}
193+
return name;
194+
}
195+
196+
if (con->aggr_mode == LOCK_AGGR_ADDR) {
197+
sym = machine__find_kernel_symbol(machine, key->aggr_key, &kmap);
198+
if (sym)
199+
name = sym->name;
200+
return name;
201+
}
202+
203+
/* LOCK_AGGR_CALLER: skip lock internal functions */
204+
while (machine__is_lock_function(machine, stack_trace[idx]) &&
205+
idx < con->max_stack - 1)
206+
idx++;
207+
208+
addr = stack_trace[idx];
209+
sym = machine__find_kernel_symbol(machine, addr, &kmap);
210+
211+
if (sym) {
212+
unsigned long offset;
213+
214+
offset = kmap->map_ip(kmap, addr) - sym->start;
215+
216+
if (offset == 0)
217+
return sym->name;
218+
219+
snprintf(name_buf, sizeof(name_buf), "%s+%#lx", sym->name, offset);
220+
} else {
221+
snprintf(name_buf, sizeof(name_buf), "%#lx", (unsigned long)addr);
222+
}
223+
224+
return name_buf;
225+
}
226+
166227
int lock_contention_read(struct lock_contention *con)
167228
{
168-
int fd, stack, task_fd, err = 0;
229+
int fd, stack, err = 0;
169230
struct contention_key *prev_key, key;
170231
struct contention_data data = {};
171232
struct lock_stat *st = NULL;
@@ -175,7 +236,6 @@ int lock_contention_read(struct lock_contention *con)
175236

176237
fd = bpf_map__fd(skel->maps.lock_stat);
177238
stack = bpf_map__fd(skel->maps.stacks);
178-
task_fd = bpf_map__fd(skel->maps.task_data);
179239

180240
con->lost = skel->bss->lost;
181241

@@ -195,9 +255,6 @@ int lock_contention_read(struct lock_contention *con)
195255

196256
prev_key = NULL;
197257
while (!bpf_map_get_next_key(fd, prev_key, &key)) {
198-
struct map *kmap;
199-
struct symbol *sym;
200-
int idx = 0;
201258
s32 stack_id;
202259

203260
/* to handle errors in the loop body */
@@ -219,61 +276,19 @@ int lock_contention_read(struct lock_contention *con)
219276
st->flags = data.flags;
220277
st->addr = key.aggr_key;
221278

222-
if (con->aggr_mode == LOCK_AGGR_TASK) {
223-
struct contention_task_data task;
224-
struct thread *t;
225-
int pid = key.aggr_key;
226-
227-
/* do not update idle comm which contains CPU number */
228-
if (st->addr) {
229-
bpf_map_lookup_elem(task_fd, &pid, &task);
230-
t = __machine__findnew_thread(machine, /*pid=*/-1, pid);
231-
thread__set_comm(t, task.comm, /*timestamp=*/0);
232-
}
233-
goto next;
234-
}
235-
236-
if (con->aggr_mode == LOCK_AGGR_ADDR) {
237-
sym = machine__find_kernel_symbol(machine, st->addr, &kmap);
238-
if (sym)
239-
st->name = strdup(sym->name);
240-
goto next;
241-
}
242-
243279
stack_id = key.aggr_key;
244280
bpf_map_lookup_elem(stack, &stack_id, stack_trace);
245281

246-
/* skip lock internal functions */
247-
while (machine__is_lock_function(machine, stack_trace[idx]) &&
248-
idx < con->max_stack - 1)
249-
idx++;
250-
251-
st->addr = stack_trace[idx];
252-
sym = machine__find_kernel_symbol(machine, st->addr, &kmap);
253-
254-
if (sym) {
255-
unsigned long offset;
256-
int ret = 0;
257-
258-
offset = kmap->map_ip(kmap, st->addr) - sym->start;
259-
260-
if (offset)
261-
ret = asprintf(&st->name, "%s+%#lx", sym->name, offset);
262-
else
263-
st->name = strdup(sym->name);
264-
265-
if (ret < 0 || st->name == NULL)
266-
break;
267-
} else if (asprintf(&st->name, "%#lx", (unsigned long)st->addr) < 0) {
282+
st->name = strdup(lock_contention_get_name(con, &key, stack_trace));
283+
if (st->name == NULL)
268284
break;
269-
}
270285

271286
if (con->save_callstack) {
272287
st->callstack = memdup(stack_trace, stack_size);
273288
if (st->callstack == NULL)
274289
break;
275290
}
276-
next:
291+
277292
hlist_add_head(&st->hash_entry, con->result);
278293
prev_key = &key;
279294

0 commit comments

Comments
 (0)