perf evsel: Handle precise_ip fallback in evsel__open_cpu()
authorRiccardo Mancini <rickyman7@gmail.com>
Sat, 21 Aug 2021 09:19:30 +0000 (11:19 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 31 Aug 2021 19:52:27 +0000 (16:52 -0300)
This is another patch in the effort to separate the fallback mechanisms
from the open itself.

In case of precise_ip fallback, the original precise_ip will be stored
in the evsel (it was stored in a local variable) and the open will be
retried. Since the precise_ip fallback will be the first in the chain of
fallbacks, there should be no functional change with this patch.

Signed-off-by: Riccardo Mancini <rickyman7@gmail.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/74208c433d2024a6c4af9c0b140b54ed6b5ea810.1629490974.git.rickyman7@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index a576d98..54d2513 100644 (file)
@@ -1709,42 +1709,29 @@ static void display_attr(struct perf_event_attr *attr)
        }
 }
 
-static int perf_event_open(struct evsel *evsel,
-                          pid_t pid, int cpu, int group_fd)
+bool evsel__precise_ip_fallback(struct evsel *evsel)
 {
-       int precise_ip = evsel->core.attr.precise_ip;
-       int fd;
-
-       while (1) {
-               pr_debug2_peo("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
-                         pid, cpu, group_fd, evsel->open_flags);
-
-               fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, group_fd, evsel->open_flags);
-               if (fd >= 0)
-                       break;
-
-               /* Do not try less precise if not requested. */
-               if (!evsel->precise_max)
-                       break;
-
-               /*
-                * We tried all the precise_ip values, and it's
-                * still failing, so leave it to standard fallback.
-                */
-               if (!evsel->core.attr.precise_ip) {
-                       evsel->core.attr.precise_ip = precise_ip;
-                       break;
-               }
+       /* Do not try less precise if not requested. */
+       if (!evsel->precise_max)
+               return false;
 
-               pr_debug2_peo("\nsys_perf_event_open failed, error %d\n", -ENOTSUP);
-               evsel->core.attr.precise_ip--;
-               pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
-               display_attr(&evsel->core.attr);
+       /*
+        * We tried all the precise_ip values, and it's
+        * still failing, so leave it to standard fallback.
+        */
+       if (!evsel->core.attr.precise_ip) {
+               evsel->core.attr.precise_ip = evsel->precise_ip_original;
+               return false;
        }
 
-       return fd;
-}
+       if (!evsel->precise_ip_original)
+               evsel->precise_ip_original = evsel->core.attr.precise_ip;
 
+       evsel->core.attr.precise_ip--;
+       pr_debug2_peo("decreasing precise_ip by one (%d)\n", evsel->core.attr.precise_ip);
+       display_attr(&evsel->core.attr);
+       return true;
+}
 
 static struct perf_cpu_map *empty_cpu_map;
 static struct perf_thread_map *empty_thread_map;
@@ -2004,8 +1991,11 @@ retry_open:
 
                        test_attr__ready();
 
-                       fd = perf_event_open(evsel, pid, cpus->map[cpu],
-                                            group_fd);
+                       pr_debug2_peo("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
+                               pid, cpus->map[cpu], group_fd, evsel->open_flags);
+
+                       fd = sys_perf_event_open(&evsel->core.attr, pid, cpus->map[cpu],
+                                               group_fd, evsel->open_flags);
 
                        FD(evsel, cpu, thread) = fd;
 
@@ -2058,6 +2048,9 @@ retry_open:
        return 0;
 
 try_fallback:
+       if (evsel__precise_ip_fallback(evsel))
+               goto retry_open;
+
        if (evsel__ignore_missing_thread(evsel, cpus->nr, cpu, threads, thread, err)) {
                /* We just removed 1 thread, so lower the upper nthreads limit. */
                nthreads--;
index b749bee..1b3eeab 100644 (file)
@@ -151,6 +151,7 @@ struct evsel {
                struct bperf_follower_bpf *follower_skel;
        };
        unsigned long           open_flags;
+       int                     precise_ip_original;
 };
 
 struct perf_missing_features {
@@ -298,6 +299,7 @@ bool evsel__ignore_missing_thread(struct evsel *evsel,
                                  int nr_cpus, int cpu,
                                  struct perf_thread_map *threads,
                                  int thread, int err);
+bool evsel__precise_ip_fallback(struct evsel *evsel);
 
 struct perf_sample;