From 2df270716447a1024a6c955eed8fa579333dca85 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Jun 2023 15:18:27 -0300 Subject: perf bench uprobe: Add benchmark to test uprobe overhead This just adds the initial "workload", a call to libc's usleep(1000us) function: $ perf stat --null perf bench uprobe all # Running uprobe/baseline benchmark... # Executed 1000 usleep(1000) calls Total time: 1053533 usecs 1053.533 usecs/op Performance counter stats for 'perf bench uprobe all': 1.061042896 seconds time elapsed 0.001079000 seconds user 0.006499000 seconds sys $ More entries will be added using a BPF skel to add various uprobes to the usleep() function. Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Andre Fredette Cc: Clark Williams Cc: Dave Tucker Cc: Derek Barbosa Cc: Jiri Olsa Cc: Masami Hiramatsu (Google) Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/20230719204910.539044-2-acme@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/Build | 1 + tools/perf/bench/bench.h | 1 + tools/perf/bench/uprobe.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 tools/perf/bench/uprobe.c (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build index 0f158dc8139b..47412d47dccf 100644 --- a/tools/perf/bench/Build +++ b/tools/perf/bench/Build @@ -16,6 +16,7 @@ perf-y += inject-buildid.o perf-y += evlist-open-close.o perf-y += breakpoint.o perf-y += pmu-scan.o +perf-y += uprobe.o perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index 0d2b65976212..201311f75c96 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h @@ -42,6 +42,7 @@ int bench_inject_build_id(int argc, const char **argv); int bench_evlist_open_close(int argc, const char **argv); int bench_breakpoint_thread(int argc, const char **argv); int bench_breakpoint_enable(int argc, const char **argv); +int bench_uprobe_baseline(int argc, const char **argv); int bench_pmu_scan(int argc, const char **argv); #define BENCH_FORMAT_DEFAULT_STR "default" diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c new file mode 100644 index 000000000000..707174220a76 --- /dev/null +++ b/tools/perf/bench/uprobe.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * uprobe.c + * + * uprobe benchmarks + * + * Copyright (C) 2023, Red Hat Inc, Arnaldo Carvalho de Melo + */ +#include "../perf.h" +#include "../util/util.h" +#include +#include "../builtin.h" +#include "bench.h" +#include + +#include +#include +#include +#include +#include +#include +#include + +#define LOOPS_DEFAULT 1000 +static int loops = LOOPS_DEFAULT; + +static const struct option options[] = { + OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), + OPT_END() +}; + +static const char * const bench_uprobe_usage[] = { + "perf bench uprobe ", + NULL +}; + +static int bench_uprobe(int argc, const char **argv) +{ + const char *name = "usleep(1000)", *unit = "usec"; + struct timespec start, end; + u64 diff; + int i; + + argc = parse_options(argc, argv, options, bench_uprobe_usage, 0); + + clock_gettime(CLOCK_REALTIME, &start); + + for (i = 0; i < loops; i++) { + usleep(USEC_PER_MSEC); + } + + clock_gettime(CLOCK_REALTIME, &end); + + diff = end.tv_sec * NSEC_PER_SEC + end.tv_nsec - (start.tv_sec * NSEC_PER_SEC + start.tv_nsec); + diff /= NSEC_PER_USEC; + + switch (bench_format) { + case BENCH_FORMAT_DEFAULT: + printf("# Executed %'d %s calls\n", loops, name); + printf(" %14s: %'" PRIu64 " %ss\n\n", "Total time", diff, unit); + printf(" %'.3f %ss/op\n", (double)diff / (double)loops, unit); + break; + + case BENCH_FORMAT_SIMPLE: + printf("%" PRIu64 "\n", diff); + break; + + default: + /* reaching here is something of a disaster */ + fprintf(stderr, "Unknown format:%d\n", bench_format); + exit(1); + } + + return 0; +} + +int bench_uprobe_baseline(int argc, const char **argv) +{ + return bench_uprobe(argc, argv); +} -- cgit v1.2.3 From dded6f615b854740461be63672fa05158875ffaa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 Jul 2023 08:45:12 -0300 Subject: perf bench uprobe: Print diff to baseline This is just prep work to show the diff to the unmodified workload. Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Andre Fredette Cc: Clark Williams Cc: Dave Tucker Cc: Derek Barbosa Cc: Jiri Olsa Cc: Masami Hiramatsu (Google) Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/20230719204910.539044-3-acme@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/uprobe.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index 707174220a76..60e7c43298d8 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -34,6 +34,29 @@ static const char * const bench_uprobe_usage[] = { NULL }; +static int bench_uprobe_format__default_fprintf(const char *name, const char *unit, u64 diff, FILE *fp) +{ + static u64 baseline; + s64 diff_to_baseline = diff - baseline; + int printed = fprintf(fp, "# Executed %'d %s calls\n", loops, name); + + printed += fprintf(fp, " %14s: %'" PRIu64 " %ss", "Total time", diff, unit); + + if (baseline) + printed += fprintf(fp, " %s%'" PRId64 " to baseline", diff_to_baseline > 0 ? "+" : "", diff_to_baseline); + + printed += fprintf(fp, "\n\n %'.3f %ss/op", (double)diff / (double)loops, unit); + + if (baseline) + printed += fprintf(fp, " %'.3f %ss/op to baseline", (double)diff_to_baseline / (double)loops, unit); + else + baseline = diff; + + fputc('\n', fp); + + return printed + 1; +} + static int bench_uprobe(int argc, const char **argv) { const char *name = "usleep(1000)", *unit = "usec"; @@ -56,9 +79,7 @@ static int bench_uprobe(int argc, const char **argv) switch (bench_format) { case BENCH_FORMAT_DEFAULT: - printf("# Executed %'d %s calls\n", loops, name); - printf(" %14s: %'" PRIu64 " %ss\n\n", "Total time", diff, unit); - printf(" %'.3f %ss/op\n", (double)diff / (double)loops, unit); + bench_uprobe_format__default_fprintf(name, unit, diff, stdout); break; case BENCH_FORMAT_SIMPLE: -- cgit v1.2.3 From 54d811023b5f99e658511b577b16a6d7014d162c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 Jul 2023 08:49:40 -0300 Subject: perf bench uprobe: Show diff to previous Will be useful to show the incremental overhead as we do more stuff in the BPF program attached to the uprobes. Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Andre Fredette Cc: Clark Williams Cc: Dave Tucker Cc: Derek Barbosa Cc: Jiri Olsa Cc: Masami Hiramatsu (Google) Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/20230719204910.539044-4-acme@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/uprobe.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index 60e7c43298d8..a90e09f791c5 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -36,24 +36,35 @@ static const char * const bench_uprobe_usage[] = { static int bench_uprobe_format__default_fprintf(const char *name, const char *unit, u64 diff, FILE *fp) { - static u64 baseline; - s64 diff_to_baseline = diff - baseline; + static u64 baseline, previous; + s64 diff_to_baseline = diff - baseline, + diff_to_previous = diff - previous; int printed = fprintf(fp, "# Executed %'d %s calls\n", loops, name); printed += fprintf(fp, " %14s: %'" PRIu64 " %ss", "Total time", diff, unit); - if (baseline) + if (baseline) { printed += fprintf(fp, " %s%'" PRId64 " to baseline", diff_to_baseline > 0 ? "+" : "", diff_to_baseline); + if (previous != baseline) + fprintf(stdout, " %s%'" PRId64 " to previous", diff_to_previous > 0 ? "+" : "", diff_to_previous); + } + printed += fprintf(fp, "\n\n %'.3f %ss/op", (double)diff / (double)loops, unit); - if (baseline) + if (baseline) { printed += fprintf(fp, " %'.3f %ss/op to baseline", (double)diff_to_baseline / (double)loops, unit); - else + + if (previous != baseline) + printed += fprintf(fp, " %'.3f %ss/op to previous", (double)diff_to_previous / (double)loops, unit); + } else { baseline = diff; + } fputc('\n', fp); + previous = diff; + return printed + 1; } -- cgit v1.2.3 From 6af5e4cf3a6521d23ca53df5001319babefdffbf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Jun 2023 17:42:47 -0300 Subject: perf bench uprobe empty: Add entry attaching an empty BPF program Using libbpf and a BPF skel: # perf bench uprobe all # Running uprobe/baseline benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,055,618 usecs 1,055.618 usecs/op # Running uprobe/empty benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,057,146 usecs +1,528 to baseline 1,057.146 usecs/op # Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Andre Fredette Cc: Clark Williams Cc: Dave Tucker Cc: Derek Barbosa Cc: Jiri Olsa Cc: Masami Hiramatsu (Google) Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/20230719204910.539044-5-acme@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/bench.h | 1 + tools/perf/bench/uprobe.c | 75 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index 201311f75c96..daf4850b441c 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h @@ -43,6 +43,7 @@ int bench_evlist_open_close(int argc, const char **argv); int bench_breakpoint_thread(int argc, const char **argv); int bench_breakpoint_enable(int argc, const char **argv); int bench_uprobe_baseline(int argc, const char **argv); +int bench_uprobe_empty(int argc, const char **argv); int bench_pmu_scan(int argc, const char **argv); #define BENCH_FORMAT_DEFAULT_STR "default" diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index a90e09f791c5..dfb90038a4f7 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -24,6 +24,11 @@ #define LOOPS_DEFAULT 1000 static int loops = LOOPS_DEFAULT; +enum bench_uprobe { + BENCH_UPROBE__BASELINE, + BENCH_UPROBE__EMPTY, +}; + static const struct option options[] = { OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), OPT_END() @@ -34,6 +39,59 @@ static const char * const bench_uprobe_usage[] = { NULL }; +#ifdef HAVE_BPF_SKEL +#include "bpf_skel/bench_uprobe.skel.h" + +struct bench_uprobe_bpf *skel; + +static int bench_uprobe__setup_bpf_skel(void) +{ + DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts); + int err; + + /* Load and verify BPF application */ + skel = bench_uprobe_bpf__open(); + if (!skel) { + fprintf(stderr, "Failed to open and load uprobes bench BPF skeleton\n"); + return -1; + } + + err = bench_uprobe_bpf__load(skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF skeleton\n"); + goto cleanup; + } + + uprobe_opts.func_name = "usleep"; + skel->links.empty = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.empty, + /*pid=*/-1, + /*binary_path=*/"/lib64/libc.so.6", + /*func_offset=*/0, + /*opts=*/&uprobe_opts); + if (!skel->links.empty) { + err = -errno; + fprintf(stderr, "Failed to attach bench uprobe: %s\n", strerror(errno)); + goto cleanup; + } + + return err; +cleanup: + bench_uprobe_bpf__destroy(skel); + return err; +} + +static void bench_uprobe__teardown_bpf_skel(void) +{ + if (skel) { + bench_uprobe_bpf__destroy(skel); + skel = NULL; + } +} +#else +static int bench_uprobe__setup_bpf_skel(void) { return 0; } +static void bench_uprobe__teardown_bpf_skel(void) {}; +#endif + static int bench_uprobe_format__default_fprintf(const char *name, const char *unit, u64 diff, FILE *fp) { static u64 baseline, previous; @@ -68,7 +126,7 @@ static int bench_uprobe_format__default_fprintf(const char *name, const char *un return printed + 1; } -static int bench_uprobe(int argc, const char **argv) +static int bench_uprobe(int argc, const char **argv, enum bench_uprobe bench) { const char *name = "usleep(1000)", *unit = "usec"; struct timespec start, end; @@ -77,7 +135,10 @@ static int bench_uprobe(int argc, const char **argv) argc = parse_options(argc, argv, options, bench_uprobe_usage, 0); - clock_gettime(CLOCK_REALTIME, &start); + if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel() < 0) + return 0; + + clock_gettime(CLOCK_REALTIME, &start); for (i = 0; i < loops; i++) { usleep(USEC_PER_MSEC); @@ -103,10 +164,18 @@ static int bench_uprobe(int argc, const char **argv) exit(1); } + if (bench != BENCH_UPROBE__BASELINE) + bench_uprobe__teardown_bpf_skel(); + return 0; } int bench_uprobe_baseline(int argc, const char **argv) { - return bench_uprobe(argc, argv); + return bench_uprobe(argc, argv, BENCH_UPROBE__BASELINE); +} + +int bench_uprobe_empty(int argc, const char **argv) +{ + return bench_uprobe(argc, argv, BENCH_UPROBE__EMPTY); } -- cgit v1.2.3 From 7b47623b8cae8149688c11396bb690bed6936f70 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Jun 2023 17:42:47 -0300 Subject: perf bench uprobe trace_printk: Add entry attaching an BPF program that does a trace_printk [root@five ~]# perf bench uprobe all # Running uprobe/baseline benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,053,963 usecs 1,053.963 usecs/op # Running uprobe/empty benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,056,293 usecs +2,330 to baseline 1,056.293 usecs/op 2.330 usecs/op to baseline # Running uprobe/trace_printk benchmark... # Executed 1,000 usleep(1000) calls Total time: 1,056,977 usecs +3,014 to baseline +684 to previous 1,056.977 usecs/op 3.014 usecs/op to baseline 0.684 usecs/op to previous [root@five ~]# Acked-by: Ian Rogers Cc: Adrian Hunter Cc: Andre Fredette Cc: Clark Williams Cc: Dave Tucker Cc: Derek Barbosa Cc: Jiri Olsa Cc: Masami Hiramatsu (Google) Cc: Namhyung Kim Link: https://lore.kernel.org/lkml/20230719204910.539044-6-acme@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/bench.h | 1 + tools/perf/bench/uprobe.c | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index daf4850b441c..50de4773651f 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h @@ -44,6 +44,7 @@ int bench_breakpoint_thread(int argc, const char **argv); int bench_breakpoint_enable(int argc, const char **argv); int bench_uprobe_baseline(int argc, const char **argv); int bench_uprobe_empty(int argc, const char **argv); +int bench_uprobe_trace_printk(int argc, const char **argv); int bench_pmu_scan(int argc, const char **argv); #define BENCH_FORMAT_DEFAULT_STR "default" diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index dfb90038a4f7..914c0817fe8a 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -11,6 +11,7 @@ #include #include "../builtin.h" #include "bench.h" +#include #include #include @@ -27,6 +28,7 @@ static int loops = LOOPS_DEFAULT; enum bench_uprobe { BENCH_UPROBE__BASELINE, BENCH_UPROBE__EMPTY, + BENCH_UPROBE__TRACE_PRINTK, }; static const struct option options[] = { @@ -42,9 +44,21 @@ static const char * const bench_uprobe_usage[] = { #ifdef HAVE_BPF_SKEL #include "bpf_skel/bench_uprobe.skel.h" +#define bench_uprobe__attach_uprobe(prog) \ + skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \ + /*pid=*/-1, \ + /*binary_path=*/"/lib64/libc.so.6", \ + /*func_offset=*/0, \ + /*opts=*/&uprobe_opts); \ + if (!skel->links.prog) { \ + err = -errno; \ + fprintf(stderr, "Failed to attach bench uprobe \"%s\": %s\n", #prog, strerror(errno)); \ + goto cleanup; \ + } + struct bench_uprobe_bpf *skel; -static int bench_uprobe__setup_bpf_skel(void) +static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench) { DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts); int err; @@ -63,14 +77,12 @@ static int bench_uprobe__setup_bpf_skel(void) } uprobe_opts.func_name = "usleep"; - skel->links.empty = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.empty, - /*pid=*/-1, - /*binary_path=*/"/lib64/libc.so.6", - /*func_offset=*/0, - /*opts=*/&uprobe_opts); - if (!skel->links.empty) { - err = -errno; - fprintf(stderr, "Failed to attach bench uprobe: %s\n", strerror(errno)); + switch (bench) { + case BENCH_UPROBE__BASELINE: break; + case BENCH_UPROBE__EMPTY: bench_uprobe__attach_uprobe(empty); break; + case BENCH_UPROBE__TRACE_PRINTK: bench_uprobe__attach_uprobe(trace_printk); break; + default: + fprintf(stderr, "Invalid bench: %d\n", bench); goto cleanup; } @@ -88,7 +100,7 @@ static void bench_uprobe__teardown_bpf_skel(void) } } #else -static int bench_uprobe__setup_bpf_skel(void) { return 0; } +static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench __maybe_unused) { return 0; } static void bench_uprobe__teardown_bpf_skel(void) {}; #endif @@ -135,7 +147,7 @@ static int bench_uprobe(int argc, const char **argv, enum bench_uprobe bench) argc = parse_options(argc, argv, options, bench_uprobe_usage, 0); - if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel() < 0) + if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel(bench) < 0) return 0; clock_gettime(CLOCK_REALTIME, &start); @@ -179,3 +191,8 @@ int bench_uprobe_empty(int argc, const char **argv) { return bench_uprobe(argc, argv, BENCH_UPROBE__EMPTY); } + +int bench_uprobe_trace_printk(int argc, const char **argv) +{ + return bench_uprobe(argc, argv, BENCH_UPROBE__TRACE_PRINTK); +} -- cgit v1.2.3 From 9823ae6f68786aff4fbe870897aee1abc0b01fda Mon Sep 17 00:00:00 2001 From: Kajol Jain Date: Wed, 23 Aug 2023 13:21:03 +0530 Subject: perf bench breakpoint: Skip run if no breakpoints available Based on commit 7d54a4acd8c1de3e ("perf test: Skip watchpoint tests if no watchpoints available"), hardware breakpoints are not available for power9 platform and because of that 'perf bench breakpoint' run fails on power9 platform. Add code to check for the return value of perf_event_open() in the breakpoint run and skip the 'perf bench breakpoint' run, if hardware breakpoints are not available. Result on power9 system before patch changes: [command]# perf bench breakpoint thread perf_event_open: No such device Result on power9 system after patch changes: [command]# ./perf bench breakpoint thread Skipping perf bench breakpoint thread: No hardware support Reported-by: Disha Goel Signed-off-by: Kajol Jain Acked-by: Naveen N Rao Cc: Athira Rajeev Cc: Disha Goel Cc: Ian Rogers Cc: Madhavan Srinivasan Cc: Namhyung Kim Cc: Naveen N. Rao Cc: linuxppc-dev@lists.ozlabs.org Link: https://lore.kernel.org/r/20230823075103.190565-1-kjain@linux.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/breakpoint.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/breakpoint.c b/tools/perf/bench/breakpoint.c index 41385f89ffc7..dfd18f5db97d 100644 --- a/tools/perf/bench/breakpoint.c +++ b/tools/perf/bench/breakpoint.c @@ -47,6 +47,7 @@ struct breakpoint { static int breakpoint_setup(void *addr) { struct perf_event_attr attr = { .size = 0, }; + int fd; attr.type = PERF_TYPE_BREAKPOINT; attr.size = sizeof(attr); @@ -56,7 +57,12 @@ static int breakpoint_setup(void *addr) attr.bp_addr = (unsigned long)addr; attr.bp_type = HW_BREAKPOINT_RW; attr.bp_len = HW_BREAKPOINT_LEN_1; - return syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0); + fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0); + + if (fd < 0) + fd = -errno; + + return fd; } static void *passive_thread(void *arg) @@ -122,8 +128,14 @@ int bench_breakpoint_thread(int argc, const char **argv) for (i = 0; i < thread_params.nbreakpoints; i++) { breakpoints[i].fd = breakpoint_setup(&breakpoints[i].watched); - if (breakpoints[i].fd == -1) + + if (breakpoints[i].fd < 0) { + if (breakpoints[i].fd == -ENODEV) { + printf("Skipping perf bench breakpoint thread: No hardware support\n"); + return 0; + } exit((perror("perf_event_open"), EXIT_FAILURE)); + } } gettimeofday(&start, NULL); for (i = 0; i < thread_params.nparallel; i++) { @@ -196,8 +208,14 @@ int bench_breakpoint_enable(int argc, const char **argv) exit(EXIT_FAILURE); } fd = breakpoint_setup(&watched); - if (fd == -1) + + if (fd < 0) { + if (fd == -ENODEV) { + printf("Skipping perf bench breakpoint enable: No hardware support\n"); + return 0; + } exit((perror("perf_event_open"), EXIT_FAILURE)); + } nthreads = enable_params.npassive + enable_params.nactive; threads = calloc(nthreads, sizeof(threads[0])); if (!threads) -- cgit v1.2.3 From c3245d2093c16c60bddc2ec5e945354ffe16bb95 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 23 Aug 2023 21:13:14 -0700 Subject: perf pmu: Abstract alias/event struct In order to be able to lazily compute aliases/events for a PMU, move the struct perf_pmu_alias into pmu.c. Add perf_pmu__find_event and perf_pmu__for_each_event that take a callback that is called for the found event or for each event. The layout of struct pmu and the event/alias list is unchanged but the API is altered so that aliases are no longer directly accessed, allowing for later changes. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Gaosheng Cui Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kan Liang Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Link: https://lore.kernel.org/r/20230824041330.266337-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/pmu-scan.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'tools/perf/bench') diff --git a/tools/perf/bench/pmu-scan.c b/tools/perf/bench/pmu-scan.c index c7d207f8e13c..9e4d36486f62 100644 --- a/tools/perf/bench/pmu-scan.c +++ b/tools/perf/bench/pmu-scan.c @@ -57,9 +57,7 @@ static int save_result(void) r->is_core = pmu->is_core; r->nr_caps = pmu->nr_caps; - r->nr_aliases = 0; - list_for_each(list, &pmu->aliases) - r->nr_aliases++; + r->nr_aliases = perf_pmu__num_events(pmu); r->nr_formats = 0; list_for_each(list, &pmu->format) @@ -98,9 +96,7 @@ static int check_result(bool core_only) return -1; } - nr = 0; - list_for_each(list, &pmu->aliases) - nr++; + nr = perf_pmu__num_events(pmu); if (nr != r->nr_aliases) { pr_err("Unmatched number of event aliases in %s: expect %d vs got %d\n", pmu->name, r->nr_aliases, nr); -- cgit v1.2.3