summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2022-07-29 23:07:56 +0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2022-08-01 15:28:51 +0300
commit6fda2405f414b24a6d4fc74f2b1ab24b7fe00d14 (patch)
tree11506bea5fe13fbbcd2dac6f0a12b70d969a0a43 /tools/perf/util
parent407b36f69efbdccf341ccc5be6a366ec0795aa83 (diff)
downloadlinux-6fda2405f414b24a6d4fc74f2b1ab24b7fe00d14.tar.xz
perf lock: Implement cpu and task filters for BPF
Add -a/--all-cpus and -C/--cpu options for cpu filtering. Also -p/--pid and --tid options are added for task filtering. The short -t option is taken for --threads already. Tracking the command line workload is possible as well. $ sudo perf lock contention -a -b sleep 1 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Blake Jones <blakejones@google.com> Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Waiman Long <longman@redhat.com> Cc: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20220729200756.666106-4-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/bpf_lock_contention.c51
-rw-r--r--tools/perf/util/bpf_skel/lock_contention.bpf.c41
-rw-r--r--tools/perf/util/lock-contention.h11
3 files changed, 99 insertions, 4 deletions
diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
index 8eb33e6f5029..16b7451b4b09 100644
--- a/tools/perf/util/bpf_lock_contention.c
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
#include "util/debug.h"
+#include "util/evlist.h"
#include "util/machine.h"
#include "util/map.h"
#include "util/symbol.h"
+#include "util/target.h"
+#include "util/thread_map.h"
#include "util/lock-contention.h"
#include <linux/zalloc.h>
#include <bpf/bpf.h>
@@ -24,19 +27,65 @@ struct lock_contention_data {
u32 flags;
};
-int lock_contention_prepare(void)
+int lock_contention_prepare(struct evlist *evlist, struct target *target)
{
+ int i, fd;
+ int ncpus = 1, ntasks = 1;
+
skel = lock_contention_bpf__open();
if (!skel) {
pr_err("Failed to open lock-contention BPF skeleton\n");
return -1;
}
+ if (target__has_cpu(target))
+ ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus);
+ if (target__has_task(target))
+ ntasks = perf_thread_map__nr(evlist->core.threads);
+
+ bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus);
+ bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
+
if (lock_contention_bpf__load(skel) < 0) {
pr_err("Failed to load lock-contention BPF skeleton\n");
return -1;
}
+ if (target__has_cpu(target)) {
+ u32 cpu;
+ u8 val = 1;
+
+ skel->bss->has_cpu = 1;
+ fd = bpf_map__fd(skel->maps.cpu_filter);
+
+ for (i = 0; i < ncpus; i++) {
+ cpu = perf_cpu_map__cpu(evlist->core.user_requested_cpus, i).cpu;
+ bpf_map_update_elem(fd, &cpu, &val, BPF_ANY);
+ }
+ }
+
+ if (target__has_task(target)) {
+ u32 pid;
+ u8 val = 1;
+
+ skel->bss->has_task = 1;
+ fd = bpf_map__fd(skel->maps.task_filter);
+
+ for (i = 0; i < ntasks; i++) {
+ pid = perf_thread_map__pid(evlist->core.threads, i);
+ bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
+ }
+ }
+
+ if (target__none(target) && evlist->workload.pid > 0) {
+ u32 pid = evlist->workload.pid;
+ u8 val = 1;
+
+ skel->bss->has_task = 1;
+ fd = bpf_map__fd(skel->maps.task_filter);
+ bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
+ }
+
lock_contention_bpf__attach(skel);
return 0;
}
diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index 5d1c7641223f..67d46533e518 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -54,8 +54,47 @@ struct {
__uint(max_entries, MAX_ENTRIES);
} lock_stat SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u8));
+ __uint(max_entries, 1);
+} cpu_filter SEC(".maps");
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u8));
+ __uint(max_entries, 1);
+} task_filter SEC(".maps");
+
/* control flags */
int enabled;
+int has_cpu;
+int has_task;
+
+static inline int can_record(void)
+{
+ if (has_cpu) {
+ __u32 cpu = bpf_get_smp_processor_id();
+ __u8 *ok;
+
+ ok = bpf_map_lookup_elem(&cpu_filter, &cpu);
+ if (!ok)
+ return 0;
+ }
+
+ if (has_task) {
+ __u8 *ok;
+ __u32 pid = bpf_get_current_pid_tgid();
+
+ ok = bpf_map_lookup_elem(&task_filter, &pid);
+ if (!ok)
+ return 0;
+ }
+
+ return 1;
+}
SEC("tp_btf/contention_begin")
int contention_begin(u64 *ctx)
@@ -63,7 +102,7 @@ int contention_begin(u64 *ctx)
struct task_struct *curr;
struct tstamp_data *pelem;
- if (!enabled)
+ if (!enabled || !can_record())
return 0;
curr = bpf_get_current_task_btf();
diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.h
index c92db4a47d8d..092c84441f9f 100644
--- a/tools/perf/util/lock-contention.h
+++ b/tools/perf/util/lock-contention.h
@@ -103,11 +103,13 @@ struct thread_stat {
#define LCB_F_PERCPU (1U << 4)
#define LCB_F_MUTEX (1U << 5)
+struct evlist;
struct machine;
+struct target;
#ifdef HAVE_BPF_SKEL
-int lock_contention_prepare(void);
+int lock_contention_prepare(struct evlist *evlist, struct target *target);
int lock_contention_start(void);
int lock_contention_stop(void);
int lock_contention_read(struct machine *machine, struct hlist_head *head);
@@ -115,7 +117,12 @@ int lock_contention_finish(void);
#else /* !HAVE_BPF_SKEL */
-static inline int lock_contention_prepare(void) { return 0; }
+static inline int lock_contention_prepare(struct evlist *evlist __maybe_unused,
+ struct target *target __maybe_unused)
+{
+ return 0;
+}
+
static inline int lock_contention_start(void) { return 0; }
static inline int lock_contention_stop(void) { return 0; }
static inline int lock_contention_finish(void) { return 0; }