PAPI  5.3.0.0
peu_libpfm4_events.c
Go to the documentation of this file.
00001 /*
00002 * File:    peu_libpfm4_events.c
00003 * Author:  Vince Weaver vincent.weaver @ maine.edu
00004 *
00005 * Handle the libpfm4 event interface for the perf_event_uncore component
00006 */
00007 
00008 #include <string.h>
00009 
00010 #include "papi.h"
00011 #include "papi_internal.h"
00012 #include "papi_vector.h"
00013 
00014 #include "papi_libpfm4_events.h"
00015 #include "peu_libpfm4_events.h"
00016 
00017 #include "perfmon/pfmlib.h"
00018 #include "perfmon/pfmlib_perf_event.h"
00019 
00020 #define NATIVE_EVENT_CHUNK 1024
00021 
00034 static int find_existing_event(char *name,
00035                                struct native_event_table_t *event_table) {
00036 
00037   int i,event=PAPI_ENOEVNT;
00038 
00039   SUBDBG("Looking for %s in %d events\n",
00040          name,event_table->num_native_events);
00041 
00042   _papi_hwi_lock( NAMELIB_LOCK );
00043 
00044   for(i=0;i<event_table->num_native_events;i++) {
00045 
00046     if (!strcmp(name,event_table->native_events[i].allocated_name)) {
00047       SUBDBG("Found %s (%#x)\n",
00048          event_table->native_events[i].allocated_name,
00049          event_table->native_events[i].libpfm4_idx);
00050       event=i;
00051       break;
00052     }
00053   }
00054   _papi_hwi_unlock( NAMELIB_LOCK );
00055 
00056   if (event<0) { SUBDBG("%s not allocated yet\n",name); }
00057 
00058   return event;
00059 }
00060 
00073 static struct native_event_t *find_existing_event_by_number(int eventnum,
00074        struct native_event_table_t *event_table) {
00075 
00076   struct native_event_t *temp_event=NULL;
00077 
00078   _papi_hwi_lock( NAMELIB_LOCK );
00079 
00080   temp_event=&(event_table->native_events[eventnum]);
00081 
00082   _papi_hwi_unlock( NAMELIB_LOCK );
00083 
00084   SUBDBG("Found %p for %#x\n",temp_event,eventnum);
00085 
00086   return temp_event;
00087 }
00088 
00089 static int pmu_is_present_and_right_type(pfm_pmu_info_t *pinfo, int type) {
00090 
00091   if (!pinfo->is_present) return 0;
00092 
00093   if ((pinfo->type==PFM_PMU_TYPE_UNCORE) && (type&PMU_TYPE_UNCORE)) return 1;
00094   if ((pinfo->type==PFM_PMU_TYPE_CORE) && (type&PMU_TYPE_CORE)) return 1;
00095   if ((pinfo->type==PFM_PMU_TYPE_OS_GENERIC) && (type&PMU_TYPE_OS)) return 1;
00096 
00097   return 0;
00098 }
00099 
00100 
00112 static int find_event(char *name, int pmu_type) {
00113 
00114     int ret, actual_idx;
00115     pfm_pmu_info_t pinfo;
00116     pfm_event_info_t event_info;
00117 
00118     SUBDBG("Looking for %s\n",name);
00119 
00120     actual_idx=pfm_find_event(name);
00121     if (actual_idx<0) {
00122         return PFM_ERR_NOTFOUND;
00123     }
00124 
00125     memset(&event_info,0,sizeof(pfm_event_info_t));
00126     ret=pfm_get_event_info(actual_idx, PFM_OS_PERF_EVENT, &event_info);
00127     if (ret<0) {
00128     return PFM_ERR_NOTFOUND;
00129     }
00130 
00131     memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00132     pfm_get_pmu_info(event_info.pmu, &pinfo);
00133     if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
00134        return actual_idx;
00135     }
00136 
00137     return PFM_ERR_NOTFOUND;
00138 }
00139 
00140 
00152 static int find_event_no_aliases(char *name, int pmu_type) {
00153 
00154     int j,i, ret;
00155     pfm_pmu_info_t pinfo;
00156     pfm_event_info_t event_info;
00157     char full_name[BUFSIZ];
00158 
00159     SUBDBG("Looking for %s\n",name);
00160 
00161     pfm_for_all_pmus(j) {
00162 
00163        memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00164        pfm_get_pmu_info(j, &pinfo);
00165        if (!pmu_is_present_and_right_type(&pinfo,pmu_type)) {
00166           continue;
00167        }
00168 
00169        SUBDBG("Looking in pmu %d\n",j);   
00170        i = pinfo.first_event; 
00171        while(1) {
00172           memset(&event_info,0,sizeof(pfm_event_info_t));
00173           ret=pfm_get_event_info(i, PFM_OS_PERF_EVENT, &event_info);
00174       if (ret<0) break;
00175 
00176       sprintf(full_name,"%s::%s",pinfo.name,event_info.name);
00177 
00178       if (!strcmp(name,full_name)) {
00179          SUBDBG("FOUND %s %s %#x\n",name,full_name,i);
00180          return i;
00181       }
00182 
00183       if (!strcmp(name,event_info.name)) {
00184          SUBDBG("FOUND %s %s %#x\n",name,event_info.name,i);
00185          return i;
00186       }
00187       i=pfm_get_event_next(i);
00188        }
00189     }
00190     return PFM_ERR_NOTFOUND;
00191 }
00192 
00193 
00205 static int find_next_no_aliases(int code, int pmu_type) {
00206 
00207   int current_pmu=0,current_event=0;
00208   pfm_err_t ret;
00209   pfm_pmu_info_t pinfo;
00210   pfm_event_info_t event_info;
00211 
00212   /* Clear the structures, as libpfm4 requires it */
00213   memset(&event_info,0,sizeof(pfm_event_info_t));
00214 
00215   ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &event_info);
00216   if (ret!=PFM_SUCCESS) {
00217      return ret;
00218   }
00219 
00220   current_pmu=event_info.pmu;
00221   current_event=pfm_get_event_next(code);
00222 
00223   SUBDBG("Current is %#x guessing next is %#x\n",code,current_event);
00224 
00225   while(1) {
00226 
00227      memset(&event_info,0,sizeof(pfm_event_info_t));
00228      ret=pfm_get_event_info(current_event, PFM_OS_PERF_EVENT, &event_info);
00229      if (ret==PFM_SUCCESS) {
00230         SUBDBG("Returning %#x\n",current_event);
00231         return current_event;
00232      }
00233 
00234      /* next event not found, so try moving to next PMU */
00235 
00236      while(1) {
00237 
00238         current_pmu++;
00239         SUBDBG("Incrementing PMU: %#x\n",current_pmu);
00240 
00241     /* Off the end, so done iterating */
00242         if (current_pmu>PFM_PMU_MAX) {
00243            return PFM_ERR_NOTFOUND;
00244         }
00245  
00246         memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00247         pfm_get_pmu_info(current_pmu, &pinfo);
00248         if (pmu_is_present_and_right_type(&pinfo,pmu_type)) break;
00249      }
00250 
00251      current_event=pinfo.first_event;
00252 
00253   }
00254 
00255 }
00256 
00271 static struct native_event_t *allocate_native_event(char *name, 
00272                             int event_idx,
00273               struct native_event_table_t *event_table) {
00274 
00275   int new_event;
00276 
00277   pfm_err_t ret;
00278   unsigned int i;
00279   char *base_start;
00280   pfm_event_info_t info;
00281   pfm_pmu_info_t pinfo;
00282   char base[BUFSIZ],pmuplusbase[BUFSIZ];
00283   char fullname[BUFSIZ];
00284 
00285   pfm_perf_encode_arg_t perf_arg;
00286 
00287   struct perf_event_attr perf_attr;
00288 
00289   /* get the event name from libpfm */
00290   memset(&info,0,sizeof(pfm_event_info_t));
00291   ret = pfm_get_event_info(event_idx, PFM_OS_PERF_EVENT, &info);
00292   if (ret!=PFM_SUCCESS) {
00293      return NULL;
00294   }
00295 
00296   /* get the PMU info */
00297   memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00298   pfm_get_pmu_info(info.pmu, &pinfo);
00299 
00300   /* calculate the base name, meaning strip off pmu identifier */
00301   strncpy(base,name,BUFSIZ);
00302   i=0;
00303   base_start=base;
00304   while(i<strlen(base)) {
00305     if (base[i]==':') {
00306       if (base[i+1]==':') {
00307           i++;
00308       base_start=&base[i+1];
00309       }
00310       else {
00311     base[i]=0;
00312       }
00313     }
00314     i++;
00315   }
00316 
00317   /* add the event */
00318   _papi_hwi_lock( NAMELIB_LOCK );
00319 
00320   new_event=event_table->num_native_events;
00321 
00322   event_table->native_events[new_event].base_name=strdup(base_start);
00323 
00324   sprintf(fullname,"%s::%s",pinfo.name,info.name);
00325   event_table->native_events[new_event].pmu_plus_name=strdup(fullname);
00326 
00327   sprintf(pmuplusbase,"%s::%s",pinfo.name,base_start);
00328 
00329   event_table->native_events[new_event].component=0;
00330   event_table->native_events[new_event].pmu=strdup(pinfo.name);
00331 
00332   event_table->native_events[new_event].libpfm4_idx=
00333     find_event_no_aliases(pmuplusbase,event_table->pmu_type);
00334 
00335   SUBDBG("Using %#x as index instead of %#x for %s\n",
00336      event_table->native_events[new_event].libpfm4_idx,
00337      event_idx,pmuplusbase);
00338 
00339   event_table->native_events[new_event].allocated_name=strdup(name);
00340 
00341   /* is this needed? */
00342   event_table->native_events[new_event].users=0;
00343 
00344 
00345   /* use name of the event to get the perf_event encoding */
00346 
00347   /* clear the attribute structure */
00348   memset(&perf_arg,0,sizeof(pfm_perf_encode_arg_t));
00349 
00350   /* clear out the perf_attr struct */
00351   memset(&perf_attr,0,sizeof(struct perf_event_attr));
00352   perf_arg.attr=&perf_attr;
00353 
00354   ret = pfm_get_os_event_encoding(name,
00355                   PFM_PLM0 | PFM_PLM3,
00356                                   PFM_OS_PERF_EVENT,
00357                   &perf_arg);
00358   if (ret==PFM_SUCCESS) {
00359 
00360      event_table->native_events[new_event].config=perf_arg.attr->config;
00361      event_table->native_events[new_event].config1=perf_arg.attr->config1;
00362      event_table->native_events[new_event].type=perf_arg.attr->type;
00363 
00364      SUBDBG( "pe_event: config 0x%"PRIx64" config1 0x%"PRIx64
00365              " type 0x%"PRIx32"\n", 
00366              perf_arg.attr->config, 
00367          perf_arg.attr->config1,
00368          perf_arg.attr->type);
00369 
00370      SUBDBG("Creating event %s with perfidx %#x\n",
00371             name, event_table->native_events[new_event].libpfm4_idx);
00372 
00373      event_table->num_native_events++;
00374 
00375      /* If we've allocated too many native events, then allocate more room */
00376      if (event_table->num_native_events >= 
00377          event_table->allocated_native_events) {
00378 
00379         SUBDBG("Allocating more room for native events (%d %ld)\n",
00380         (event_table->allocated_native_events+NATIVE_EVENT_CHUNK),
00381         (long)sizeof(struct native_event_t) *
00382         (event_table->allocated_native_events+NATIVE_EVENT_CHUNK));
00383 
00384         event_table->native_events=realloc(event_table->native_events,
00385                sizeof(struct native_event_t) * 
00386                (event_table->allocated_native_events+NATIVE_EVENT_CHUNK));
00387         event_table->allocated_native_events+=NATIVE_EVENT_CHUNK;
00388      }
00389   }
00390   _papi_hwi_unlock( NAMELIB_LOCK );
00391 
00392   if (event_table->native_events==NULL) {
00393      return NULL;
00394   }
00395 
00396   return &event_table->native_events[new_event];
00397 
00398 }
00399 
00414 static int find_max_umask(struct native_event_t *current_event) {
00415 
00416   pfm_event_attr_info_t ainfo;
00417   char *b;
00418   int a, ret, max =0;
00419   pfm_event_info_t info;
00420   char event_string[BUFSIZ],*ptr;
00421   char temp_string[BUFSIZ];
00422 
00423   SUBDBG("Trying to find max umask in %s\n",current_event->allocated_name);
00424 
00425   strcpy(event_string,current_event->allocated_name);
00426 
00427   /* Skip leading :: delimited PMU name and point to first umask */
00428   if (strstr(event_string,"::")) {
00429      ptr=strstr(event_string,"::");
00430      ptr+=2;
00431      b=strtok(ptr,":");
00432   }
00433   else {
00434      b=strtok(event_string,":");
00435   }
00436 
00437   if (!b) {
00438      SUBDBG("No colon!\n");
00439      return PFM_ERR_UMASK; /* Must be this value!! */
00440   }
00441 
00442   memset(&info,0,sizeof(pfm_event_info_t));
00443   ret = pfm_get_event_info(current_event->libpfm4_idx, 
00444                PFM_OS_PERF_EVENT, &info);
00445   if (ret!=PFM_SUCCESS) {
00446      SUBDBG("get_event_info failed\n");
00447      return PFM_ERR_NOTFOUND;
00448   }
00449 
00450   /* skip first */
00451   b=strtok(NULL,":");
00452   if (!b) {
00453      SUBDBG("Skipping first failed\n");
00454      return PFM_ERR_UMASK; /* Must be this value!! */
00455   }
00456 
00457   while(b) {
00458     a=0;
00459     while(1) {
00460 
00461       SUBDBG("get_event_attr %#x %d %p\n",current_event->libpfm4_idx,a,&ainfo);
00462 
00463       memset(&ainfo,0,sizeof(pfm_event_attr_info_t));
00464 
00465       ret = pfm_get_event_attr_info(current_event->libpfm4_idx, a, 
00466                     PFM_OS_PERF_EVENT, &ainfo);
00467 
00468       if (ret != PFM_SUCCESS) {
00469     SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret));
00470     return ret;
00471       }
00472 
00473       SUBDBG("Trying %s with %s\n",ainfo.name,b);
00474 
00475       if (ainfo.type == PFM_ATTR_MOD_BOOL) {
00476      sprintf(temp_string,"%s=0",ainfo.name);
00477          if (!strcasecmp(temp_string, b)) {
00478         SUBDBG("Found %s %d\n",b,a);
00479         if (a>max) max=a;
00480         goto found_attr;
00481      }
00482       }
00483       else if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
00484      sprintf(temp_string,"%s=0",ainfo.name);
00485          if (!strcasecmp(temp_string, b)) {
00486         SUBDBG("Found %s %d\n",b,a);
00487         if (a>max) max=a;
00488         goto found_attr;
00489      }
00490       }
00491       else {
00492          if (!strcasecmp(ainfo.name, b)) {
00493         SUBDBG("Found %s %d\n",b,a);
00494         if (a>max) max=a;
00495         goto found_attr;
00496      }
00497       }
00498       a++;
00499     }
00500 
00501     SUBDBG("attr=%s not found for event %s\n", b, info.name);
00502 
00503     return PFM_ERR_ATTR;
00504 
00505 found_attr:
00506 
00507     b=strtok(NULL,":");
00508   }
00509 
00510   SUBDBG("Found max %d\n", max);
00511 
00512   return max;
00513 }
00514 
00515 
00516 
00525 static int
00526 get_event_first_active(int pmu_type)
00527 {
00528   int pidx, pmu_idx, ret;
00529 
00530   pfm_pmu_info_t pinfo;
00531 
00532   pmu_idx=0;
00533 
00534   while(pmu_idx<PFM_PMU_MAX) {
00535 
00536     /* clear the PMU structure (required by libpfm4) */
00537     memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00538     ret=pfm_get_pmu_info(pmu_idx, &pinfo);
00539 
00540     if ((ret==PFM_SUCCESS) && pmu_is_present_and_right_type(&pinfo,pmu_type)) {
00541 
00542       pidx=pinfo.first_event;
00543 
00544       SUBDBG("First event in %s is %d\n",pinfo.name,pidx);
00545 
00546       if (pidx<0) {
00547     /* For some reason no events available */
00548     /* despite the PMU being active.       */
00549         /* This can happen, for example with ix86arch */
00550     /* inside of VMware                           */
00551       }
00552       else {
00553          return pidx;
00554       }
00555     }
00556 
00557     pmu_idx++;
00558 
00559   }
00560 
00561   return PAPI_ENOEVNT;
00562   
00563 }
00564 
00565 
00566 
00581 static int
00582 convert_libpfm4_to_string( int code, char **event_name)
00583 {
00584 
00585   int ret;
00586   pfm_event_info_t gete;
00587   pfm_pmu_info_t pinfo;
00588   char name[BUFSIZ];
00589 
00590   SUBDBG("ENTER %#x\n",code);
00591 
00592   /* Clear structures, as wanted by libpfm4 */
00593   memset( &gete, 0, sizeof (pfm_event_info_t) );
00594 
00595   ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &gete);
00596   if (ret!=PFM_SUCCESS) {
00597      return ret;
00598   }
00599 
00600   memset( &pinfo, 0, sizeof(pfm_pmu_info_t) );
00601   ret=pfm_get_pmu_info(gete.pmu, &pinfo);
00602   if (ret!=PFM_SUCCESS) {
00603      return ret;
00604   }
00605 
00606   sprintf(name,"%s::%s",pinfo.name,gete.name);
00607   *event_name=strdup(name);
00608 
00609   SUBDBG("Found name: %s\n",*event_name);
00610 
00611   return PFM_SUCCESS;
00612 
00613 }
00614 
00615 
00630 static int convert_pfmidx_to_native(int code, unsigned int *PapiEventCode,
00631                     struct native_event_table_t *event_table) {
00632 
00633   int ret;
00634   char *name=NULL;
00635 
00636   ret=convert_libpfm4_to_string( code, &name);
00637   if (ret!=PFM_SUCCESS) {
00638      return _papi_libpfm4_error(ret);
00639   }
00640 
00641   SUBDBG("Converted %#x to %s\n",code,name);
00642 
00643   ret=_peu_libpfm4_ntv_name_to_code(name,PapiEventCode,event_table);
00644 
00645   SUBDBG("Converted %s to event %#x\n",name,*PapiEventCode);
00646 
00647   if (name) free(name);
00648 
00649   return ret;
00650 
00651 }
00652 
00653 
00672 static int find_next_umask(struct native_event_t *current_event,
00673                            int current,char *umask_name) {
00674 
00675   char temp_string[BUFSIZ];
00676   pfm_event_info_t event_info;
00677   pfm_event_attr_info_t ainfo;
00678   int num_masks=0;
00679   pfm_err_t ret;
00680   int i;
00681 
00682   /* get number of attributes */
00683 
00684   memset(&event_info, 0, sizeof(event_info));
00685   ret=pfm_get_event_info(current_event->libpfm4_idx, 
00686              PFM_OS_PERF_EVENT, &event_info);
00687   if (ret!=PFM_SUCCESS) {
00688      return ret;
00689   }
00690 
00691   SUBDBG("%d possible attributes for event %s\n",
00692      event_info.nattrs,
00693      event_info.name);
00694 
00695   pfm_for_each_event_attr(i, &event_info) {
00696 
00697      ainfo.size = sizeof(ainfo);
00698 
00699      ret = pfm_get_event_attr_info(event_info.idx, i, PFM_OS_PERF_EVENT, 
00700                    &ainfo);
00701      if (ret != PFM_SUCCESS) {
00702         SUBDBG("Not found\n");
00703     return PFM_ERR_NOTFOUND;
00704      }
00705 
00706      if (ainfo.type == PFM_ATTR_UMASK) {
00707     SUBDBG("nm %d looking for %d\n",num_masks,current);
00708     if (num_masks==current+1) {
00709        SUBDBG("Found attribute %d: %s type: %d\n",
00710           i,ainfo.name,ainfo.type);
00711 
00712            sprintf(temp_string,"%s",ainfo.name);
00713            strncpy(umask_name,temp_string,BUFSIZ);
00714 
00715        return current+1;
00716     }
00717     num_masks++;
00718      }
00719 
00720      if (ainfo.type == PFM_ATTR_MOD_BOOL) {
00721     SUBDBG("nm %d looking for %d\n",num_masks,current);
00722 
00723     if (num_masks==current+1) {
00724        SUBDBG("Found attribute %d: %s type: %d\n",
00725           i,ainfo.name,ainfo.type);
00726 
00727            sprintf(temp_string,"%s=0",ainfo.name);
00728            strncpy(umask_name,temp_string,BUFSIZ);
00729 
00730        return current+1;
00731     }
00732     num_masks++;
00733      }
00734 
00735      if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
00736     SUBDBG("nm %d looking for %d\n",num_masks,current);
00737     if (num_masks==current+1) {
00738        SUBDBG("Found attribute %d: %s type: %d\n",
00739           i,ainfo.name,ainfo.type);
00740 
00741            sprintf(temp_string,"%s=0",ainfo.name);
00742            strncpy(umask_name,temp_string,BUFSIZ);
00743 
00744        return current+1;
00745     }
00746     num_masks++;
00747      }
00748   }
00749 
00750   return PFM_ERR_ATTR;
00751 
00752 }
00753 
00754 
00755 
00756 /***********************************************************/
00757 /* Exported functions                                      */
00758 /***********************************************************/
00759 
00774 int
00775 _peu_libpfm4_ntv_name_to_code( char *name, unsigned int *event_code,
00776                 struct native_event_table_t *event_table)
00777 {
00778 
00779   int actual_idx;
00780   struct native_event_t *our_event;
00781   int event_num;
00782 
00783   SUBDBG( "Converting %s\n", name);
00784 
00785   event_num=find_existing_event(name,event_table);
00786 
00787   if (event_num<0) {
00788 
00789      /* event currently doesn't exist, so try to find it */
00790      /* using libpfm4                                    */
00791 
00792      SUBDBG("Using pfm to look up event %s\n",name);
00793 
00794      actual_idx=find_event(name, event_table->pmu_type);
00795      if (actual_idx<0) {
00796         return _papi_libpfm4_error(actual_idx);
00797      }
00798 
00799      SUBDBG("Using %#x as the index\n",actual_idx);
00800 
00801      /* We were found in libpfm4, so allocate our copy of the event */
00802 
00803      our_event=allocate_native_event(name,actual_idx,event_table);
00804      if (our_event==NULL) return PAPI_ENOEVNT;
00805 
00806      event_num=find_existing_event(name,event_table);
00807   }
00808 
00809   if (event_num>=0) {
00810      *event_code=event_num;
00811      SUBDBG("Found code: %#x\n",*event_code);
00812      return PAPI_OK;
00813   }
00814 
00815   /* Failure here means allocate_native_event failed */
00816 
00817   SUBDBG("Event %s not found\n",name);
00818 
00819   return PAPI_ENOEVNT;
00820 
00821 }
00822 
00823 
00841 int
00842 _peu_libpfm4_ntv_code_to_name(unsigned int EventCode,
00843                    char *ntv_name, int len,
00844                    struct native_event_table_t *event_table)
00845 {
00846 
00847         struct native_event_t *our_event;
00848 
00849         SUBDBG("ENTER %#x\n",EventCode);
00850 
00851         our_event=find_existing_event_by_number(EventCode,event_table);
00852     if (our_event==NULL) {
00853       return PAPI_ENOEVNT;
00854     }
00855 
00856     strncpy(ntv_name,our_event->allocated_name,len);
00857 
00858     if (strlen(our_event->allocated_name) > (unsigned)len) {
00859        return PAPI_EBUF;
00860     }
00861 
00862     return PAPI_OK;
00863 }
00864 
00865 
00888 int
00889 _peu_libpfm4_ntv_code_to_descr( unsigned int EventCode,
00890                  char *ntv_descr, int len,
00891                      struct native_event_table_t *event_table)
00892 {
00893   int ret,a,first_mask=1;
00894   char *eventd, *tmp=NULL;
00895   pfm_event_info_t gete;
00896 
00897   pfm_event_attr_info_t ainfo;
00898   char *b;
00899   char event_string[BUFSIZ],*ptr;
00900   char temp_string[BUFSIZ];
00901 
00902   struct native_event_t *our_event;
00903 
00904   SUBDBG("ENTER %#x\n",EventCode);
00905 
00906   our_event=find_existing_event_by_number(EventCode,event_table);
00907   if (our_event==NULL) {
00908      return PAPI_ENOEVNT;
00909   }
00910 
00911   SUBDBG("Getting info on %#x\n",our_event->libpfm4_idx);
00912 
00913   /* libpfm requires the structure be zeroed */
00914   memset( &gete, 0, sizeof ( gete ) );
00915 
00916   ret=pfm_get_event_info(our_event->libpfm4_idx, PFM_OS_PERF_EVENT, &gete);
00917   if (ret<0) {
00918      SUBDBG("Return=%d\n",ret);
00919      return _papi_libpfm4_error(ret);
00920   }
00921 
00922   eventd=strdup(gete.desc);
00923 
00924   tmp = ( char * ) malloc( strlen( eventd ) + 1 );
00925   if ( tmp == NULL ) {
00926      free( eventd );
00927      return PAPI_ENOMEM;
00928   }
00929 
00930   tmp[0] = '\0';
00931   strcat( tmp, eventd );
00932   free( eventd );
00933 
00934   /* Handle Umasks */
00935 
00936   /* attributes concactinated onto end of descr separated by ", masks" */
00937   /* then comma separated */
00938 
00939   strcpy(event_string,our_event->allocated_name);
00940 
00941   /* Point to first umask */
00942 
00943   /* Skip the pmu name :: if one exists */
00944   if (strstr(event_string,"::")) {
00945      ptr=strstr(event_string,"::");
00946      ptr+=2;
00947      b=strtok(ptr,":");
00948   }
00949   else {
00950      b=strtok(event_string,":");
00951   }
00952 
00953   /* if no umask, then done */
00954   if (!b) {
00955      SUBDBG("No colon!\n"); /* no umask */
00956      goto descr_in_tmp;
00957   }
00958 
00959   /* skip first */
00960   b=strtok(NULL,":");
00961   if (!b) {
00962      SUBDBG("Skipping first failed\n");
00963      goto descr_in_tmp;
00964   }
00965 
00966   /* loop through all umasks, seeing which match */
00967   while(b) {
00968     a=0;
00969     while(1) {
00970 
00971       SUBDBG("get_event_attr %#x %p\n",our_event->libpfm4_idx,&ainfo);
00972 
00973       memset(&ainfo,0,sizeof(pfm_event_attr_info_t));
00974 
00975       ret = pfm_get_event_attr_info(our_event->libpfm4_idx, a,
00976                     PFM_OS_PERF_EVENT, &ainfo);
00977       if (ret != PFM_SUCCESS) {
00978     free( tmp );
00979     SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret));
00980     return _papi_libpfm4_error(ret);
00981       }
00982 
00983       /* Plain UMASK case */
00984       if (ainfo.type == PFM_ATTR_UMASK) {
00985 
00986          SUBDBG("Trying %s with %s\n",ainfo.name,b);
00987 
00988          if (!strcasecmp(ainfo.name, b)) {
00989         int new_length;
00990 
00991         SUBDBG("Found %s\n",b);
00992         new_length=strlen(ainfo.desc);
00993 
00994         if (first_mask) {
00995            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
00996            strcat(tmp,", masks:");
00997            first_mask=0;
00998         }
00999         else {
01000            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
01001            strcat(tmp,",");
01002         }
01003         strcat(tmp,ainfo.desc);
01004 
01005         goto found_attr;
01006      }
01007       }
01008 
01009       /* Boolean Case */
01010       if (ainfo.type == PFM_ATTR_MOD_BOOL) {
01011 
01012      sprintf(temp_string,"%s=0",ainfo.name);
01013 
01014          SUBDBG("Trying %s with %s\n",temp_string,b);
01015 
01016          if (!strcasecmp(temp_string, b)) {
01017         int new_length;
01018 
01019         SUBDBG("Found %s\n",b);
01020         new_length=strlen(ainfo.desc);
01021 
01022         if (first_mask) {
01023            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
01024            strcat(tmp,", masks:");
01025            first_mask=0;
01026         }
01027         else {
01028            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
01029            strcat(tmp,",");
01030         }
01031         strcat(tmp,ainfo.desc);
01032 
01033         goto found_attr;
01034      }
01035       }
01036 
01037       /* Integer Case */
01038       if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
01039 
01040      sprintf(temp_string,"%s=0",ainfo.name);
01041 
01042          SUBDBG("Trying %s with %s\n",temp_string,b);
01043 
01044          if (!strcasecmp(temp_string, b)) {
01045         int new_length;
01046 
01047         SUBDBG("Found %s\n",b);
01048         new_length=strlen(ainfo.desc);
01049 
01050         if (first_mask) {
01051            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
01052            strcat(tmp,", masks:");
01053            first_mask=0;
01054         }
01055         else {
01056            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
01057            strcat(tmp,",");
01058         }
01059         strcat(tmp,ainfo.desc);
01060 
01061         goto found_attr;
01062      }
01063       }
01064 
01065       a++;
01066     }
01067 
01068     SUBDBG("attr=%s not found for event %s\n", b, ainfo.name);
01069 
01070     return PAPI_EATTR;
01071 
01072 found_attr:
01073 
01074     b=strtok(NULL,":");
01075   }
01076 
01077   /* We are done and the description to copy is in tmp */
01078 descr_in_tmp:
01079     strncpy( ntv_descr, tmp, ( size_t ) len );
01080     if ( ( int ) strlen( tmp ) > len - 1 )
01081         ret = PAPI_EBUF;
01082     else
01083         ret = PAPI_OK;
01084     free( tmp );
01085 
01086     SUBDBG("PFM4 Code: %#x %s\n",EventCode,ntv_descr);
01087 
01088     return ret;
01089 }
01090 
01091 
01092 int
01093 _peu_libpfm4_ntv_code_to_info(unsigned int EventCode,
01094                    PAPI_event_info_t *info,
01095                    struct native_event_table_t *event_table)
01096 {
01097 
01098 
01099   struct native_event_t *our_event;
01100 
01101   SUBDBG("ENTER %#x\n",EventCode);
01102 
01103   our_event=find_existing_event_by_number(EventCode,event_table);
01104   if (our_event==NULL) {
01105      return PAPI_ENOEVNT;
01106   }
01107 
01108   strncpy(info->symbol, our_event->allocated_name, sizeof(info->symbol));
01109 
01110   if (strlen(our_event->allocated_name) > sizeof(info->symbol)) {
01111      return PAPI_EBUF;
01112   }
01113 
01114   _peu_libpfm4_ntv_code_to_descr(EventCode,info->long_descr,
01115                   sizeof(info->long_descr),event_table);
01116 
01117   return PAPI_OK;
01118 }
01119 
01120 
01121 
01138 int
01139 _peu_libpfm4_ntv_enum_events( unsigned int *PapiEventCode,
01140                    int modifier,
01141                    struct native_event_table_t *event_table) {
01142 
01143     int code,ret;
01144     struct native_event_t *current_event;
01145 
01146         SUBDBG("ENTER\n");
01147 
01148     /* return first event if so specified */
01149     if ( modifier == PAPI_ENUM_FIRST ) {
01150 
01151        unsigned int papi_event=0;
01152 
01153            SUBDBG("ENUM_FIRST\n");
01154 
01155        code=get_event_first_active(event_table->pmu_type);
01156        SUBDBG("ENUM_FIRST code: %d\n",code);
01157        if (code < 0 ) {
01158           return code;
01159        }
01160 
01161        /* convert the libpfm4 event to a PAPI event */
01162        ret=convert_pfmidx_to_native(code, &papi_event,event_table);
01163 
01164        *PapiEventCode=(unsigned int)papi_event;
01165 
01166            SUBDBG("FOUND %#x (from %#x) ret=%d\n",*PapiEventCode,code,ret);
01167 
01168        return ret;
01169     }
01170 
01171     /* If we get this far, we're looking for a        */
01172     /* next-event.  So gather info on the current one */
01173     current_event=find_existing_event_by_number(*PapiEventCode,
01174                             event_table);
01175     if (current_event==NULL) {
01176            SUBDBG("EVENTS %#x not found\n",*PapiEventCode);
01177        return PAPI_ENOEVNT;
01178     }
01179 
01180 
01181     /* Handle looking for the next event */
01182 
01183     if ( modifier == PAPI_ENUM_EVENTS ) {
01184 
01185        unsigned int papi_event=0;
01186 
01187        SUBDBG("PAPI_ENUM_EVENTS %#x\n",*PapiEventCode);
01188 
01189        code=current_event->libpfm4_idx;
01190 
01191        ret=find_next_no_aliases(code,event_table->pmu_type);
01192        SUBDBG("find_next_no_aliases() Returned %#x\n",ret);
01193        if (ret<0) {
01194           return ret;
01195        }
01196 
01197        /* Convert libpfm4 event code to PAPI event code */
01198        ret=convert_pfmidx_to_native(ret, &papi_event, event_table);
01199        if (ret<0) {
01200            SUBDBG("Couldn't convert to native %d %s\n",
01201               ret,PAPI_strerror(ret));
01202            return ret;
01203        }
01204 
01205        *PapiEventCode=(unsigned int)papi_event;
01206 
01207            SUBDBG("Returning PAPI_OK\n");
01208 
01209        return ret;
01210     }
01211 
01212     /* We don't handle PAPI_NTV_ENUM_UMASK_COMBOS */
01213     if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) {
01214        return PAPI_ENOIMPL;
01215     }
01216 
01217     /* Enumerate PAPI_NTV_ENUM_UMASKS (umasks on an event) */
01218     if ( modifier == PAPI_NTV_ENUM_UMASKS ) {
01219 
01220        int max_umask,next_umask;
01221        char umask_string[BUFSIZ],new_name[BUFSIZ];
01222 
01223        SUBDBG("Finding maximum mask in event %s\n",
01224                   current_event->allocated_name);
01225 
01226        max_umask=find_max_umask(current_event);
01227        SUBDBG("Found max %d\n",max_umask);
01228 
01229        if (max_umask<0) {
01230           if (max_umask==PFM_ERR_UMASK) {
01231              max_umask=-1; /* needed for find_next_umask() to work */
01232                        /* indicates the event as passed had no */
01233                        /* umask in it.                         */
01234           }
01235           else {
01236              return _papi_libpfm4_error(max_umask);
01237           }
01238        }
01239 
01240        next_umask=find_next_umask(current_event,max_umask,
01241                       umask_string);
01242 
01243        SUBDBG("Found next %d\n",next_umask);
01244 
01245        if (next_umask>=0) {
01246 
01247           unsigned int papi_event;
01248 
01249           sprintf(new_name,"%s:%s",current_event->base_name,
01250              umask_string);
01251 
01252           SUBDBG("Found new name %s\n",new_name);
01253 
01254               ret=_peu_libpfm4_ntv_name_to_code(new_name,&papi_event,
01255                          event_table);
01256           if (ret!=PAPI_OK) {
01257          return PAPI_ENOEVNT;
01258           }
01259 
01260           *PapiEventCode=(unsigned int)papi_event;
01261           SUBDBG("found code %#x\n",*PapiEventCode);
01262 
01263           return PAPI_OK;
01264        }
01265 
01266        SUBDBG("couldn't find umask\n");
01267 
01268        return _papi_libpfm4_error(next_umask);
01269 
01270     }
01271 
01272     /* An unknown enumeration method was indicated */
01273 
01274     return PAPI_ENOIMPL;
01275 }
01276 
01287 int
01288 _peu_libpfm4_shutdown(struct native_event_table_t *event_table) {
01289 
01290   int i;
01291 
01292   APIDBG("Entry\n");
01293 
01294   /* clean out and free the native events structure */
01295   _papi_hwi_lock( NAMELIB_LOCK );
01296 
01297   /* Only free if we're the last user */
01298 
01299   /* free memory allocated with strdup */
01300   for( i=0; i<event_table->num_native_events; i++) {
01301      free(event_table->native_events[i].base_name);
01302      free(event_table->native_events[i].pmu_plus_name);
01303      free(event_table->native_events[i].pmu);
01304      free(event_table->native_events[i].allocated_name);
01305   }
01306 
01307   memset(event_table->native_events,0,
01308      sizeof(struct native_event_t)*event_table->allocated_native_events);
01309   event_table->num_native_events=0;
01310   event_table->allocated_native_events=0;
01311   free(event_table->native_events);
01312 
01313   _papi_hwi_unlock( NAMELIB_LOCK );
01314 
01315   return PAPI_OK;
01316 }
01317 
01329 int
01330 _peu_libpfm4_init(papi_vector_t *my_vector, 
01331            struct native_event_table_t *event_table,
01332            int pmu_type) {
01333 
01334    int detected_pmus=0;
01335    int i;
01336    pfm_err_t retval = PFM_SUCCESS;
01337    unsigned int ncnt;
01338    pfm_pmu_info_t pinfo;
01339 
01340    /* allocate the native event structure */
01341 
01342    event_table->num_native_events=0;
01343    event_table->pmu_type=pmu_type;
01344 
01345    event_table->native_events=calloc(NATIVE_EVENT_CHUNK,
01346                        sizeof(struct native_event_t));
01347    if (event_table->native_events==NULL) {
01348       return PAPI_ENOMEM;
01349    }
01350    event_table->allocated_native_events=NATIVE_EVENT_CHUNK;
01351 
01352    /* Count number of present PMUs */
01353    detected_pmus=0;
01354    ncnt=0;
01355 
01356    my_vector->cmp_info.num_cntrs=0;
01357 
01358    SUBDBG("Detected pmus:\n");
01359    for(i=0;i<PFM_PMU_MAX;i++) {
01360       memset(&pinfo,0,sizeof(pfm_pmu_info_t));
01361       retval=pfm_get_pmu_info(i, &pinfo);
01362       if (retval!=PFM_SUCCESS) {
01363      continue;
01364       }
01365 
01366       if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
01367      SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type);
01368 
01369          detected_pmus++;
01370      ncnt+=pinfo.nevents;
01371 
01372          my_vector->cmp_info.num_cntrs += pinfo.num_cntrs+
01373                                    pinfo.num_fixed_cntrs;
01374       }
01375    }
01376    SUBDBG("%d native events detected on %d pmus\n",ncnt,detected_pmus);
01377 
01378    my_vector->cmp_info.num_native_events = ncnt;
01379 
01380    SUBDBG( "num_counters: %d\n", my_vector->cmp_info.num_cntrs );
01381 
01382    return PAPI_OK;
01383 }
01384 
01385 
01400 int
01401 _peu_libpfm4_setup_counters( struct perf_event_attr *attr,
01402                   int event,
01403                   struct native_event_table_t *event_table) {
01404 
01405   struct native_event_t *our_event;
01406 
01407   our_event=find_existing_event_by_number(event,event_table);
01408   if (our_event==NULL) {
01409      return PAPI_ENOEVNT;
01410   }
01411 
01412   attr->config=our_event->config;
01413   attr->config1=our_event->config1;
01414   attr->config2=our_event->config2;
01415   attr->type=our_event->type;
01416 
01417   SUBDBG( "pe_event: config 0x%"PRIx64
01418           " config1 0x%"PRIx64
01419           " type 0x%"PRIx32"\n",
01420           attr->config,
01421       attr->config1,
01422       attr->type);
01423 
01424   return PAPI_OK;
01425 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines