On 05/31/2017 04:53 PM, Vince Weaver wrote:
> On Tue, 30 May 2017, William Cohen wrote:
>
>> As a workaround I have been developing a patch that avoids using the
>> PFM_PMU_MAX and examines the pfm_pmu_get_info return code to determine
>> if there are might be additional pmu descriptions to scan. Attached is
>> the patch. I have tried it out. It compiles and appears to allow papi
>> to not care so much about which particular libpfm was used to build
>> papi.
>
> The patch is a little more intrusive than I was hoping for, but I'll see
> that it (or something like it) gets applied. Is there a quick way of
> testing it? Were you using papi_component_avail or something else?
>
> Mostly your use of forever-looping for loops throws me, I'm more used to a
> while(1) type idiom.
>
> Vince
>
Hi Vince,
Did you have a chance to try out test the patch? Attached is what I currently
have in my branch with some explanation on what was going wrong and the
approach used to fix it.
-Will
>From 796ab7fd22f21c5ad6efd822c043829792502908 Mon Sep 17 00:00:00 2001
From: William Cohen <wco...@redhat.com>
Date: Fri, 9 Jun 2017 10:45:29 -0400
Subject: [PATCH] Avoid unintended libpfm build dependency due to PFM_PMU_MAX
enum use
The libpfm pfmlib.h file enumerates the each of performance monitoring
units (PMUs) it can program in pfm_pmu_t type. The last enum in this
type is PFM_PMU_MAX. Depending on which specific version of libpfm
being used this specific value could vary. The problem is that
PFM_PMU_MAX is statically defined in the pfmlib.h file and this was
being used as a loop bounds when iterating to determine which PMUs are
potentially available. If PAPI was built with an older version of
libpfm and then run with a newer libpfm shared library on a machine
with a larger PFM_PMU_MAX value, none of the PMUs past the smaller
PFM_PMU_MAX used for the the build would be examined or enabled.
This fix uses the fact that the libpfm pfm_get_pmu_info function
should return either PFM_SUCCESS or PFM_ERR_NOTSUPP for pmus on the
list. The PFM_SUCCESS returned for pmu available on the machine and
the PFM_ERR_NOTSUPP for the pmu for unavailable on the machine. For
cases with PFM_ERR_NOTSUPP the initialization loops will just skip
those items. If PFM_SUCCESS is returned, do the appropriate
initialization. Any other values returned by the pfm_get_pmu_info
function indicate that the end of the list has been reached.
---
src/components/perf_event/pe_libpfm4_events.c | 40 ++++++++++++++--------
.../perf_event_uncore/peu_libpfm4_events.c | 38 ++++++++++++--------
2 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/src/components/perf_event/pe_libpfm4_events.c b/src/components/perf_event/pe_libpfm4_events.c
index dd8a213..51d3486 100644
--- a/src/components/perf_event/pe_libpfm4_events.c
+++ b/src/components/perf_event/pe_libpfm4_events.c
@@ -436,14 +436,22 @@ get_first_event_next_pmu(int pmu_idx, int pmu_type)
// start looking at the next pmu in the list
pmu_idx++;
- while(pmu_idx<PFM_PMU_MAX) {
+ for( ; 1; pmu_idx++) {
/* clear the PMU structure (required by libpfm4) */
memset(&pinfo,0,sizeof(pfm_pmu_info_t));
pinfo.size = sizeof(pfm_pmu_info_t);
ret=pfm_get_pmu_info(pmu_idx, &pinfo);
- if ((ret==PFM_SUCCESS) && pmu_is_present_and_right_type(&pinfo,pmu_type)) {
+ if (ret==PFM_ERR_NOTSUPP) {
+ continue;
+ }
+
+ if (ret!=PFM_SUCCESS) {
+ break;
+ }
+
+ if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
pidx=pinfo.first_event;
SUBDBG("First event in pmu: %s is %#x\n", pinfo.name, pidx);
@@ -459,9 +467,6 @@ get_first_event_next_pmu(int pmu_idx, int pmu_type)
return pidx;
}
}
-
- pmu_idx++;
-
}
SUBDBG("EXIT: PAPI_ENOEVNT\n");
@@ -824,14 +829,11 @@ _pe_libpfm4_ntv_enum_events( unsigned int *PapiEventCode,
// get the pmu number of the last event
pnum = einfo.pmu;
- while ( pnum<PFM_PMU_MAX) {
- SUBDBG("pnum: %d\n", pnum);
- code=get_first_event_next_pmu(pnum, event_table->pmu_type);
- if (code < 0) {
- SUBDBG("EXIT: No more pmu's to list, returning: %d\n", code);
- return code;
- }
- break;
+ SUBDBG("pnum: %d\n", pnum);
+ code=get_first_event_next_pmu(pnum, event_table->pmu_type);
+ if (code < 0) {
+ SUBDBG("EXIT: No more pmu's to list, returning: %d\n", code);
+ return code;
}
}
@@ -1088,11 +1090,19 @@ _pe_libpfm4_init(papi_vector_t *my_vector, int cidx,
retval=pfm_get_pmu_info(0, &(event_table->default_pmu));
SUBDBG("Detected pmus:\n");
- for(i=0;i<PFM_PMU_MAX;i++) {
+ for (i=PFM_PMU_NONE; 1; i++) {
memset(&pinfo,0,sizeof(pfm_pmu_info_t));
pinfo.size = sizeof(pfm_pmu_info_t);
retval=pfm_get_pmu_info(i, &pinfo);
- if ((retval!=PFM_SUCCESS) || (pinfo.name == NULL)) {
+ if (retval==PFM_ERR_NOTSUPP) {
+ continue;
+ }
+
+ if (retval!=PFM_SUCCESS) {
+ break;
+ }
+
+ if (pinfo.name == NULL) {
continue;
}
diff --git a/src/components/perf_event_uncore/peu_libpfm4_events.c b/src/components/perf_event_uncore/peu_libpfm4_events.c
index 598fcc7..abb0017 100644
--- a/src/components/perf_event_uncore/peu_libpfm4_events.c
+++ b/src/components/perf_event_uncore/peu_libpfm4_events.c
@@ -427,14 +427,22 @@ get_first_event_next_pmu(int pmu_idx, int pmu_type)
// start looking at the next pmu in the list
pmu_idx++;
- while(pmu_idx<PFM_PMU_MAX) {
+ for(; 1; pmu_idx++) {
/* clear the PMU structure (required by libpfm4) */
memset(&pinfo,0,sizeof(pfm_pmu_info_t));
pinfo.size = sizeof(pfm_pmu_info_t);
ret=pfm_get_pmu_info(pmu_idx, &pinfo);
- if ((ret==PFM_SUCCESS) && pmu_is_present_and_right_type(&pinfo,pmu_type)) {
+ if (ret==PFM_ERR_NOTSUPP) {
+ continue;
+ }
+
+ if (ret!=PFM_SUCCESS) {
+ break;
+ }
+
+ if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
pidx=pinfo.first_event;
SUBDBG("First event in pmu: %s is %#x\n", pinfo.name, pidx);
@@ -450,9 +458,6 @@ get_first_event_next_pmu(int pmu_idx, int pmu_type)
return pidx;
}
}
-
- pmu_idx++;
-
}
SUBDBG("EXIT: PAPI_ENOEVNT\n");
@@ -806,14 +811,11 @@ _peu_libpfm4_ntv_enum_events( unsigned int *PapiEventCode,
// get the pmu number of the last event
pnum = einfo.pmu;
- while ( pnum<PFM_PMU_MAX) {
- SUBDBG("pnum: %d\n", pnum);
- code=get_first_event_next_pmu(pnum, event_table->pmu_type);
- if (code < 0) {
- SUBDBG("EXIT: No more pmu's to list, returning: %d\n", code);
- return code;
- }
- break;
+ SUBDBG("pnum: %d\n", pnum);
+ code=get_first_event_next_pmu(pnum, event_table->pmu_type);
+ if (code < 0) {
+ SUBDBG("EXIT: No more pmu's to list, returning: %d\n", code);
+ return code;
}
}
@@ -1066,14 +1068,20 @@ _peu_libpfm4_init(papi_vector_t *my_vector,
my_vector->cmp_info.num_cntrs=0;
SUBDBG("Detected pmus:\n");
- for(i=0;i<PFM_PMU_MAX;i++) {
+
+ for(i=PFM_PMU_NONE; 1; i++) {
memset(&pinfo,0,sizeof(pfm_pmu_info_t));
pinfo.size = sizeof(pfm_pmu_info_t);
retval=pfm_get_pmu_info(i, &pinfo);
- if (retval!=PFM_SUCCESS) {
+
+ if (retval==PFM_ERR_NOTSUPP) {
continue;
}
+ if (retval!=PFM_SUCCESS) {
+ break;
+ }
+
if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type);
--
2.9.4
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel