On 05/30/2017 02:53 PM, Steve Kaufmann wrote:
> In cases like this I like to have an ending entry that is a null pointer, 
> then you simply loop until you see it to know you've exhausted the list:
> 
> 
>      for (i=0; pfmlib_pmus_map[i] != NULL; i++) {
> 
>                    ....
> 
>      }
>> 
> Just make sure to add/update the NULL entry after populating/adding 
> to/deleting from the table.
> 
> 
> Then just redefine the PFM_PMU_MAX entry something like:
> 
> 
> #define PFM_PMU_MAX do while(0) { int _i; for(_i=0; 
> pfmlib_pmus_map[_i]!=NULL; _i++) { } }, _i
> 
> 
> or perhaps a small function to do this would be cleaner:
> 
> 
> #define PFM_PMU_MAX __pfm_count_max()
> 
> 
> Steve
> 

Hi Steve,

Keep in mind that Red Hat build a separate libpfm from upstream rather than 
using the libpfm bundled in papi. The problem encountered was with different 
versions of libpfm supporting a different number of pmus. Right now papi uses 
the number of pmus impementations (pfm_pmu_t)  PFM_PMU_MAX that is hard coded 
in the /usr/include/perfmon/pfmlib.h.  Thes if a old version of the shared 
library is installed papi will try pfm_get_pmu_info() for pfm_pmu_t that are 
not supported by the older library.  There are enough checks that the code will 
probably survive this, but it is bad form. If a newer libpfm shared library is 
installed, papi initialization won't scan past the pfm_pmu_t that were listed 
in pfmlib.h used for compiling the code.

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.

-Will


> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> *From:* William Cohen <wco...@redhat.com>
> *Sent:* Tuesday, May 30, 2017 1:28:03 PM
> *To:* perfmon2-devel@lists.sourceforge.net; ptools-perf...@icl.utk.edu
> *Cc:* Michael Petlan
> *Subject:* [ptools-perfapi] Avoid hardcoding the number of entries in the 
> libpfm library with PFM_PMU_MAX
>  
> Hi,
> 
> I just got done analyzing a problem where papi was built with an old verion 
> of the libpfm then it was being tested with a newer version of libpfm that 
> had support for additional processor architectures.  In theory things should 
> just work because papi was using the libpfm shared library.  However, in this 
> case the papi did not recognize the newer hardware's pmu.  The problem was 
> caused by use of the PFM_PMU_MAX enum in papi's pe_libpfm4_event.c 
> initialization loop:
> 
>    for(i=0;i<PFM_PMU_MAX;i++) {
>       memset(&pinfo,0,sizeof(pfm_pmu_info_t));
>       retval=pfm_get_pmu_info(i, &pinfo);
>       if (retval!=PFM_SUCCESS) {
>          continue;
>       }
>    ...
>    }
> 
> The older libpfm that papi was built with has a smaller value for PFM_PMU_MAX 
> than the newer libpfm on the system being tested.  Thus, the pmu entries 
> added in the newer libpfm were not scanned by papi.
> 
> There should be a better way of doing this in libpfm.  As new pmus are added 
> to libpfm the other code should not need to be recompiled because of a change 
> to PFM_PMU_MAX. The following in /usr/include/perfmon/libpfm.h will also 
> cause problems with this problem if it is used in other applications:
> 
> #define pfm_for_all_pmus(x) \
>         for((x)= 0 ; (x) < PFM_PMU_MAX; (x)++)
> 
> 
> One possible way is to use the return value from pfm_get_pmu_info() to 
> determine whether a loop is at the end of the valid pfm_pmu_t range. Any 
> thoughts or comments on this?
> 
> -Will
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "ptools-perfapi" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to ptools-perfapi+unsubscr...@icl.utk.edu.
> To post to this group, send email to ptools-perf...@icl.utk.edu.
> Visit this group at 
> https://groups.google.com/a/icl.utk.edu/group/ptools-perfapi/.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "ptools-perfapi" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to ptools-perfapi+unsubscr...@icl.utk.edu 
> <mailto:ptools-perfapi+unsubscr...@icl.utk.edu>.
> To post to this group, send email to ptools-perf...@icl.utk.edu 
> <mailto:ptools-perf...@icl.utk.edu>.
> Visit this group at 
> https://groups.google.com/a/icl.utk.edu/group/ptools-perfapi/.

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);
 
------------------------------------------------------------------------------
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