perf mem record: Check for memory events support
authorJiri Olsa <jolsa@kernel.org>
Wed, 24 Feb 2016 08:46:42 +0000 (09:46 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 24 Feb 2016 13:10:59 +0000 (10:10 -0300)
Check if current kernel support available memory events and display the
status within -e  list option:

  $ perf mem record -e list
  ldlat-loads  : available
  ldlat-stores : available

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1456303616-26926-2-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-mem.c
tools/perf/util/mem-events.c
tools/perf/util/mem-events.h

index b3f8a89ede40af9e07ac12724f853af2095aa2b7..f1fa7b8d1f6949f23383482f88a6fad178d05d2c 100644 (file)
@@ -40,10 +40,11 @@ static int parse_record_events(const struct option *opt,
        for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
                struct perf_mem_event *e = &perf_mem_events[j];
 
-               fprintf(stderr, "%-20s%s",
-                       e->tag, verbose ? "" : "\n");
-               if (verbose)
-                       fprintf(stderr, " [%s]\n", e->name);
+               fprintf(stderr, "%-13s%-*s%s\n",
+                       e->tag,
+                       verbose ? 25 : 0,
+                       verbose ? e->name : "",
+                       e->supported ? ": available" : "");
        }
        exit(0);
 }
@@ -92,6 +93,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
                if (!perf_mem_events[j].record)
                        continue;
 
+               if (!perf_mem_events[j].supported) {
+                       pr_err("failed: event '%s' not supported\n",
+                              perf_mem_events[j].name);
+                       return -1;
+               }
+
                rec_argv[i++] = "-e";
                rec_argv[i++] = perf_mem_events[j].name;
        };
@@ -355,6 +362,11 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
                NULL
        };
 
+       if (perf_mem_events__init()) {
+               pr_err("failed: memory events not supported\n");
+               return -1;
+       }
+
        argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
                                        mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
index b1507c04b2577493d48bc05cb048256f723f277e..e21853fe1312ce1bc5dcfe1529cb44708ee73913 100644 (file)
@@ -2,15 +2,20 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <api/fs/fs.h>
 #include "mem-events.h"
 #include "debug.h"
 
-#define E(t, n) { .tag = t, .name = n }
+#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
 
 struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
-       E("ldlat-loads",        "cpu/mem-loads,ldlat=30/P"),
-       E("ldlat-stores",       "cpu/mem-stores/P"),
+       E("ldlat-loads",        "cpu/mem-loads,ldlat=30/P",     "mem-loads"),
+       E("ldlat-stores",       "cpu/mem-stores/P",             "mem-stores"),
 };
+#undef E
 
 #undef E
 
@@ -49,3 +54,27 @@ int perf_mem_events__parse(const char *str)
        pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
        return -1;
 }
+
+int perf_mem_events__init(void)
+{
+       const char *mnt = sysfs__mount();
+       bool found = false;
+       int j;
+
+       if (!mnt)
+               return -ENOENT;
+
+       for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+               char path[PATH_MAX];
+               struct perf_mem_event *e = &perf_mem_events[j];
+               struct stat st;
+
+               scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
+                         mnt, e->sysfs_name);
+
+               if (!stat(path, &st))
+                       e->supported = found = true;
+       }
+
+       return found ? 0 : -ENOENT;
+}
index 2995bae6ac335f799cbc8ef930c6e8b68b45a92e..75c1660bda627cdbe3069735cb7b8c4714553a22 100644 (file)
@@ -5,8 +5,10 @@
 
 struct perf_mem_event {
        bool            record;
+       bool            supported;
        const char      *tag;
        const char      *name;
+       const char      *sysfs_name;
 };
 
 enum {
@@ -18,5 +20,6 @@ enum {
 extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX];
 
 int perf_mem_events__parse(const char *str);
+int perf_mem_events__init(void);
 
 #endif /* __PERF_MEM_EVENTS_H */