tests: perf: UNHALTED_REFERENCE_CYCLES might not be actionable on a host
[lttng-tools.git] / tests / perf / find_event.c
index 38ac6c139c2edd6a163069e68974f0acc2cd809c..aa1c964c399180ce95dc769ce5f1cfa404bc7536 100644 (file)
  *
  */
 
+#include <errno.h>
 #include <stdio.h>
-#include <perfmon/pfmlib.h>
 #include <string.h>
 
+#include <linux/perf_event.h>
+#include <perfmon/perf_event.h>
+#include <perfmon/pfmlib_perf_event.h>
+
 int main(int argc, char **argv)
 {
-       int ret, i;
-       unsigned int j;
-       pfm_pmu_info_t pinfo;
+       int ret, fd;
+
+       /* pfm query objects */
+       pfm_perf_encode_arg_t pencoder;
+       pfm_event_info_t info;
+
+       /* Perf event object to be populated by libpfm */
+       struct perf_event_attr attr;
 
        if (argc != 2) {
                fprintf(stderr, "Usage: %s <pmu counter to find>\n"
                                "ex: %s UNHALTED_REFERENCE_CYCLES\n"
-                               "Returns the first occurence it finds with "
+                               "Returns the event raw number if found and actionable with"
                                "return code 0.\n"
-                               "If not found returns 1, on error returns -1\n",
+                               "If not found returns 1,"
+                               "If not actionable return 2,"
+                               "on error returns 255\n",
                                argv[0], argv[0]);
                ret = -1;
                goto end;
        }
 
-       memset(&pinfo, 0, sizeof(pinfo));
-       pinfo.size = sizeof(pinfo);
+       /* Initialize perf_event_attr. */
+       memset(&attr, 0, sizeof(struct perf_event_attr));
+
+       /* Initialize libpfm encoder structure. */
+       memset(&pencoder, 0, sizeof(pencoder));
+       pencoder.size = sizeof(pfm_perf_encode_arg_t);
+
+       /* Initialize libpfm event info structure. */
+       memset(&info, 0, sizeof(info));
+       info.size = sizeof(info);
+
+       /* Prepare the encoder for query. */
+       pencoder.attr = &attr; /* Set the perf_event_attr pointer. */
+       pencoder.fstr = NULL; /* Not interested by the fully qualified event string. */
 
        ret = pfm_initialize();
        if (ret != PFM_SUCCESS) {
                fprintf(stderr, "Failed to initialise libpfm: %s",
                                pfm_strerror(ret));
-               ret = -1;
+               ret = 255;
+               goto end;
+       }
+
+       ret = pfm_get_os_event_encoding(argv[1],
+                       PFM_PLM0 | PFM_PLM1 | PFM_PLM2 | PFM_PLM3,
+                       PFM_OS_PERF_EVENT, &pencoder);
+       if (ret != PFM_SUCCESS) {
+               fprintf(stderr, "libpfm: error pfm_get_os_event_encoding: %s\n",
+                               pfm_strerror(ret));
+               ret = 1;
+               goto end;
+       }
+
+       /*
+        * Query the raw code for later use. Do it now to simplify error
+        * management.
+        */
+       ret = pfm_get_event_info(pencoder.idx, PFM_OS_NONE, &info);
+       if (ret != PFM_SUCCESS) {
+               fprintf(stderr, "libpfm: error pfm_get_event_info: %s\n", pfm_strerror(ret));
+               ret = 1;
                goto end;
        }
 
-       pfm_for_all_pmus(j) {
-               ret = pfm_get_pmu_info(j, &pinfo);
-               if (ret != PFM_SUCCESS) {
-                       continue;
-               }
-
-               for (i = pinfo.first_event; i != -1; i = pfm_get_event_next(i)) {
-                       pfm_event_info_t info =
-                                       { .size = sizeof(pfm_event_info_t) };
-
-                       ret = pfm_get_event_info(i, PFM_OS_NONE, &info);
-                       if (ret != PFM_SUCCESS) {
-                               fprintf(stderr, "Cannot get event info: %s\n",
-                                               pfm_strerror(ret));
-                               ret = -1;
-                               goto end;
-                       }
-
-                       if (info.pmu != j) {
-                               continue;
-                       }
-
-                       if (strcmp(info.name, argv[1]) == 0) {
-                               fprintf(stdout, "r%" PRIx64 "\n", info.code);
-                               ret = 0;
-                               goto end;
-                       }
-               }
+       /*
+        * Now that the event is found, try to use it to validate that
+        * the current user has access to it and that it can be used on that
+        * host.
+        */
+
+       /* Set the event to disabled to prevent unnecessary side effects. */
+       pencoder.attr->disabled = 1;
+
+       /* perf_event_open is provided by perfmon/perf_event.h. */
+       fd = perf_event_open(pencoder.attr, 0, -1, -1, 0);
+       if (fd == -1) {
+               fprintf(stderr, "perf: error perf_event_open: %d: %s\n", errno,
+                               strerror(errno));
+               ret = 2;
+               goto end;
        }
 
-       ret = 1;
+       /* We close the fd immediately since the event is actionable. */
+       close(fd);
+
+       /* Output the raw code for the event */
+       fprintf(stdout, "r%" PRIx64 "\n", info.code);
+       ret = 0;
 
 end:
        return ret;
This page took 0.024592 seconds and 4 git commands to generate.