Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf lock contention: Constify control data for BPF

The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.

Committer testing:

root@x1:~# perf lock contention --use-bpf
contended total wait max wait avg wait type caller

5 31.57 us 14.93 us 6.31 us mutex btrfs_delayed_update_inode+0x43
1 16.91 us 16.91 us 16.91 us rwsem:R btrfs_tree_read_lock_nested+0x1b
1 15.13 us 15.13 us 15.13 us spinlock btrfs_getattr+0xd1
1 6.65 us 6.65 us 6.65 us rwsem:R btrfs_tree_read_lock_nested+0x1b
1 4.34 us 4.34 us 4.34 us spinlock process_one_work+0x1a9
root@x1:~#
root@x1:~# perf trace -e bpf --max-events 10 perf lock contention --use-bpf
0.000 ( 0.013 ms): :2948281/2948281 bpf(cmd: 36, uattr: 0x7ffd5f12d730, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.024 ( 0.120 ms): :2948281/2948281 bpf(cmd: PROG_LOAD, uattr: 0x7ffd5f12d460, size: 148) = 16
0.158 ( 0.034 ms): :2948281/2948281 bpf(cmd: PROG_LOAD, uattr: 0x7ffd5f12d520, size: 148) = 16
26.653 ( 0.154 ms): perf/2948281 bpf(cmd: PROG_LOAD, uattr: 0x7ffd5f12d3d0, size: 148) = 16
26.825 ( 0.014 ms): perf/2948281 bpf(uattr: 0x7ffd5f12d580, size: 80) = 16
87.924 ( 0.038 ms): perf/2948281 bpf(cmd: BTF_LOAD, uattr: 0x7ffd5f12d400, size: 40) = 16
87.988 ( 0.006 ms): perf/2948281 bpf(cmd: BTF_LOAD, uattr: 0x7ffd5f12d470, size: 40) = 16
88.019 ( 0.006 ms): perf/2948281 bpf(cmd: BTF_LOAD, uattr: 0x7ffd5f12d250, size: 40) = 16
88.029 ( 0.172 ms): perf/2948281 bpf(cmd: PROG_LOAD, uattr: 0x7ffd5f12d320, size: 148) = 17
88.217 ( 0.005 ms): perf/2948281 bpf(cmd: BTF_LOAD, uattr: 0x7ffd5f12d4d0, size: 40) = 16
root@x1:~#

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-5-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
4afdc00c 066fd840

+38 -34
+24 -21
tools/perf/util/bpf_lock_contention.c
··· 46 46 else 47 47 bpf_map__set_max_entries(skel->maps.stacks, 1); 48 48 49 - if (target__has_cpu(target)) 49 + if (target__has_cpu(target)) { 50 + skel->rodata->has_cpu = 1; 50 51 ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus); 51 - if (target__has_task(target)) 52 + } 53 + if (target__has_task(target)) { 54 + skel->rodata->has_task = 1; 52 55 ntasks = perf_thread_map__nr(evlist->core.threads); 53 - if (con->filters->nr_types) 56 + } 57 + if (con->filters->nr_types) { 58 + skel->rodata->has_type = 1; 54 59 ntypes = con->filters->nr_types; 55 - if (con->filters->nr_cgrps) 60 + } 61 + if (con->filters->nr_cgrps) { 62 + skel->rodata->has_cgroup = 1; 56 63 ncgrps = con->filters->nr_cgrps; 64 + } 57 65 58 66 /* resolve lock name filters to addr */ 59 67 if (con->filters->nr_syms) { ··· 90 82 con->filters->addrs = addrs; 91 83 } 92 84 naddrs = con->filters->nr_addrs; 85 + skel->rodata->has_addr = 1; 93 86 } 94 87 95 88 bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus); ··· 98 89 bpf_map__set_max_entries(skel->maps.type_filter, ntypes); 99 90 bpf_map__set_max_entries(skel->maps.addr_filter, naddrs); 100 91 bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps); 92 + 93 + skel->rodata->stack_skip = con->stack_skip; 94 + skel->rodata->aggr_mode = con->aggr_mode; 95 + skel->rodata->needs_callstack = con->save_callstack; 96 + skel->rodata->lock_owner = con->owner; 97 + 98 + if (con->aggr_mode == LOCK_AGGR_CGROUP || con->filters->nr_cgrps) { 99 + if (cgroup_is_v2("perf_event")) 100 + skel->rodata->use_cgroup_v2 = 1; 101 + } 101 102 102 103 if (lock_contention_bpf__load(skel) < 0) { 103 104 pr_err("Failed to load lock-contention BPF skeleton\n"); ··· 118 99 u32 cpu; 119 100 u8 val = 1; 120 101 121 - skel->bss->has_cpu = 1; 122 102 fd = bpf_map__fd(skel->maps.cpu_filter); 123 103 124 104 for (i = 0; i < ncpus; i++) { ··· 130 112 u32 pid; 131 113 u8 val = 1; 132 114 133 - skel->bss->has_task = 1; 134 115 fd = bpf_map__fd(skel->maps.task_filter); 135 116 136 117 for (i = 0; i < ntasks; i++) { ··· 142 125 u32 pid = evlist->workload.pid; 143 126 u8 val = 1; 144 127 145 - skel->bss->has_task = 1; 146 128 fd = bpf_map__fd(skel->maps.task_filter); 147 129 bpf_map_update_elem(fd, &pid, &val, BPF_ANY); 148 130 } ··· 149 133 if (con->filters->nr_types) { 150 134 u8 val = 1; 151 135 152 - skel->bss->has_type = 1; 153 136 fd = bpf_map__fd(skel->maps.type_filter); 154 137 155 138 for (i = 0; i < con->filters->nr_types; i++) ··· 158 143 if (con->filters->nr_addrs) { 159 144 u8 val = 1; 160 145 161 - skel->bss->has_addr = 1; 162 146 fd = bpf_map__fd(skel->maps.addr_filter); 163 147 164 148 for (i = 0; i < con->filters->nr_addrs; i++) ··· 167 153 if (con->filters->nr_cgrps) { 168 154 u8 val = 1; 169 155 170 - skel->bss->has_cgroup = 1; 171 156 fd = bpf_map__fd(skel->maps.cgroup_filter); 172 157 173 158 for (i = 0; i < con->filters->nr_cgrps; i++) 174 159 bpf_map_update_elem(fd, &con->filters->cgrps[i], &val, BPF_ANY); 175 160 } 176 161 177 - /* these don't work well if in the rodata section */ 178 - skel->bss->stack_skip = con->stack_skip; 179 - skel->bss->aggr_mode = con->aggr_mode; 180 - skel->bss->needs_callstack = con->save_callstack; 181 - skel->bss->lock_owner = con->owner; 182 - 183 - if (con->aggr_mode == LOCK_AGGR_CGROUP) { 184 - if (cgroup_is_v2("perf_event")) 185 - skel->bss->use_cgroup_v2 = 1; 186 - 162 + if (con->aggr_mode == LOCK_AGGR_CGROUP) 187 163 read_all_cgroups(&con->cgroups); 188 - } 189 164 190 165 bpf_program__set_autoload(skel->progs.collect_lock_syms, false); 191 166
+14 -13
tools/perf/util/bpf_skel/lock_contention.bpf.c
··· 117 117 } __attribute__((preserve_access_index)); 118 118 119 119 /* control flags */ 120 - int enabled; 121 - int has_cpu; 122 - int has_task; 123 - int has_type; 124 - int has_addr; 125 - int has_cgroup; 126 - int needs_callstack; 127 - int stack_skip; 128 - int lock_owner; 129 - 130 - int use_cgroup_v2; 131 - int perf_subsys_id = -1; 120 + const volatile int has_cpu; 121 + const volatile int has_task; 122 + const volatile int has_type; 123 + const volatile int has_addr; 124 + const volatile int has_cgroup; 125 + const volatile int needs_callstack; 126 + const volatile int stack_skip; 127 + const volatile int lock_owner; 128 + const volatile int use_cgroup_v2; 132 129 133 130 /* determine the key of lock stat */ 134 - int aggr_mode; 131 + const volatile int aggr_mode; 132 + 133 + int enabled; 134 + 135 + int perf_subsys_id = -1; 135 136 136 137 __u64 end_ts; 137 138