PAPI  5.0.1.0
papi_libpfm4_events.c
Go to the documentation of this file.
00001 /*
00002 * File:    papi_libpfm4_events.c
00003 * Author:  Vince Weaver vweaver1 @ eecs.utk.edu
00004 *          based heavily on existing papi_libpfm3_events.c
00005 */
00006 
00007 #include <string.h>
00008 
00009 #include "papi.h"
00010 #include "papi_internal.h"
00011 #include "papi_vector.h"
00012 
00013 #include "papi_libpfm4_events.h"
00014 
00015 #include "perfmon/pfmlib.h"
00016 #include "perfmon/pfmlib_perf_event.h"
00017 
00018 #define NATIVE_EVENT_CHUNK 1024
00019 
00020 struct native_event_t {
00021   int component;
00022   char *pmu;
00023   int libpfm4_idx;
00024   char *allocated_name;
00025   char *base_name;
00026   char *pmu_plus_name;
00027   int users;
00028   long long config;
00029   long long config1;
00030   long long config2;
00031   int type;
00032 };
00033 
00034 static struct native_event_t *native_events;
00035 
00036 static int num_native_events=0;
00037 static int allocated_native_events=0;
00038 
00039 static pfm_pmu_info_t default_pmu;
00040 
00041 
00052 static int find_existing_event(char *name) {
00053 
00054   int i,event=PAPI_ENOEVNT;
00055 
00056   SUBDBG("Looking for %s in %d events\n",name,num_native_events);
00057 
00058   _papi_hwi_lock( NAMELIB_LOCK );
00059 
00060   for(i=0;i<num_native_events;i++) {
00061 
00062     if (!strcmp(name,native_events[i].allocated_name)) {
00063       SUBDBG("Found %s (%x)\n",
00064          native_events[i].allocated_name,
00065          native_events[i].libpfm4_idx);
00066       event=i;
00067       break;
00068     }
00069   }
00070   _papi_hwi_unlock( NAMELIB_LOCK );
00071 
00072   if (event<0) { SUBDBG("%s not allocated yet\n",name); }
00073 
00074   return event;
00075 }
00076 
00087 static struct native_event_t *find_existing_event_by_number(int eventnum) {
00088 
00089   struct native_event_t *temp_event=NULL;
00090 
00091   _papi_hwi_lock( NAMELIB_LOCK );
00092 
00093   temp_event=&native_events[eventnum];
00094   
00095   _papi_hwi_unlock( NAMELIB_LOCK );
00096 
00097   SUBDBG("Found %p for %x\n",temp_event,eventnum);
00098 
00099   return temp_event;
00100 }
00101 
00102 
00113 static int find_event_no_aliases(char *name) {
00114 
00115     int j,i, ret;
00116     pfm_pmu_info_t pinfo;
00117     pfm_event_info_t event_info;
00118     char full_name[BUFSIZ];
00119 
00120     SUBDBG("Looking for %s\n",name);
00121 
00122     pfm_for_all_pmus(j) {
00123 
00124        memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00125        pfm_get_pmu_info(j, &pinfo);
00126        if (!pinfo.is_present) {
00127           continue;
00128        }
00129 
00130        SUBDBG("Looking in pmu %d\n",j);   
00131        i = pinfo.first_event; 
00132        while(1) {
00133           memset(&event_info,0,sizeof(pfm_event_info_t));
00134           ret=pfm_get_event_info(i, PFM_OS_PERF_EVENT, &event_info);
00135       if (ret<0) break;
00136     
00137       sprintf(full_name,"%s::%s",pinfo.name,event_info.name);
00138 
00139       if (!strcmp(name,full_name)) {
00140          SUBDBG("FOUND %s %s %x\n",name,full_name,i);
00141          return i;
00142       }
00143 
00144       if (!strcmp(name,event_info.name)) {
00145          SUBDBG("FOUND %s %s %x\n",name,event_info.name,i);
00146          return i;
00147       }
00148       i=pfm_get_event_next(i);
00149        }
00150     }
00151     return PFM_ERR_NOTFOUND;
00152 }
00153 
00165 static int find_next_no_aliases(int code) {
00166 
00167   int current_pmu=0,current_event=0;
00168   pfm_err_t ret;
00169   pfm_pmu_info_t pinfo;
00170   pfm_event_info_t event_info;
00171 
00172   /* Clear the structures, as libpfm4 requires it */
00173   memset(&event_info,0,sizeof(pfm_event_info_t));
00174 
00175   ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &event_info);
00176   if (ret!=PFM_SUCCESS) {
00177      return ret;
00178   }
00179 
00180   current_pmu=event_info.pmu;
00181   current_event=pfm_get_event_next(code);
00182 
00183   SUBDBG("Current is %x guessing next is %x\n",code,current_event);
00184 
00185   while(1) {
00186 
00187      memset(&event_info,0,sizeof(pfm_event_info_t));
00188      ret=pfm_get_event_info(current_event, PFM_OS_PERF_EVENT, &event_info);
00189      if (ret==PFM_SUCCESS) {
00190         SUBDBG("Returning %x\n",current_event);
00191         return current_event;
00192      }
00193 
00194      /* next event not found, so try moving to next PMU */
00195 
00196      while(1) {
00197 
00198         current_pmu++;
00199         SUBDBG("Incrementing PMU: %x\n",current_pmu);
00200 
00201     /* Off the end, so done iterating */
00202         if (current_pmu>PFM_PMU_MAX) {
00203            return PFM_ERR_NOTFOUND;
00204         }
00205  
00206         memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00207         pfm_get_pmu_info(current_pmu, &pinfo);
00208         if (pinfo.is_present) break;
00209      }
00210 
00211      current_event=pinfo.first_event;
00212 
00213   }
00214 
00215 }
00216 
00229 static struct native_event_t *allocate_native_event(char *name, 
00230                             int event_idx) {
00231 
00232   int new_event;
00233 
00234   pfm_err_t ret;
00235   unsigned int i;
00236   char *base_start;
00237   pfm_event_info_t info;
00238   pfm_pmu_info_t pinfo;
00239   char base[BUFSIZ],pmuplusbase[BUFSIZ];
00240   char fullname[BUFSIZ];
00241 
00242   pfm_perf_encode_arg_t perf_arg;
00243 
00244   struct perf_event_attr perf_attr;
00245 
00246   /* get the event name from libpfm */
00247   memset(&info,0,sizeof(pfm_event_info_t));
00248   ret = pfm_get_event_info(event_idx, PFM_OS_PERF_EVENT, &info);
00249   if (ret!=PFM_SUCCESS) {
00250      return NULL;
00251   }
00252 
00253   /* get the PMU info */
00254   memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00255   pfm_get_pmu_info(info.pmu, &pinfo);
00256 
00257   /* calculate the base name, meaning strip off pmu identifier */
00258   strncpy(base,name,BUFSIZ);
00259   i=0;
00260   base_start=base;
00261   while(i<strlen(base)) {
00262     if (base[i]==':') {
00263       if (base[i+1]==':') {
00264           i++;
00265       base_start=&base[i+1];
00266       }
00267       else {
00268     base[i]=0;
00269       }
00270     }
00271     i++;
00272   }
00273 
00274   /* add the event */
00275   _papi_hwi_lock( NAMELIB_LOCK );
00276 
00277   new_event=num_native_events;
00278 
00279   native_events[new_event].base_name=strdup(base_start);
00280 
00281   sprintf(fullname,"%s::%s",pinfo.name,info.name);
00282   native_events[new_event].pmu_plus_name=strdup(fullname);
00283 
00284   sprintf(pmuplusbase,"%s::%s",pinfo.name,base_start);
00285 
00286   native_events[new_event].component=0;
00287   native_events[new_event].pmu=strdup(pinfo.name);
00288     
00289   native_events[new_event].libpfm4_idx=find_event_no_aliases(pmuplusbase);
00290 
00291   SUBDBG("Using %x as index instead of %x for %s\n",
00292      native_events[new_event].libpfm4_idx,event_idx,pmuplusbase);
00293 
00294   native_events[new_event].allocated_name=strdup(name);
00295 
00296   /* is this needed? */
00297   native_events[new_event].users=0;
00298 
00299 
00300   /* use name of the event to get the perf_event encoding */
00301 
00302   /* clear the attribute structure */
00303   memset(&perf_arg,0,sizeof(pfm_perf_encode_arg_t));
00304 
00305   /* clear out the perf_attr struct */
00306   memset(&perf_attr,0,sizeof(struct perf_event_attr));
00307   perf_arg.attr=&perf_attr;
00308 
00309   ret = pfm_get_os_event_encoding(name, 
00310                   PFM_PLM0 | PFM_PLM3, 
00311                                   PFM_OS_PERF_EVENT, 
00312                   &perf_arg);
00313   if (ret!=PFM_SUCCESS) {
00314      /* should do something! */
00315   }
00316   
00317   native_events[new_event].config=perf_arg.attr->config;
00318   native_events[new_event].config1=perf_arg.attr->config1;
00319   native_events[new_event].type=perf_arg.attr->type;
00320 
00321   SUBDBG( "pe_event: config 0x%"PRIx64" config1 0x%"PRIx64" type 0x%"PRIx32"\n", 
00322           perf_arg.attr->config, 
00323       perf_arg.attr->config1,
00324       perf_arg.attr->type);
00325 
00326   SUBDBG("Creating event %s with perfidx %x\n",
00327      name,
00328      native_events[new_event].libpfm4_idx);
00329 
00330   num_native_events++;
00331 
00332   /* If we've allocated too many native events, then allocate more room */
00333   if (num_native_events >= allocated_native_events) {
00334 
00335      SUBDBG("Allocating more room for native events (%d %ld)\n",
00336         (allocated_native_events+NATIVE_EVENT_CHUNK),
00337         (long)sizeof(struct native_event_t) *
00338         (allocated_native_events+NATIVE_EVENT_CHUNK));
00339 
00340      native_events=realloc(native_events,
00341                sizeof(struct native_event_t) * 
00342                (allocated_native_events+NATIVE_EVENT_CHUNK));
00343      allocated_native_events+=NATIVE_EVENT_CHUNK;
00344   }
00345 
00346   _papi_hwi_unlock( NAMELIB_LOCK );
00347 
00348   if (native_events==NULL) {
00349      return NULL;
00350   }
00351 
00352   return &native_events[new_event];
00353 
00354 }
00355 
00370 static int find_max_umask(struct native_event_t *current_event) {
00371 
00372   pfm_event_attr_info_t ainfo;
00373   char *b;
00374   int a, ret, max =0;
00375   pfm_event_info_t info;
00376   char event_string[BUFSIZ],*ptr;
00377   char temp_string[BUFSIZ];
00378 
00379   SUBDBG("Trying to find max umask in %s\n",current_event->allocated_name);
00380 
00381   strcpy(event_string,current_event->allocated_name);
00382 
00383   /* Skip leading :: delimited PMU name and point to first umask */
00384   if (strstr(event_string,"::")) {
00385      ptr=strstr(event_string,"::");
00386      ptr+=2;
00387      b=strtok(ptr,":");
00388   }
00389   else {
00390      b=strtok(event_string,":");
00391   }
00392 
00393   if (!b) {
00394      SUBDBG("No colon!\n");
00395      return PFM_ERR_UMASK; /* Must be this value!! */
00396   }
00397 
00398   memset(&info,0,sizeof(pfm_event_info_t));
00399   ret = pfm_get_event_info(current_event->libpfm4_idx, 
00400                PFM_OS_PERF_EVENT, &info);
00401   if (ret!=PFM_SUCCESS) {
00402      SUBDBG("get_event_info failed\n");
00403      return PFM_ERR_NOTFOUND;
00404   }
00405 
00406   /* skip first */
00407   b=strtok(NULL,":");
00408   if (!b) {
00409      SUBDBG("Skipping first failed\n");
00410      return PFM_ERR_UMASK; /* Must be this value!! */
00411   }
00412 
00413   while(b) {
00414     a=0;
00415     while(1) {
00416 
00417       SUBDBG("get_event_attr %x %d %p\n",current_event->libpfm4_idx,a,&ainfo);
00418 
00419       memset(&ainfo,0,sizeof(pfm_event_attr_info_t));
00420 
00421       ret = pfm_get_event_attr_info(current_event->libpfm4_idx, a, 
00422                     PFM_OS_PERF_EVENT, &ainfo);
00423 
00424       if (ret != PFM_SUCCESS) {
00425     SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret));
00426     return ret;
00427       }
00428 
00429       SUBDBG("Trying %s with %s\n",ainfo.name,b);
00430 
00431       if (ainfo.type == PFM_ATTR_MOD_BOOL) {
00432      sprintf(temp_string,"%s=0",ainfo.name);
00433          if (!strcasecmp(temp_string, b)) {
00434         SUBDBG("Found %s %d\n",b,a);
00435         if (a>max) max=a;
00436         goto found_attr;
00437      }
00438       }
00439       else if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
00440      sprintf(temp_string,"%s=0",ainfo.name);
00441          if (!strcasecmp(temp_string, b)) {
00442         SUBDBG("Found %s %d\n",b,a);
00443         if (a>max) max=a;
00444         goto found_attr;
00445      }
00446       }
00447       else {
00448          if (!strcasecmp(ainfo.name, b)) {
00449         SUBDBG("Found %s %d\n",b,a);
00450         if (a>max) max=a;
00451         goto found_attr;
00452      }
00453       }
00454       a++;
00455     }
00456 
00457     SUBDBG("attr=%s not found for event %s\n", b, info.name);
00458 
00459     return PFM_ERR_ATTR;
00460 
00461 found_attr:
00462 
00463     b=strtok(NULL,":");
00464   }
00465 
00466   SUBDBG("Found max %d\n", max);
00467 
00468   return max;
00469 }
00470 
00471 
00472 
00481 static int
00482 get_event_first_active(void)
00483 {
00484   int pidx, pmu_idx, ret;
00485 
00486   pfm_pmu_info_t pinfo;
00487 
00488   pmu_idx=0;
00489 
00490   while(pmu_idx<PFM_PMU_MAX) {
00491 
00492     /* clear the PMU structure (required by libpfm4) */
00493     memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00494     ret=pfm_get_pmu_info(pmu_idx, &pinfo);
00495 
00496     if ((ret==PFM_SUCCESS) && pinfo.is_present) {
00497 
00498       pidx=pinfo.first_event;
00499 
00500       SUBDBG("First event in %s is %d\n",pinfo.name,pidx);
00501 
00502       if (pidx<0) {
00503     /* For some reason no events available */
00504     /* despite the PMU being active.       */
00505         /* This can happen, for example with ix86arch */
00506     /* inside of VMware                           */
00507       }
00508       else {
00509          return pidx;
00510       }
00511     }
00512 
00513     pmu_idx++;
00514 
00515   }
00516 
00517   return PAPI_ENOEVNT;
00518   
00519 }
00520 
00521 
00522 
00537 static int
00538 convert_libpfm4_to_string( int code, char **event_name)
00539 {
00540 
00541   int ret;
00542   pfm_event_info_t gete;
00543   pfm_pmu_info_t pinfo;
00544   char name[BUFSIZ];
00545 
00546   SUBDBG("ENTER %x\n",code);
00547 
00548   /* Clear structures, as wanted by libpfm4 */
00549   memset( &gete, 0, sizeof (pfm_event_info_t) );
00550 
00551   ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &gete);
00552   if (ret!=PFM_SUCCESS) {
00553      return ret;
00554   }
00555 
00556   memset( &pinfo, 0, sizeof(pfm_pmu_info_t) );
00557   ret=pfm_get_pmu_info(gete.pmu, &pinfo);
00558   if (ret!=PFM_SUCCESS) {
00559      return ret;
00560   }
00561 
00562   /* Only prepend PMU name if not on the "default" PMU */
00563 
00564   if (pinfo.pmu == default_pmu.pmu) {
00565      *event_name=strdup(gete.name);
00566   }
00567   else {
00568      sprintf(name,"%s::%s",pinfo.name,gete.name);
00569      *event_name=strdup(name);
00570   }
00571 
00572   SUBDBG("Found name: %s\n",*event_name);
00573 
00574   return PFM_SUCCESS;
00575 
00576 }
00577 
00578 
00591 static int convert_pfmidx_to_native(int code, unsigned int *PapiEventCode) {
00592 
00593   int ret;
00594   char *name=NULL;
00595 
00596   ret=convert_libpfm4_to_string( code, &name);
00597   if (ret!=PFM_SUCCESS) {
00598      return _papi_libpfm4_error(ret);
00599   }
00600 
00601   SUBDBG("Converted %x to %s\n",code,name);
00602 
00603   ret=_papi_libpfm4_ntv_name_to_code(name,PapiEventCode);
00604 
00605   SUBDBG("Converted %s to event %x\n",name,*PapiEventCode);
00606 
00607   if (name) free(name);
00608 
00609   return ret;
00610 
00611 }
00612 
00613 
00632 static int find_next_umask(struct native_event_t *current_event,
00633                            int current,char *umask_name) {
00634 
00635   char temp_string[BUFSIZ];
00636   pfm_event_info_t event_info;
00637   pfm_event_attr_info_t ainfo;
00638   int num_masks=0;
00639   pfm_err_t ret;
00640   int i;
00641 
00642   /* get number of attributes */
00643 
00644   memset(&event_info, 0, sizeof(event_info));
00645   ret=pfm_get_event_info(current_event->libpfm4_idx, 
00646              PFM_OS_PERF_EVENT, &event_info);
00647   if (ret!=PFM_SUCCESS) {
00648      return ret;
00649   }
00650     
00651   SUBDBG("%d possible attributes for event %s\n",
00652      event_info.nattrs,
00653      event_info.name);
00654 
00655   pfm_for_each_event_attr(i, &event_info) {
00656 
00657      ainfo.size = sizeof(ainfo);
00658 
00659      ret = pfm_get_event_attr_info(event_info.idx, i, PFM_OS_PERF_EVENT, 
00660                    &ainfo);
00661      if (ret != PFM_SUCCESS) {
00662         SUBDBG("Not found\n");
00663     return PFM_ERR_NOTFOUND;
00664      }
00665 
00666      if (ainfo.type == PFM_ATTR_UMASK) {
00667     SUBDBG("nm %d looking for %d\n",num_masks,current);
00668     if (num_masks==current+1) {   
00669        SUBDBG("Found attribute %d: %s type: %d\n",
00670           i,ainfo.name,ainfo.type);
00671     
00672            sprintf(temp_string,"%s",ainfo.name);
00673            strncpy(umask_name,temp_string,BUFSIZ);
00674 
00675        return current+1;
00676     }
00677     num_masks++;
00678      }
00679 
00680      if (ainfo.type == PFM_ATTR_MOD_BOOL) {
00681     SUBDBG("nm %d looking for %d\n",num_masks,current);
00682     
00683     if (num_masks==current+1) {   
00684        SUBDBG("Found attribute %d: %s type: %d\n",
00685           i,ainfo.name,ainfo.type);
00686     
00687            sprintf(temp_string,"%s=0",ainfo.name);
00688            strncpy(umask_name,temp_string,BUFSIZ);
00689 
00690        return current+1;
00691     }
00692     num_masks++;
00693      }
00694 
00695      if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
00696     SUBDBG("nm %d looking for %d\n",num_masks,current);
00697     if (num_masks==current+1) {   
00698        SUBDBG("Found attribute %d: %s type: %d\n",
00699           i,ainfo.name,ainfo.type);
00700     
00701            sprintf(temp_string,"%s=0",ainfo.name);
00702            strncpy(umask_name,temp_string,BUFSIZ);
00703 
00704        return current+1;
00705     }
00706     num_masks++;
00707      }
00708   }
00709 
00710   return PFM_ERR_ATTR;
00711 
00712 }
00713 
00714 
00715 
00716 /***********************************************************/
00717 /* Exported functions                                      */
00718 /***********************************************************/
00719 
00720 
00731 int
00732 _papi_libpfm4_error( int pfm_error ) {
00733 
00734   switch ( pfm_error ) {
00735   case PFM_SUCCESS:      return PAPI_OK;       /* success */
00736   case PFM_ERR_NOTSUPP:  return PAPI_ENOSUPP;  /* function not supported */
00737   case PFM_ERR_INVAL:    return PAPI_EINVAL;   /* invalid parameters */
00738   case PFM_ERR_NOINIT:   return PAPI_ENOINIT;  /* library not initialized */
00739   case PFM_ERR_NOTFOUND: return PAPI_ENOEVNT;  /* event not found */
00740   case PFM_ERR_FEATCOMB: return PAPI_ECOMBO;   /* invalid combination of features */
00741   case PFM_ERR_UMASK:    return PAPI_EATTR;    /* invalid or missing unit mask */
00742   case PFM_ERR_NOMEM:    return PAPI_ENOMEM;   /* out of memory */
00743   case PFM_ERR_ATTR:     return PAPI_EATTR;    /* invalid event attribute */
00744   case PFM_ERR_ATTR_VAL: return PAPI_EATTR;    /* invalid event attribute value */
00745   case PFM_ERR_ATTR_SET: return PAPI_EATTR;    /* attribute value already set */
00746   case PFM_ERR_TOOMANY:  return PAPI_ECOUNT;   /* too many parameters */
00747   case PFM_ERR_TOOSMALL: return PAPI_ECOUNT;   /* parameter is too small */
00748   default: return PAPI_EINVAL;
00749   }
00750 }
00751 
00764 int
00765 _papi_libpfm4_ntv_name_to_code( char *name, unsigned int *event_code )
00766 {
00767 
00768   int actual_idx;
00769   struct native_event_t *our_event;
00770   int event_num;
00771 
00772   SUBDBG( "Converting %s\n", name);
00773 
00774   event_num=find_existing_event(name);
00775 
00776   if (event_num<0) {
00777 
00778      /* event currently doesn't exist, so try to find it */
00779      /* using libpfm4                                    */
00780 
00781      SUBDBG("Using pfm to look up event %s\n",name);
00782      actual_idx=pfm_find_event(name);
00783      if (actual_idx<0) {
00784         return _papi_libpfm4_error(actual_idx);
00785      }
00786 
00787      SUBDBG("Using %x as the index\n",actual_idx);
00788 
00789      /* We were found in libpfm4, so allocate our copy of the event */
00790 
00791      our_event=allocate_native_event(name,actual_idx);
00792      if (our_event==NULL) return PAPI_ENOEVNT;
00793 
00794      event_num=find_existing_event(name);
00795   }
00796 
00797   if (event_num>=0) {      
00798      *event_code=event_num;
00799      SUBDBG("Found code: %x\n",*event_code);
00800      return PAPI_OK;
00801   }
00802 
00803   /* Failure here means allocate_native_event failed */
00804 
00805   SUBDBG("Event %s not found\n",name);
00806 
00807   return PAPI_ENOEVNT;   
00808 
00809 }
00810 
00811 
00827 int
00828 _papi_libpfm4_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len)
00829 {
00830 
00831         struct native_event_t *our_event;
00832 
00833         SUBDBG("ENTER %x\n",EventCode);
00834 
00835         our_event=find_existing_event_by_number(EventCode);
00836     if (our_event==NULL) {
00837       return PAPI_ENOEVNT;
00838     }
00839 
00840     strncpy(ntv_name,our_event->allocated_name,len);
00841 
00842     if (strlen(our_event->allocated_name) > (unsigned)len) {
00843        return PAPI_EBUF;
00844     }
00845 
00846     return PAPI_OK;
00847 }
00848 
00849 
00870 int
00871 _papi_libpfm4_ntv_code_to_descr( unsigned int EventCode, 
00872                 char *ntv_descr, int len )
00873 {
00874   int ret,a,first_mask=1;
00875   char *eventd, *tmp=NULL;
00876   pfm_event_info_t gete;
00877 
00878   pfm_event_attr_info_t ainfo;
00879   char *b;
00880   char event_string[BUFSIZ],*ptr;
00881   char temp_string[BUFSIZ];
00882 
00883   struct native_event_t *our_event;
00884 
00885   SUBDBG("ENTER %x\n",EventCode);
00886 
00887   our_event=find_existing_event_by_number(EventCode);
00888   if (our_event==NULL) {
00889      return PAPI_ENOEVNT;
00890   }
00891 
00892   SUBDBG("Getting info on %x\n",our_event->libpfm4_idx);
00893     
00894   /* libpfm requires the structure be zeroed */
00895   memset( &gete, 0, sizeof ( gete ) );
00896 
00897   ret=pfm_get_event_info(our_event->libpfm4_idx, PFM_OS_PERF_EVENT, &gete);
00898   if (ret<0) {
00899      SUBDBG("Return=%d\n",ret);
00900      return _papi_libpfm4_error(ret);
00901   }
00902 
00903   eventd=strdup(gete.desc);
00904 
00905   tmp = ( char * ) malloc( strlen( eventd ) + 1 );
00906   if ( tmp == NULL ) {
00907      free( eventd );
00908      return PAPI_ENOMEM;
00909   }
00910     
00911   tmp[0] = '\0';
00912   strcat( tmp, eventd );
00913   free( eventd );
00914     
00915   /* Handle Umasks */
00916 
00917   /* attributes concactinated onto end of descr separated by ", masks" */
00918   /* then comma separated */
00919 
00920   strcpy(event_string,our_event->allocated_name);
00921 
00922   /* Point to first umask */
00923 
00924   /* Skip the pmu name :: if one exists */
00925   if (strstr(event_string,"::")) {
00926      ptr=strstr(event_string,"::");
00927      ptr+=2;
00928      b=strtok(ptr,":");
00929   }
00930   else {
00931      b=strtok(event_string,":");
00932   }
00933   
00934   /* if no umask, then done */
00935   if (!b) {
00936      SUBDBG("No colon!\n"); /* no umask */
00937      goto descr_in_tmp;
00938   }
00939 
00940   /* skip first */
00941   b=strtok(NULL,":");
00942   if (!b) {
00943      SUBDBG("Skipping first failed\n");
00944      goto descr_in_tmp;
00945   }
00946 
00947   /* loop through all umasks, seeing which match */
00948   while(b) {
00949     a=0;
00950     while(1) {
00951 
00952       SUBDBG("get_event_attr %x %p\n",our_event->libpfm4_idx,&ainfo);
00953 
00954       memset(&ainfo,0,sizeof(pfm_event_attr_info_t));
00955 
00956       ret = pfm_get_event_attr_info(our_event->libpfm4_idx, a, 
00957                     PFM_OS_PERF_EVENT, &ainfo);
00958       if (ret != PFM_SUCCESS) {
00959     SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret));
00960     return _papi_libpfm4_error(ret);
00961       }
00962 
00963       /* Plain UMASK case */
00964       if (ainfo.type == PFM_ATTR_UMASK) {
00965    
00966          SUBDBG("Trying %s with %s\n",ainfo.name,b);
00967 
00968          if (!strcasecmp(ainfo.name, b)) {
00969         int new_length;
00970 
00971         SUBDBG("Found %s\n",b);
00972         new_length=strlen(ainfo.desc);
00973 
00974         if (first_mask) {
00975            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
00976            strcat(tmp,", masks:");
00977            first_mask=0;
00978         }
00979         else {
00980            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
00981            strcat(tmp,",");
00982         }
00983         strcat(tmp,ainfo.desc);
00984 
00985         goto found_attr;
00986      }
00987       }
00988 
00989       /* Boolean Case */
00990       if (ainfo.type == PFM_ATTR_MOD_BOOL) {
00991     
00992      sprintf(temp_string,"%s=0",ainfo.name);
00993 
00994          SUBDBG("Trying %s with %s\n",temp_string,b);
00995 
00996          if (!strcasecmp(temp_string, b)) {
00997         int new_length;
00998 
00999         SUBDBG("Found %s\n",b);
01000         new_length=strlen(ainfo.desc);
01001 
01002         if (first_mask) {
01003            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
01004            strcat(tmp,", masks:");
01005            first_mask=0;
01006         }
01007         else {
01008            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
01009            strcat(tmp,",");
01010         }
01011         strcat(tmp,ainfo.desc);
01012 
01013         goto found_attr;
01014      }
01015       }
01016 
01017       /* Integer Case */
01018       if (ainfo.type == PFM_ATTR_MOD_INTEGER) {
01019 
01020      sprintf(temp_string,"%s=0",ainfo.name);
01021 
01022          SUBDBG("Trying %s with %s\n",temp_string,b);
01023 
01024          if (!strcasecmp(temp_string, b)) {
01025         int new_length;
01026 
01027         SUBDBG("Found %s\n",b);
01028         new_length=strlen(ainfo.desc);
01029 
01030         if (first_mask) {
01031            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:"));
01032            strcat(tmp,", masks:");
01033            first_mask=0;
01034         }
01035         else {
01036            tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(","));
01037            strcat(tmp,",");
01038         }
01039         strcat(tmp,ainfo.desc);
01040 
01041         goto found_attr;
01042      }
01043       }
01044 
01045       a++;
01046     }
01047 
01048     SUBDBG("attr=%s not found for event %s\n", b, ainfo.name);
01049 
01050     return PAPI_EATTR;
01051 
01052 found_attr:
01053 
01054     b=strtok(NULL,":");
01055   }
01056 
01057   /* We are done and the description to copy is in tmp */
01058 descr_in_tmp:
01059     strncpy( ntv_descr, tmp, ( size_t ) len );
01060     if ( ( int ) strlen( tmp ) > len - 1 )
01061         ret = PAPI_EBUF;
01062     else
01063         ret = PAPI_OK;
01064     free( tmp );
01065 
01066     SUBDBG("PFM4 Code: %x %s\n",EventCode,ntv_descr);
01067 
01068     return ret;
01069 }
01070 
01071 
01072 int
01073 _papi_libpfm4_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
01074 {
01075 
01076 
01077   struct native_event_t *our_event;
01078 
01079   SUBDBG("ENTER %x\n",EventCode);
01080 
01081   our_event=find_existing_event_by_number(EventCode);
01082   if (our_event==NULL) {
01083      return PAPI_ENOEVNT;
01084   }
01085 
01086   strncpy(info->symbol, our_event->allocated_name, sizeof(info->symbol));
01087 
01088   if (strlen(our_event->allocated_name) > sizeof(info->symbol)) {
01089      return PAPI_EBUF;
01090   }
01091 
01092   _papi_libpfm4_ntv_code_to_descr(EventCode,info->long_descr,
01093                  sizeof(info->long_descr));
01094 
01095   return PAPI_OK;
01096 }
01097 
01098 
01099 
01114 int
01115 _papi_libpfm4_ntv_enum_events( unsigned int *PapiEventCode, int modifier )
01116 {
01117     int code,ret;
01118     struct native_event_t *current_event;
01119 
01120         SUBDBG("ENTER\n");
01121 
01122     /* return first event if so specified */
01123     if ( modifier == PAPI_ENUM_FIRST ) {
01124 
01125        unsigned int papi_event=0;
01126 
01127            SUBDBG("ENUM_FIRST\n");
01128 
01129        code=get_event_first_active();
01130        SUBDBG("ENUM_FIRST code: %d\n",code);
01131        if (code < 0 ) {
01132           return code;
01133        }
01134 
01135        /* convert the libpfm4 event to a PAPI event */
01136        ret=convert_pfmidx_to_native(code, &papi_event);
01137 
01138        *PapiEventCode=(unsigned int)papi_event;
01139 
01140            SUBDBG("FOUND %x (from %x) ret=%d\n",*PapiEventCode,code,ret);
01141 
01142        return ret;
01143     }
01144 
01145     /* If we get this far, we're looking for a        */
01146     /* next-event.  So gather info on the current one */
01147     current_event=find_existing_event_by_number(*PapiEventCode);
01148     if (current_event==NULL) {
01149            SUBDBG("EVENTS %x not found\n",*PapiEventCode);
01150        return PAPI_ENOEVNT;
01151     }
01152 
01153 
01154     /* Handle looking for the next event */
01155 
01156     if ( modifier == PAPI_ENUM_EVENTS ) {
01157 
01158        unsigned int papi_event=0;
01159 
01160        SUBDBG("PAPI_ENUM_EVENTS %x\n",*PapiEventCode);
01161 
01162        code=current_event->libpfm4_idx;
01163 
01164        ret=find_next_no_aliases(code);
01165        SUBDBG("find_next_no_aliases() Returned %x\n",ret);
01166        if (ret<0) {
01167           return ret;
01168        }
01169 
01170        /* Convert libpfm4 event code to PAPI event code */
01171        ret=convert_pfmidx_to_native(ret, &papi_event);
01172        if (ret<0) {
01173            SUBDBG("Couldn't convert to native %d %s\n",
01174               ret,PAPI_strerror(ret));
01175            return ret;
01176        }
01177 
01178        *PapiEventCode=(unsigned int)papi_event;
01179 
01180            SUBDBG("Returning PAPI_OK\n");
01181 
01182        return ret;
01183     }
01184 
01185     /* We don't handle PAPI_NTV_ENUM_UMASK_COMBOS */
01186     if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) {
01187        return PAPI_ENOIMPL;
01188     } 
01189 
01190     /* Enumerate PAPI_NTV_ENUM_UMASKS (umasks on an event) */
01191     if ( modifier == PAPI_NTV_ENUM_UMASKS ) {
01192 
01193        int max_umask,next_umask;
01194        char umask_string[BUFSIZ],new_name[BUFSIZ];
01195 
01196        SUBDBG("Finding maximum mask in event %s\n",
01197                   current_event->allocated_name);
01198 
01199        max_umask=find_max_umask(current_event);
01200        SUBDBG("Found max %d\n",max_umask);
01201 
01202        if (max_umask<0) {
01203           if (max_umask==PFM_ERR_UMASK) {
01204              max_umask=-1; /* needed for find_next_umask() to work */
01205                        /* indicates the event as passed had no */
01206                        /* umask in it.                         */
01207           }
01208           else {
01209              return _papi_libpfm4_error(max_umask);
01210           }
01211        }
01212 
01213        next_umask=find_next_umask(current_event,max_umask,
01214                       umask_string);
01215 
01216        SUBDBG("Found next %d\n",next_umask);
01217 
01218        if (next_umask>=0) {
01219 
01220           unsigned int papi_event;
01221 
01222           sprintf(new_name,"%s:%s",current_event->base_name,
01223              umask_string);
01224      
01225           SUBDBG("Found new name %s\n",new_name);
01226 
01227               ret=_papi_libpfm4_ntv_name_to_code(new_name,&papi_event);
01228           if (ret!=PAPI_OK) {
01229          return PAPI_ENOEVNT;
01230           }
01231 
01232           *PapiEventCode=(unsigned int)papi_event;
01233           SUBDBG("found code %x\n",*PapiEventCode);
01234 
01235           return PAPI_OK;
01236        }
01237 
01238        SUBDBG("couldn't find umask\n");
01239 
01240        return _papi_libpfm4_error(next_umask);
01241 
01242     }
01243     
01244     /* An unknown enumeration method was indicated */
01245 
01246     return PAPI_ENOIMPL;
01247 }
01248 
01256 int 
01257 _papi_libpfm4_shutdown(void) {
01258 
01259   int i;
01260 
01261   SUBDBG("shutdown\n");
01262 
01263   /* clean out and free the native events structure */
01264   _papi_hwi_lock( NAMELIB_LOCK );
01265 
01266   /* free memory allocate with strdup */
01267   for( i=0; i<num_native_events; i++) {
01268      free(native_events[i].base_name);
01269      free(native_events[i].pmu_plus_name);
01270      free(native_events[i].pmu);
01271      free(native_events[i].allocated_name);
01272   }
01273 
01274   memset(native_events,0,
01275      sizeof(struct native_event_t)*allocated_native_events);
01276   num_native_events=0;
01277   allocated_native_events=0;
01278   free(native_events);
01279   _papi_hwi_unlock( NAMELIB_LOCK );
01280 
01281   return PAPI_OK;
01282 }
01283 
01284 
01293 int
01294 _papi_libpfm4_init(papi_vector_t *my_vector, int cidx) {
01295 
01296    int detected_pmus=0, found_default=0;
01297    int i, version;
01298    pfm_err_t retval;
01299    unsigned int ncnt;
01300    pfm_pmu_info_t pinfo;
01301 
01302    /* The following checks the version of the PFM library
01303       against the version PAPI linked to... */
01304    if ( ( retval = pfm_initialize(  ) ) != PFM_SUCCESS ) {
01305       PAPIERROR( "pfm_initialize(): %s", pfm_strerror( retval ) );
01306       return PAPI_ESYS;
01307    }
01308 
01309    /* get the libpfm4 version */
01310    SUBDBG( "pfm_get_version()\n");
01311    if ( (version=pfm_get_version( )) < 0 ) {
01312       PAPIERROR( "pfm_get_version(): %s", pfm_strerror( retval ) );
01313       return PAPI_ESYS;
01314    }
01315 
01316    /* Set the version */
01317    sprintf( my_vector->cmp_info.support_version, "%d.%d",
01318         PFM_MAJ_VERSION( version ), PFM_MIN_VERSION( version ) );
01319 
01320    /* Complain if the compiled-against version doesn't match current version */
01321    if ( PFM_MAJ_VERSION( version ) != PFM_MAJ_VERSION( LIBPFM_VERSION ) ) {
01322       PAPIERROR( "Version mismatch of libpfm: compiled %x vs. installed %x\n",
01323                    PFM_MAJ_VERSION( LIBPFM_VERSION ),
01324                    PFM_MAJ_VERSION( version ) );
01325       return PAPI_ESYS;
01326    }
01327 
01328    /* allocate the native event structure */
01329 
01330    num_native_events=0;
01331 
01332    native_events=calloc(NATIVE_EVENT_CHUNK,sizeof(struct native_event_t));
01333    if (native_events==NULL) {
01334       return PAPI_ENOMEM;
01335    }
01336    allocated_native_events=NATIVE_EVENT_CHUNK;
01337 
01338    /* Count number of present PMUs */
01339    detected_pmus=0;
01340    ncnt=0;
01341 
01342    /* need to init pinfo or pfmlib might complain */
01343    memset(&default_pmu, 0, sizeof(pfm_pmu_info_t));
01344    /* init default pmu */
01345    retval=pfm_get_pmu_info(0, &default_pmu);
01346    
01347    SUBDBG("Detected pmus:\n");
01348    for(i=0;i<PFM_PMU_MAX;i++) {
01349       memset(&pinfo,0,sizeof(pfm_pmu_info_t));
01350       retval=pfm_get_pmu_info(i, &pinfo);
01351       if (retval!=PFM_SUCCESS) {
01352      continue;
01353       }
01354       if (pinfo.is_present) {
01355      SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type);
01356 
01357          detected_pmus++;
01358      ncnt+=pinfo.nevents;
01359 
01360      /* Choose default PMU */
01361      if ( (pinfo.type==PFM_PMU_TYPE_CORE) &&
01362               strcmp(pinfo.name,"ix86arch")) {
01363 
01364         SUBDBG("\t  %s is default\n",pinfo.name);
01365         memcpy(&default_pmu,&pinfo,sizeof(pfm_pmu_info_t));
01366         found_default++;
01367      }
01368       }
01369    }
01370    SUBDBG("%d native events detected on %d pmus\n",ncnt,detected_pmus);
01371 
01372    if (!found_default) {
01373       PAPIERROR("Could not find default PMU\n");
01374       return PAPI_ECMP;
01375    }
01376 
01377    if (found_default>1) {
01378      PAPIERROR("Found too many default PMUs!\n");
01379      return PAPI_ECMP;
01380    }
01381 
01382    my_vector->cmp_info.num_native_events = ncnt;
01383 
01384    my_vector->cmp_info.num_cntrs = default_pmu.num_cntrs+
01385                                   default_pmu.num_fixed_cntrs;
01386 
01387    SUBDBG( "num_counters: %d\n", my_vector->cmp_info.num_cntrs );
01388    
01389    /* Setup presets */
01390    retval = _papi_load_preset_table( (char *)default_pmu.name, 
01391                     default_pmu.pmu, cidx );
01392    if ( retval ) {
01393       return retval;
01394    }    
01395 
01396    return PAPI_OK;
01397 }
01398 
01399 
01412 int
01413 _papi_libpfm4_setup_counters( struct perf_event_attr *attr,
01414                  int event ) {
01415 
01416   struct native_event_t *our_event;
01417 
01418   our_event=find_existing_event_by_number(event);
01419   if (our_event==NULL) {
01420      return PAPI_ENOEVNT;
01421   }
01422 
01423   attr->config=our_event->config; 
01424   attr->config1=our_event->config1;
01425   attr->config2=our_event->config2;
01426   attr->type=our_event->type;
01427   
01428   SUBDBG( "pe_event: config 0x%"PRIx64
01429           " config1 0x%"PRIx64
01430           " type 0x%"PRIx32"\n", 
01431           attr->config, 
01432       attr->config1,
01433       attr->type);
01434       
01435 
01436   return PAPI_OK;
01437 }
01438 
01439 
01440 
01441 
01442 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines