Likewise, add type_filter BPF hash map and check it when user gave a lock type filter. $ sudo ./perf lock con -ab -Y rwlock -- ./perf bench sched messaging # Running 'sched/messaging' benchmark: # 20 sender and receiver processes per group # 10 groups == 400 processes run Total time: 0.203 [sec] contended total wait max wait avg wait type caller 15 156.19 us 19.45 us 10.41 us rwlock:W do_exit+0x36d 1 11.12 us 11.12 us 11.12 us rwlock:R do_wait+0x8b 1 5.09 us 5.09 us 5.09 us rwlock:W release_task+0x6e Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx> --- tools/perf/builtin-lock.c | 1 + tools/perf/util/bpf_lock_contention.c | 15 ++++++++++++- .../perf/util/bpf_skel/lock_contention.bpf.c | 21 +++++++++++++++++-- tools/perf/util/lock-contention.h | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 49b4add53204..e4e785d3b4ec 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -1689,6 +1689,7 @@ static int __cmd_contention(int argc, const char **argv) .map_nr_entries = bpf_map_entries, .max_stack = max_stack_depth, .stack_skip = stack_skip, + .filters = &filters, }; session = perf_session__new(use_bpf ? NULL : &data, &eops); diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c index 8e1b791dc58f..b8590b82ad3d 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -20,7 +20,7 @@ static struct lock_contention_bpf *skel; int lock_contention_prepare(struct lock_contention *con) { int i, fd; - int ncpus = 1, ntasks = 1; + int ncpus = 1, ntasks = 1, ntypes = 1; struct evlist *evlist = con->evlist; struct target *target = con->target; @@ -46,9 +46,12 @@ int lock_contention_prepare(struct lock_contention *con) ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus); if (target__has_task(target)) ntasks = perf_thread_map__nr(evlist->core.threads); + if (con->filters->nr_types) + ntypes = con->filters->nr_types; bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus); bpf_map__set_max_entries(skel->maps.task_filter, ntasks); + bpf_map__set_max_entries(skel->maps.type_filter, ntypes); if (lock_contention_bpf__load(skel) < 0) { pr_err("Failed to load lock-contention BPF skeleton\n"); @@ -90,6 +93,16 @@ int lock_contention_prepare(struct lock_contention *con) bpf_map_update_elem(fd, &pid, &val, BPF_ANY); } + if (con->filters->nr_types) { + u8 val = 1; + + skel->bss->has_type = 1; + fd = bpf_map__fd(skel->maps.type_filter); + + for (i = 0; i < con->filters->nr_types; i++) + bpf_map_update_elem(fd, &con->filters->types[i], &val, BPF_ANY); + } + /* these don't work well if in the rodata section */ skel->bss->stack_skip = con->stack_skip; skel->bss->aggr_mode = con->aggr_mode; diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index 11b0fc7ee53b..fb0128de7c00 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -62,10 +62,18 @@ struct { __uint(max_entries, 1); } task_filter SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} type_filter SEC(".maps"); + /* control flags */ int enabled; int has_cpu; int has_task; +int has_type; int stack_skip; /* determine the key of lock stat */ @@ -74,7 +82,7 @@ int aggr_mode; /* error stat */ int lost; -static inline int can_record(void) +static inline int can_record(u64 *ctx) { if (has_cpu) { __u32 cpu = bpf_get_smp_processor_id(); @@ -94,6 +102,15 @@ static inline int can_record(void) return 0; } + if (has_type) { + __u8 *ok; + __u32 flags = (__u32)ctx[1]; + + ok = bpf_map_lookup_elem(&type_filter, &flags); + if (!ok) + return 0; + } + return 1; } @@ -116,7 +133,7 @@ int contention_begin(u64 *ctx) __u32 pid; struct tstamp_data *pelem; - if (!enabled || !can_record()) + if (!enabled || !can_record(ctx)) return 0; pid = bpf_get_current_pid_tgid(); diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.h index d5b75b222d8e..dc621386a16b 100644 --- a/tools/perf/util/lock-contention.h +++ b/tools/perf/util/lock-contention.h @@ -118,6 +118,7 @@ struct lock_contention { struct target *target; struct machine *machine; struct hlist_head *result; + struct lock_filter *filters; unsigned long map_nr_entries; int lost; int max_stack; -- 2.39.0.314.g84b9a713c41-goog