X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=tests%2Fperf%2Ffind_event.c;h=aa1c964c399180ce95dc769ce5f1cfa404bc7536;hp=38ac6c139c2edd6a163069e68974f0acc2cd809c;hb=90aa04a116a8be510b9d256b47de6bbb4144fb8b;hpb=9d16b343fb9e781fc8d8fa3c448a3f382306dd33 diff --git a/tests/perf/find_event.c b/tests/perf/find_event.c index 38ac6c139..aa1c964c3 100644 --- a/tests/perf/find_event.c +++ b/tests/perf/find_event.c @@ -5,69 +5,106 @@ * */ +#include #include -#include #include +#include +#include +#include + 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 \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;