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