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

Reply via email to