peu_libpfm4_events.c File Reference

Include dependency graph for peu_libpfm4_events.c:

Go to the source code of this file.

Defines

#define NATIVE_EVENT_CHUNK   1024

Functions

static int find_existing_event (char *name, struct native_event_table_t *event_table)
static int pmu_is_present_and_right_type (pfm_pmu_info_t *pinfo, int type)
static struct native_event_tallocate_native_event (char *name, int libpfm4_index, struct native_event_table_t *event_table)
static int get_first_event_next_pmu (int pmu_idx, int pmu_type)
int _peu_libpfm4_ntv_name_to_code (char *name, unsigned int *event_code, struct native_event_table_t *event_table)
int _peu_libpfm4_ntv_code_to_name (unsigned int EventCode, char *ntv_name, int len, struct native_event_table_t *event_table)
int _peu_libpfm4_ntv_code_to_descr (unsigned int EventCode, char *ntv_descr, int len, struct native_event_table_t *event_table)
int _peu_libpfm4_ntv_code_to_info (unsigned int EventCode, PAPI_event_info_t *info, struct native_event_table_t *event_table)
int _peu_libpfm4_ntv_enum_events (unsigned int *PapiEventCode, int modifier, struct native_event_table_t *event_table)
int _peu_libpfm4_shutdown (papi_vector_t *my_vector, struct native_event_table_t *event_table)
int _peu_libpfm4_init (papi_vector_t *my_vector, struct native_event_table_t *event_table, int pmu_type)

Variables

static int attr_idx

Define Documentation

#define NATIVE_EVENT_CHUNK   1024

Definition at line 30 of file peu_libpfm4_events.c.


Function Documentation

int _peu_libpfm4_init ( papi_vector_t my_vector,
struct native_event_table_t event_table,
int  pmu_type 
)

Definition at line 1039 of file peu_libpfm4_events.c.

01041                          {
01042 
01043    int detected_pmus=0;
01044    int i;
01045    int j=0;
01046    pfm_err_t retval = PFM_SUCCESS;
01047    unsigned int ncnt;
01048    pfm_pmu_info_t pinfo;
01049 
01050    /* allocate the native event structure */
01051 
01052    event_table->num_native_events=0;
01053    event_table->pmu_type=pmu_type;
01054 
01055    event_table->native_events=calloc(NATIVE_EVENT_CHUNK,
01056                        sizeof(struct native_event_t));
01057    if (event_table->native_events==NULL) {
01058       return PAPI_ENOMEM;
01059    }
01060    event_table->allocated_native_events=NATIVE_EVENT_CHUNK;
01061 
01062    /* Count number of present PMUs */
01063    detected_pmus=0;
01064    ncnt=0;
01065 
01066    my_vector->cmp_info.num_cntrs=0;
01067 
01068    SUBDBG("Detected pmus:\n");
01069    for(i=0;i<PFM_PMU_MAX;i++) {
01070       memset(&pinfo,0,sizeof(pfm_pmu_info_t));
01071       pinfo.size = sizeof(pfm_pmu_info_t);
01072       retval=pfm_get_pmu_info(i, &pinfo);
01073       if (retval!=PFM_SUCCESS) {
01074      continue;
01075       }
01076 
01077       if (pmu_is_present_and_right_type(&pinfo,pmu_type)) {
01078      SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type);
01079 
01080          detected_pmus++;
01081      ncnt+=pinfo.nevents;
01082 
01083      if ((j < PAPI_PMU_MAX) && (pinfo.name != NULL)) {
01084          my_vector->cmp_info.pmu_names[j++] = strdup(pinfo.name);
01085      }
01086          my_vector->cmp_info.num_cntrs += pinfo.num_cntrs+
01087                                    pinfo.num_fixed_cntrs;
01088       }
01089    }
01090    SUBDBG("%d native events detected on %d pmus\n",ncnt,detected_pmus);
01091 
01092    my_vector->cmp_info.num_native_events = ncnt;
01093 
01094    SUBDBG( "num_counters: %d\n", my_vector->cmp_info.num_cntrs );
01095 
01096    return PAPI_OK;
01097 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_ntv_code_to_descr ( unsigned int  EventCode,
char *  ntv_descr,
int  len,
struct native_event_table_t event_table 
)

Definition at line 619 of file peu_libpfm4_events.c.

00622 {
00623     SUBDBG("ENTER: EventCode: %#x, ntv_descr: %p, len: %d: event_table: %p\n", EventCode, ntv_descr, len, event_table);
00624 
00625     int eidx;
00626     int papi_event_code;
00627 
00628     // get the attribute index for this papi event
00629     papi_event_code = _papi_hwi_get_papi_event_code();
00630 
00631     // a papi event code less than 0 is invalid, return error
00632     if (papi_event_code <= 0) {
00633         SUBDBG("EXIT: PAPI_ENOEVNT\n");
00634         return PAPI_ENOEVNT;
00635     }
00636 
00637     // find our native event table for this papi event code (search list backwards because it improves chances of finding it quickly)
00638     for (eidx=event_table->num_native_events-1 ; eidx>=0 ; eidx--) {
00639         SUBDBG("native_event[%d]: papi_event_code: %#x, libpfm4_idx: %#x\n", eidx, event_table->native_events[eidx].papi_event_code, event_table->native_events[eidx].libpfm4_idx);
00640         if ((papi_event_code == event_table->native_events[eidx].papi_event_code) && (EventCode == ((unsigned)event_table->native_events[eidx].libpfm4_idx))) {
00641             break;
00642         }
00643     }
00644 
00645     // if we did not find a match, return an error
00646     if (eidx < 0) {
00647         // If we did not find a match in our native event table, then the code passed in has not been
00648         // allocated yet  It should not be possible to get to this code.  The user has to call the papi
00649         // code_to_name api with a papi event code for a native event.  But the only way to get one of
00650         // those is to call either name_to_code or enum_cmp_events first.  When one of these calls is
00651         // done we allocate the event so it should always be there.
00652 
00653         SUBDBG("EXIT: PAPI_ENOEVNT\n");
00654         return PAPI_ENOEVNT;
00655     }
00656 
00657     char *edesc = event_table->native_events[eidx].event_description;
00658 
00659     // if it will not fit, return error
00660     if (strlen (edesc) >= (unsigned)len) {
00661         SUBDBG("EXIT: event name %s will not fit in buffer provided\n", edesc);
00662         return PAPI_EBUF;
00663     }
00664     strcpy (ntv_descr, edesc);
00665 
00666     // if this event had masks, also add their descriptions
00667     char *mdesc = event_table->native_events[eidx].mask_description;
00668     if ((mdesc != NULL)  &&  (strlen(mdesc) > 0)) {
00669         if ((strlen(edesc) + 8 + strlen(mdesc)) >= (unsigned)len) {
00670             SUBDBG("EXIT: Not enough room for event and mask descriptions: need: %u, have: %u", (unsigned)(strlen(edesc) + 8 + strlen(mdesc)), (unsigned)len);
00671             return PAPI_EBUF;
00672         }
00673         strcat (ntv_descr, ", masks:");
00674         strcat (ntv_descr, mdesc);
00675     }
00676 
00677     SUBDBG("EXIT: event description: %s\n", ntv_descr);
00678     return PAPI_OK;
00679 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_ntv_code_to_info ( unsigned int  EventCode,
PAPI_event_info_t info,
struct native_event_table_t event_table 
)

Definition at line 683 of file peu_libpfm4_events.c.

00686 {
00687     SUBDBG("ENTER: EventCode: %#x, info: %p, event_table: %p\n", EventCode, info, event_table);
00688 
00689     int ret;
00690 
00691     // get the event name first
00692     if ((ret = _peu_libpfm4_ntv_code_to_name(EventCode, info->symbol, sizeof(info->symbol), event_table)) != PAPI_OK) {
00693         SUBDBG("EXIT: _peu_libpfm4_ntv_code_to_name returned: %d\n", ret);
00694         return PAPI_ENOEVNT;
00695     }
00696 
00697     if ((ret = _peu_libpfm4_ntv_code_to_descr(EventCode, info->long_descr, sizeof(info->long_descr), event_table)) != PAPI_OK) {
00698         SUBDBG("EXIT: _peu_libpfm4_ntv_code_to_descr returned: %d\n", ret);
00699         return PAPI_ENOEVNT;
00700     }
00701 
00702     SUBDBG("EXIT: EventCode: %#x, name: %s, desc: %s\n", EventCode, info->symbol, info->long_descr);
00703     return PAPI_OK;
00704 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_ntv_code_to_name ( unsigned int  EventCode,
char *  ntv_name,
int  len,
struct native_event_table_t event_table 
)

Definition at line 532 of file peu_libpfm4_events.c.

00535 {
00536     SUBDBG("ENTER: EventCode: %#x, ntv_name: %p, len: %d, event_table: %p\n", EventCode, ntv_name, len, event_table);
00537 
00538     int eidx;
00539     int papi_event_code;
00540 
00541     // get the attribute index for this papi event
00542     papi_event_code = _papi_hwi_get_papi_event_code();
00543 
00544     // a papi event code less than 0 is invalid, return error
00545     if (papi_event_code <= 0) {
00546         SUBDBG("EXIT: PAPI_ENOEVNT\n");
00547         return PAPI_ENOEVNT;
00548     }
00549 
00550     // find our native event table for this papi event code (search list backwards because it improves chances of finding it quickly)
00551     for (eidx=event_table->num_native_events-1 ; eidx>=0 ; eidx--) {
00552         if ((papi_event_code == event_table->native_events[eidx].papi_event_code) && (EventCode == ((unsigned)event_table->native_events[eidx].libpfm4_idx))) {
00553             SUBDBG("Found native_event[%d]: papi_event_code: %#x, libpfm4_idx: %#x\n", eidx, event_table->native_events[eidx].papi_event_code, event_table->native_events[eidx].libpfm4_idx);
00554             break;
00555         }
00556     }
00557 
00558     // if we did not find a match, return an error
00559     if (eidx < 0) {
00560         // If we did not find a match in our native event table, then the code passed in has not been
00561         // allocated yet  It should not be possible to get to this code.  The user has to call the papi
00562         // code_to_name api with a papi event code for a native event.  But the only way to get one of
00563         // those is to call either name_to_code or enum_cmp_events first.  When one of these calls is
00564         // done we allocate the event so it should always be there.
00565 
00566         SUBDBG("EXIT: PAPI_ENOEVNT\n");
00567         return PAPI_ENOEVNT;
00568     }
00569 
00570     // always use pmu name and event name for uncore events
00571     char *ename = event_table->native_events[eidx].pmu_plus_name;
00572 
00573     // if it will not fit, return error
00574     if (strlen (ename) >= (unsigned)len) {
00575         SUBDBG("EXIT: event name %s will not fit in buffer provided\n", ename);
00576         return PAPI_EBUF;
00577     }
00578     strcpy (ntv_name, ename);
00579 
00580     // if this event had masks, also add their names
00581     char *mname = event_table->native_events[eidx].mask_string;
00582     if ((mname != NULL)  &&  (strlen(mname) > 0)) {
00583         if ((strlen(ename) + 8 + strlen(mname)) >= (unsigned)len) {
00584             SUBDBG("EXIT: Not enough room for event and mask descriptions: need: %u, have: %u", (unsigned)(strlen(ename) + 8 + strlen(mname)), (unsigned)len);
00585             return PAPI_EBUF;
00586         }
00587         strcat (ntv_name, ":");
00588         strcat (ntv_name, mname);
00589     }
00590 
00591     SUBDBG("EXIT: event name: %s\n", ntv_name);
00592     return PAPI_OK;
00593 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_ntv_enum_events ( unsigned int *  PapiEventCode,
int  modifier,
struct native_event_table_t event_table 
)

Definition at line 724 of file peu_libpfm4_events.c.

00726                                                              {
00727 
00728     SUBDBG("ENTER: PapiEventCode: %p, *PapiEventCode: %#x, modifier: %d, event_table: %p\n", PapiEventCode, *PapiEventCode, modifier, event_table);
00729 
00730     int code,ret, pnum;
00731     int max_umasks;
00732     char event_string[BUFSIZ];
00733     pfm_pmu_info_t pinfo;
00734     pfm_event_info_t einfo;
00735     struct native_event_t *our_event;
00736 
00737     /* return first event if so specified */
00738     if ( modifier == PAPI_ENUM_FIRST ) {
00739         attr_idx = 0;   // set so if they want attribute information, it will start with the first attribute
00740         code=get_first_event_next_pmu(-1, event_table->pmu_type);
00741        if (code < 0 ) {
00742            SUBDBG("EXIT: Invalid component first event code: %d\n", code);
00743           return code;
00744        }
00745 
00746         // get the event information from libpfm4 (must zero structure)
00747         memset( &einfo, 0, sizeof( pfm_event_info_t ));
00748         einfo.size = sizeof(pfm_event_info_t);
00749         if ((ret = pfm_get_event_info(code, PFM_OS_PERF_EVENT_EXT, &einfo)) != PFM_SUCCESS) {
00750             SUBDBG("EXIT: pfm_get_event_info returned: %d\n", ret);
00751             return PAPI_ENOIMPL;
00752         }
00753 
00754         // get the pmu information from libpfm4 (must zero structure)
00755         memset( &pinfo, 0, sizeof(pfm_pmu_info_t) );
00756         pinfo.size = sizeof(pfm_pmu_info_t);
00757         ret=pfm_get_pmu_info(einfo.pmu, &pinfo);
00758         if (ret!=PFM_SUCCESS) {
00759             SUBDBG("EXIT: pfm_get_pmu_info returned: %d\n", ret);
00760             return ret;
00761         }
00762 
00763         // build full event name
00764         sprintf (event_string, "%s::%s", pinfo.name, einfo.name);
00765         SUBDBG("code: %#x, pmu: %s, event: %s, event_string: %s\n", code, pinfo.name, einfo.name, event_string);
00766 
00767         // go allocate this event, need to create tables used by the get event info call that will probably follow
00768         if ((our_event = allocate_native_event(event_string, code, event_table)) == NULL) {
00769             // allocate may have created the event table but returned NULL to tell the caller the event string was invalid (attempt to encode it failed).
00770             // if the caller wants to use this event to count something, it will report an error
00771             // but if the caller is just interested in listing the event, then we need an event table with an event name and libpfm4 index
00772             int evt_idx;
00773             if ((evt_idx = find_existing_event(event_string, event_table)) < 0) {
00774                 SUBDBG("EXIT: Allocating event: '%s' failed\n", event_string);
00775                 return PAPI_ENOEVNT;
00776             }
00777 
00778             // give back the new event code
00779             *PapiEventCode = event_table->native_events[evt_idx].libpfm4_idx;
00780             SUBDBG("EXIT: event code: %#x\n", *PapiEventCode);
00781             return PAPI_OK;
00782         }
00783 
00784         *PapiEventCode = our_event->libpfm4_idx;
00785 
00786         SUBDBG("EXIT: *PapiEventCode: %#x\n", *PapiEventCode);
00787         return PAPI_OK;
00788     }
00789 
00790     /* Handle looking for the next event */
00791     if ( modifier == PAPI_ENUM_EVENTS ) {
00792         attr_idx = 0;   // set so if they want attribute information, it will start with the first attribute
00793 
00794         // get the next event code from libpfm4, if there are no more in this pmu find first event in next pmu
00795         if ((code = pfm_get_event_next(*PapiEventCode)) < 0) {
00796 
00797             // get this events information from libpfm4, we need the pmu number of the last event we processed (table must be cleared)
00798             memset( &einfo, 0, sizeof( pfm_event_info_t ));
00799             einfo.size = sizeof(pfm_event_info_t);
00800             if ((ret = pfm_get_event_info(*PapiEventCode, PFM_OS_PERF_EVENT_EXT, &einfo)) != PFM_SUCCESS) {
00801                 SUBDBG("EXIT: pfm_get_event_info returned: %d\n", ret);
00802                 return PAPI_ENOIMPL;
00803             }
00804             SUBDBG("*PapiEventCode: %#x, event: %s\n", *PapiEventCode, einfo.name);
00805 
00806             // get the pmu number of the last event
00807             pnum = einfo.pmu;
00808 
00809             while ( pnum<PFM_PMU_MAX) {
00810                 SUBDBG("pnum: %d\n", pnum);
00811                 code=get_first_event_next_pmu(pnum, event_table->pmu_type);
00812                 if (code < 0) {
00813                     SUBDBG("EXIT: No more pmu's to list, returning: %d\n", code);
00814                     return code;
00815                 }
00816                 break;
00817             }
00818         }
00819 
00820 
00821         // get the event information from libpfm4 (must zero structure)
00822         memset( &einfo, 0, sizeof( pfm_event_info_t ));
00823         einfo.size = sizeof(pfm_event_info_t);
00824         if ((ret = pfm_get_event_info(code, PFM_OS_PERF_EVENT_EXT, &einfo)) != PFM_SUCCESS) {
00825             SUBDBG("EXIT: pfm_get_event_info returned: %d\n", ret);
00826             return PAPI_ENOIMPL;
00827         }
00828 
00829         // get the pmu information from libpfm4 (must zero structure)
00830         memset( &pinfo, 0, sizeof(pfm_pmu_info_t) );
00831         pinfo.size = sizeof(pfm_pmu_info_t);
00832         ret=pfm_get_pmu_info(einfo.pmu, &pinfo);
00833         if (ret!=PFM_SUCCESS) {
00834             SUBDBG("EXIT: pfm_get_pmu_info returned: %d\n", ret);
00835             return ret;
00836         }
00837 
00838         // build full event name
00839         sprintf (event_string, "%s::%s", pinfo.name, einfo.name);
00840         SUBDBG("code: %#x, pmu: %s, event: %s, event_string: %s\n", code, pinfo.name, einfo.name, event_string);
00841 
00842         // go allocate this event, need to create tables used by the get event info call that will follow
00843         if ((our_event = allocate_native_event(event_string, code, event_table)) == NULL) {
00844             // allocate may have created the event table but returned NULL to tell the caller the event string was invalid (attempt to encode it failed).
00845             // if the caller wants to use this event to count something, it will report an error
00846             // but if the caller is just interested in listing the event, then we need an event table with an event name and libpfm4 index
00847             int evt_idx;
00848             if ((evt_idx = find_existing_event(event_string, event_table)) < 0) {
00849                 SUBDBG("EXIT: Allocating event: '%s' failed\n", event_string);
00850                 return PAPI_ENOEVNT;
00851             }
00852 
00853             // give back the new event code
00854             *PapiEventCode = event_table->native_events[evt_idx].libpfm4_idx;
00855             SUBDBG("EXIT: event code: %#x\n", *PapiEventCode);
00856             return PAPI_OK;
00857         }
00858 
00859         // give back the new event code
00860         *PapiEventCode = our_event->libpfm4_idx;
00861 
00862         SUBDBG("EXIT: *PapiEventCode: %#x\n", *PapiEventCode);
00863         return PAPI_OK;
00864     }
00865 
00866     /* We don't handle PAPI_NTV_ENUM_UMASK_COMBOS */
00867     if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) {
00868         SUBDBG("EXIT: do not support umask combos yet\n");
00869         return PAPI_ENOIMPL;
00870     } 
00871 
00872     /* Enumerate PAPI_NTV_ENUM_UMASKS (umasks on an event) */
00873     if ( modifier == PAPI_NTV_ENUM_UMASKS ) {
00874         // get this events information from libpfm4, we need the number of masks this event knows about (table must be cleared)
00875         memset( &einfo, 0, sizeof( pfm_event_info_t ));
00876         einfo.size = sizeof(pfm_event_info_t);
00877         if ((ret = pfm_get_event_info(*PapiEventCode, PFM_OS_PERF_EVENT_EXT, &einfo)) != PFM_SUCCESS) {
00878             SUBDBG("EXIT: pfm_get_event_info returned: %d\n", ret);
00879             return PAPI_ENOIMPL;
00880         }
00881 //      SUBDBG("*PapiEventCode: %#x, einfo.name: %s, einfo.code: %#x, einfo.nattrs: %d\n", *PapiEventCode, einfo.name, einfo.code, einfo.nattrs);
00882 
00883         // set max number of masks
00884         max_umasks = einfo.nattrs;
00885 
00886         // if we reached last attribute, return error to show we are done with this events masks
00887         if (attr_idx == max_umasks) {
00888             SUBDBG("EXIT: already processed all umasks: attr_idx: %d\n", attr_idx);
00889             return PAPI_ENOEVNT;
00890         }
00891 
00892         // find the event table for this event, we need the pmu name and event name without any masks
00893         int ntv_idx = _papi_hwi_get_ntv_idx(_papi_hwi_get_papi_event_code());
00894         if (ntv_idx < 0) {
00895             SUBDBG("EXIT: _papi_hwi_get_ntv_idx returned: %d\n", ntv_idx);
00896             return ntv_idx;
00897         }
00898         char *ename = event_table->native_events[ntv_idx].pmu_plus_name;
00899         if ((ename == NULL)  ||  (strlen(ename) >= sizeof(event_string))) {
00900             SUBDBG("EXIT: Event name will not fit into buffer\n");
00901             return PAPI_EBUF;
00902         }
00903         strcpy (event_string, ename);
00904         SUBDBG("event_string: %s\n", event_string);
00905 
00906         // go get the attribute information for this event
00907         // libpfm4 likes the table cleared
00908         pfm_event_attr_info_t ainfo;
00909         memset (&ainfo, 0, sizeof(pfm_event_attr_info_t));
00910         ainfo.size = sizeof(pfm_event_attr_info_t);
00911         ret = pfm_get_event_attr_info(*PapiEventCode, attr_idx, PFM_OS_PERF_EVENT_EXT, &ainfo);
00912         if (ret != PFM_SUCCESS) {
00913             SUBDBG("EXIT: Attribute info not found, EventCode: %#x, attr_idx: %d, ret: %d\n", *PapiEventCode, attr_idx, _papi_libpfm4_error(ret));
00914             return _papi_libpfm4_error(ret);
00915         }
00916         SUBDBG("*PapiEventCode: %#x, attr_idx: %d, type: %d, name: %s, description: %s\n", *PapiEventCode, attr_idx, ainfo.type, ainfo.name, ainfo.desc);
00917 
00918         if (strlen(event_string) + strlen(ainfo.name) + 35 > sizeof(event_string)) {
00919             SUBDBG("EXIT: Event name and mask will not fit into buffer\n");
00920             return PAPI_EBUF;
00921         }
00922 
00923         strcat (event_string, ":");
00924         strcat (event_string, ainfo.name);
00925         switch (ainfo.type) {
00926             case PFM_ATTR_UMASK:
00927                 break;
00928             case PFM_ATTR_MOD_BOOL:
00929             case PFM_ATTR_MOD_INTEGER:
00930                 // a few attributes require a non-zero value to encode correctly (most would accept zero here)
00931                 strcat(event_string,"=0");
00932                 break;
00933             default:
00934                 SUBDBG("EXIT: Unsupported attribute type: %d", ainfo.type);
00935                 return PAPI_EATTR;
00936         }
00937 
00938         // go allocate this event, need to create tables used by the get event info call that will follow
00939         if ((our_event = allocate_native_event(event_string, *PapiEventCode, event_table)) == NULL) {
00940             // allocate may have created the event table but returned NULL to tell the caller the event string was invalid.
00941             // if the caller wants to use this event to count something, it must report the error
00942             // but if the caller is just interested in listing the event (like this code), then find the table that was created and return its libpfm4 index
00943             int evt_idx;
00944             if ((evt_idx = find_existing_event(event_string, event_table)) < 0) {
00945                 SUBDBG("EXIT: Allocating event: '%s' failed\n", event_string);
00946                 return PAPI_ENOEVNT;
00947             }
00948             // bump so next time we will use next attribute
00949             attr_idx++;
00950             // give back the new event code
00951             *PapiEventCode = event_table->native_events[evt_idx].libpfm4_idx;
00952             SUBDBG("EXIT: event code: %#x\n", *PapiEventCode);
00953             return PAPI_OK;
00954         }
00955 
00956         // bump so next time we will use next attribute
00957         attr_idx++;
00958 
00959         // give back the new event code
00960         *PapiEventCode = our_event->libpfm4_idx;
00961 
00962         SUBDBG("EXIT: event code: %#x\n", *PapiEventCode);
00963         return PAPI_OK;
00964     }
00965 
00966     /* Enumerate PAPI_NTV_ENUM_GROUPS (groups on an event) */
00967     if ( modifier == PAPI_NTV_ENUM_GROUPS ) {
00968         SUBDBG("EXIT: do not support enumerating groups in this component\n");
00969         return PAPI_ENOIMPL;
00970     }
00971 
00972     /* An unknown enumeration method was indicated */
00973 
00974     SUBDBG("EXIT: Invalid modifier argument provided\n");
00975     return PAPI_ENOIMPL;
00976 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_ntv_name_to_code ( char *  name,
unsigned int *  event_code,
struct native_event_table_t event_table 
)

Definition at line 483 of file peu_libpfm4_events.c.

00485 {
00486   SUBDBG( "ENTER: name: %s, event_code: %p, *event_code: %#x, event_table: %p\n", name, event_code, *event_code, event_table);
00487 
00488   struct native_event_t *our_event;
00489   int event_num;
00490 
00491   // if we already know this event name, just return its native code
00492   event_num=find_existing_event(name, event_table);
00493   if (event_num >= 0) {
00494          *event_code=event_table->native_events[event_num].libpfm4_idx;
00495          // the following call needs to happen to prevent the internal layer from creating a new papi native event table
00496          _papi_hwi_set_papi_event_code(event_table->native_events[event_num].papi_event_code, 1);
00497          SUBDBG("EXIT: Found papi_event_code: %#x, libpfm4_idx: %#x\n", event_table->native_events[event_num].papi_event_code, event_table->native_events[event_num].libpfm4_idx);
00498          return PAPI_OK;
00499   }
00500 
00501      // Try to allocate this event to see if it is known by libpfm4, if allocate fails tell the caller it is not valid
00502      our_event=allocate_native_event(name, -1, event_table);
00503      if (our_event==NULL) {
00504          SUBDBG("EXIT: Allocating event: '%s' failed\n", name);
00505          return PAPI_ENOEVNT;
00506      }
00507 
00508      *event_code = our_event->libpfm4_idx;
00509      SUBDBG("EXIT: Found code: %#x\n",*event_code);
00510      return PAPI_OK;
00511 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _peu_libpfm4_shutdown ( papi_vector_t my_vector,
struct native_event_table_t event_table 
)

Definition at line 990 of file peu_libpfm4_events.c.

00991                                                   {
00992   SUBDBG("ENTER: event_table: %p\n", event_table);
00993 
00994   int i;
00995 
00996   for (i=0 ; i<PAPI_PMU_MAX ; i++) {
00997       if (my_vector->cmp_info.pmu_names[i] != NULL) {
00998           free (my_vector->cmp_info.pmu_names[i]);
00999       }
01000   }
01001 
01002   /* clean out and free the native events structure */
01003   _papi_hwi_lock( NAMELIB_LOCK );
01004 
01005   /* free memory allocated with strdup or malloc */
01006   for( i=0; i<event_table->num_native_events; i++) {
01007      free(event_table->native_events[i].base_name);
01008      free(event_table->native_events[i].pmu_plus_name);
01009      free(event_table->native_events[i].pmu);
01010      free(event_table->native_events[i].allocated_name);
01011      free(event_table->native_events[i].mask_string);
01012      free(event_table->native_events[i].event_description);
01013      if (event_table->native_events[i].mask_description != NULL) {
01014           free(event_table->native_events[i].mask_description);
01015      }
01016   }
01017 
01018   free(event_table->native_events);
01019 
01020   _papi_hwi_unlock( NAMELIB_LOCK );
01021 
01022   SUBDBG("EXIT: PAPI_OK\n");
01023   return PAPI_OK;
01024 }

Here is the call graph for this function:

Here is the caller graph for this function:

static struct native_event_t* allocate_native_event ( char *  name,
int  libpfm4_index,
struct native_event_table_t event_table 
) [static, read]

Definition at line 117 of file peu_libpfm4_events.c.

00118                                                         {
00119 
00120   SUBDBG("ENTER: name: %s, libpfm4_index: %#x, event_table: %p, event_table->pmu_type: %d\n", name, libpfm4_index, event_table, event_table->pmu_type);
00121 
00122   int nevt_idx;
00123   int event_num;
00124   int encode_failed=0;
00125 
00126   pfm_err_t ret;
00127   char *event_string=NULL;
00128   char *pmu_name;
00129   char *event;
00130   char *masks;
00131   char fullname[BUFSIZ];
00132   struct native_event_t *ntv_evt;
00133 
00134   pfm_perf_encode_arg_t perf_arg;
00135   pfm_event_info_t einfo;
00136   pfm_event_attr_info_t ainfo;
00137   pfm_pmu_info_t pinfo;
00138 
00139   // if no place to put native events, report that allocate failed
00140   if (event_table->native_events==NULL) {
00141      SUBDBG("EXIT: no place to put native events\n");
00142      return NULL;
00143   }
00144 
00145   // find out if this event is already known
00146   event_num=find_existing_event(name, event_table);
00147 
00148   /* add the event to our event table */
00149   _papi_hwi_lock( NAMELIB_LOCK );
00150 
00151   // if we already know this event name, it was created as part of setting up the preset tables
00152   // we need to use the event table which is already created
00153   if (event_num >= 0) {
00154      nevt_idx = event_num;
00155      ntv_evt = &(event_table->native_events[event_num]);
00156   } else {
00157       // set to use a new event table (count of used events not bumped until we are sure setting it up does not get an errro)
00158      nevt_idx = event_table->num_native_events;
00159      ntv_evt = &(event_table->native_events[nevt_idx]);
00160   }
00161 
00162   SUBDBG("event_num: %d, nevt_idx: %d, ntv_evt: %p\n", event_num, nevt_idx, ntv_evt);
00163 
00164   /* clear the argument and attribute structures */
00165   memset(&perf_arg,0,sizeof(pfm_perf_encode_arg_t));
00166   memset(&(ntv_evt->attr),0,sizeof(struct perf_event_attr));
00167 
00168   // set argument structure fields so the encode function can give us what we need
00169   perf_arg.attr=&ntv_evt->attr;
00170   perf_arg.fstr=&event_string;
00171 
00172   /* use user provided name of the event to get the perf_event encoding and a fully qualified event string */
00173   ret = pfm_get_os_event_encoding(name, 
00174                   PFM_PLM0 | PFM_PLM3, 
00175                   PFM_OS_PERF_EVENT_EXT,
00176                   &perf_arg);
00177 
00178   // If the encode function failed, skip processing of the event_string
00179   if ((ret != PFM_SUCCESS) || (event_string == NULL)) {
00180       SUBDBG("encode failed for event: %s, returned: %d\n", name, ret);
00181 
00182       // we need to remember that this event encoding failed but still create the native event table
00183       // the event table is used by the list so we put what we can get into it
00184       // but the failure doing the encode causes us to return null to our caller
00185       encode_failed = 1;
00186 
00187       // Noting the encode_failed error in the attr.config allows
00188       // any later validate attempts to return an error value
00189       ntv_evt->attr.config = 0xFFFFFF;
00190 
00191       // we also want to make it look like a cpu number was not provided as an event mask
00192       perf_arg.cpu = -1;
00193   }
00194 
00195   // get a copy of the event name and break it up into its parts
00196   event_string = strdup(name);
00197 
00198   SUBDBG("event_string: %s\n", event_string);
00199 
00200   // get the pmu name, event name and mask list pointers from the event string
00201   event = strstr (event_string, "::");
00202   if (event != NULL) {
00203     *event = 0;     // null terminate pmu name
00204     event += 2;     // event name follows '::'
00205     pmu_name = strdup(event_string);
00206   } else {
00207     // no pmu name in event string
00208     pmu_name = malloc(2);
00209     pmu_name[0] = 0;
00210     event = event_string;
00211   }
00212   masks = strstr (event, ":");
00213   if (masks != NULL) {
00214       *masks = 0;     // null terminate event name
00215       masks += 1;     // masks follow :
00216   } else {
00217       masks = "";
00218   }
00219 
00220   // build event name to find, put a pmu name on it if we have one
00221   if(strlen(pmu_name) == 0) {
00222       sprintf(fullname,"%s", event);
00223   } else {
00224       sprintf(fullname,"%s::%s", pmu_name, event);
00225   }
00226   SUBDBG("pmu_name: %s, event: %s, masks: %s, fullname: %s\n", pmu_name, event, masks, fullname);
00227 
00228   // if the libpfm4 index was not provided, try to get one based on the event name passed in.
00229   if (libpfm4_index == -1) {
00230       libpfm4_index = pfm_find_event(fullname);
00231       if (libpfm4_index < 0) {
00232           free(event_string);
00233           free(pmu_name);
00234           _papi_hwi_unlock( NAMELIB_LOCK );
00235           SUBDBG("EXIT: error from libpfm4 find event\n");
00236           return NULL;
00237       }
00238       SUBDBG("libpfm4_index: %#x\n", libpfm4_index);
00239   }
00240 
00241     // get this events information from libpfm4, if unavailable return event not found (structure be zeroed)
00242     memset( &einfo, 0, sizeof( pfm_event_info_t ));
00243     einfo.size = sizeof(pfm_event_info_t);
00244     if ((ret = pfm_get_event_info(libpfm4_index, PFM_OS_PERF_EVENT_EXT, &einfo)) != PFM_SUCCESS) {
00245         free(event_string);
00246         free(pmu_name);
00247         _papi_hwi_unlock( NAMELIB_LOCK );
00248         SUBDBG("EXIT: pfm_get_event_info failed with %d\n", ret);
00249         return NULL;
00250     }
00251 
00252     // if pmu type is not one supported by this component, return event not found (structure be zeroed)
00253     memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00254     pinfo.size = sizeof(pfm_pmu_info_t);
00255     pfm_get_pmu_info(einfo.pmu, &pinfo);
00256     if (pmu_is_present_and_right_type(&pinfo, event_table->pmu_type) == 0) {
00257         free(event_string);
00258         free(pmu_name);
00259         _papi_hwi_unlock( NAMELIB_LOCK );
00260         SUBDBG("EXIT: PMU not supported by this component: einfo.pmu: %d, PFM_PMU_TYPE_UNCORE: %d\n", einfo.pmu, PFM_PMU_TYPE_UNCORE);
00261         return NULL;
00262     }
00263 
00264   ntv_evt->allocated_name=strdup(name);
00265   ntv_evt->mask_string=strdup(masks);
00266   ntv_evt->component=_peu_libpfm4_get_cidx();
00267   ntv_evt->pmu=pmu_name;
00268   ntv_evt->base_name=strdup(event);
00269   ntv_evt->pmu_plus_name=strdup(fullname);
00270   ntv_evt->libpfm4_idx=libpfm4_index;
00271   ntv_evt->event_description=strdup(einfo.desc);
00272   ntv_evt->users=0;      /* is this needed? */
00273   ntv_evt->cpu=perf_arg.cpu;
00274 
00275     SUBDBG("ntv_evt->mask_string: %p (%s)\n", ntv_evt->mask_string, ntv_evt->mask_string);
00276     char *msk_ptr = strdup(masks);      // get a work copy of the mask string before we free the space it was in
00277     free(event_string);
00278 
00279     // if there is any mask data, collect their descriptions
00280     if ((msk_ptr != NULL)  &&  (strlen(msk_ptr) > 0)) {
00281         // go get the descriptions for each of the masks provided with this event
00282         char mask_desc[PAPI_HUGE_STR_LEN] = "";
00283         char *ptr = msk_ptr;
00284         SUBDBG("ptr: %p (%s)\n", ptr, ptr);
00285         while (ptr != NULL) {
00286             char *ptrm = strstr(ptr, ":");
00287             if (ptrm != NULL) {
00288                 *ptrm = '\0';
00289                 ptrm++;
00290             }
00291 
00292             // get the length of the mask name
00293             char *wrk = strchr(ptr, '=');
00294             unsigned int msk_name_len;
00295             if (wrk != NULL) {
00296                 msk_name_len = wrk - ptr;
00297             } else {
00298                 msk_name_len = strlen (ptr);
00299             }
00300 
00301             int i;
00302             for (i=0 ; i<einfo.nattrs ; i++) {
00303                 // get this events attribute information from libpfm4, if unavailable return event not found (table must be cleared)
00304                 memset (&ainfo, 0, sizeof(pfm_event_attr_info_t));
00305                 ainfo.size = sizeof(pfm_event_attr_info_t);
00306                 ret = pfm_get_event_attr_info(libpfm4_index, i, PFM_OS_PERF_EVENT_EXT, &ainfo);
00307                 if (ret != PFM_SUCCESS) {
00308                     free (msk_ptr);
00309                     SUBDBG("EXIT: Attribute info not found, libpfm4_index: %#x, ret: %d\n", libpfm4_index, _papi_libpfm4_error(ret));
00310                     return NULL;
00311                 }
00312 
00313                 // if this is the one we want, append its description
00314                 if ((msk_name_len == strlen(ainfo.name))  && (strncmp(ptr, ainfo.name, msk_name_len) == 0)) {
00315                     SUBDBG("Found mask: %s, i: %d\n", ainfo.name, i);
00316                     // find out how much space is left in the mask description work buffer we are building
00317                     unsigned int mskleft = sizeof(mask_desc) - strlen(mask_desc);
00318                     // if no space left, just discard this mask description
00319                     if (mskleft <= 1) {
00320                         SUBDBG("EXIT: Attribute description discarded: %s\n", ainfo.desc);
00321                         break;
00322                     }
00323                     // if description buffer is not empty, put in mask description separator
00324                     if (strlen(mask_desc) > 0) {
00325                         strcat (mask_desc, ":");
00326                         mskleft--;
00327                     }
00328                     // if new description will not all fit in buffer, report truncation
00329                     if (mskleft < (strlen(ainfo.desc) + 1)) {
00330                         SUBDBG("EXIT: Attribute description truncated: %s\n", ainfo.desc);
00331                     }
00332                     // move as much of this description as will fit
00333                     strncat (mask_desc, ainfo.desc, mskleft-1);
00334                     mask_desc[mskleft-1] = '\0';
00335                     break;
00336                 }
00337             }
00338 
00339             // if we have filled the work buffer, we can quit now
00340             if ( (sizeof(mask_desc) - strlen(mask_desc))  <= 1) {
00341                 break;
00342             }
00343             ptr = ptrm;
00344         }
00345         ntv_evt->mask_description=strdup(mask_desc);
00346         SUBDBG("ntv_evt->mask_description: %p (%s)\n", ntv_evt->mask_description, ntv_evt->mask_description);
00347     }
00348 
00349     // give back space if we got any
00350     if (msk_ptr != NULL) {
00351         free (msk_ptr);
00352     }
00353 
00354     // create a papi table for this native event, put the index into the event sets array of native events into the papi table
00355     int new_event_code = _papi_hwi_native_to_eventcode(_peu_libpfm4_get_cidx(), libpfm4_index, nevt_idx, ntv_evt->allocated_name);
00356     _papi_hwi_set_papi_event_string((const char *)ntv_evt->allocated_name);
00357     _papi_hwi_set_papi_event_code(new_event_code, 1);
00358 
00359     ntv_evt->papi_event_code=new_event_code;
00360 
00361     SUBDBG("Using %#x as index for %s\n", ntv_evt->libpfm4_idx, fullname);
00362     SUBDBG("num_native_events: %d, allocated_native_events: %d\n", event_table->num_native_events, event_table->allocated_native_events);
00363     SUBDBG("Native Event: papi_event_code: %#x, libpfm4_idx: %#x, pmu: %s, base_name: %s, mask_string: %s, allocated_name: %s\n",
00364             ntv_evt->papi_event_code, ntv_evt->libpfm4_idx, ntv_evt->pmu, ntv_evt->base_name, ntv_evt->mask_string, ntv_evt->allocated_name);
00365     SUBDBG("event_table->native_events[%d]: %p, cpu: %d, attr.config: 0x%"PRIx64", attr.config1: 0x%"PRIx64", attr.config2: 0x%"PRIx64", attr.type: 0x%"PRIx32", attr.exclude_user: %d, attr.exclude_kernel: %d, attr.exclude_guest: %d\n",
00366         nevt_idx, &(event_table->native_events[nevt_idx]), ntv_evt->cpu, ntv_evt->attr.config,
00367         ntv_evt->attr.config1, ntv_evt->attr.config2, ntv_evt->attr.type,
00368         ntv_evt->attr.exclude_user, ntv_evt->attr.exclude_kernel, ntv_evt->attr.exclude_guest);
00369 
00370   /* If we've used all of the allocated native events, then allocate more room */
00371   if (event_table->num_native_events >=
00372       event_table->allocated_native_events-1) {
00373 
00374       SUBDBG("Allocating more room for native events (%d %ld)\n",
00375         (event_table->allocated_native_events+NATIVE_EVENT_CHUNK),
00376         (long)sizeof(struct native_event_t) *
00377         (event_table->allocated_native_events+NATIVE_EVENT_CHUNK));
00378 
00379       event_table->native_events=realloc(event_table->native_events,
00380                sizeof(struct native_event_t) *
00381                (event_table->allocated_native_events+NATIVE_EVENT_CHUNK));
00382       event_table->allocated_native_events+=NATIVE_EVENT_CHUNK;
00383 
00384       // we got new space so we need to reset the pointer to the correct native event in the new space
00385       ntv_evt = &(event_table->native_events[nevt_idx]);
00386    }
00387 
00388   _papi_hwi_unlock( NAMELIB_LOCK );
00389 
00390   // if getting more space for native events failed, report that allocate failed
00391   if (event_table->native_events==NULL) {
00392      SUBDBG("EXIT: attempt to get more space for native events failed\n");
00393      return NULL;
00394   }
00395 
00396   // if we created a new event, bump the number used
00397   if (event_num < 0) {
00398      event_table->num_native_events++;
00399   }
00400 
00401   if (encode_failed != 0) {
00402       SUBDBG("EXIT: encoding event failed\n");
00403       return NULL;
00404   }
00405 
00406   SUBDBG("EXIT: new_event: %p\n", ntv_evt);
00407   return ntv_evt;
00408 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int find_existing_event ( char *  name,
struct native_event_table_t event_table 
) [static]

Definition at line 47 of file peu_libpfm4_events.c.

00048                                                                          {
00049   SUBDBG("Entry: name: %s, event_table: %p, num_native_events: %d\n", name, event_table, event_table->num_native_events);
00050 
00051   int i,event=PAPI_ENOEVNT;
00052 
00053   _papi_hwi_lock( NAMELIB_LOCK );
00054 
00055   for(i=0;i<event_table->num_native_events;i++) {
00056     // Most names passed in will contain the pmu name, so first we compare to the allocated name (it has pmu name on front)
00057     if (!strcmp(name,event_table->native_events[i].allocated_name)) {
00058       SUBDBG("Found allocated_name: %s, libpfm4_idx: %#x, papi_event_code: %#x\n", 
00059          event_table->native_events[i].allocated_name, event_table->native_events[i].libpfm4_idx, event_table->native_events[i].papi_event_code);
00060       event=i;
00061       break;
00062     }
00063     // some callers have an event name without the pmu name on the front, so we also compare to the base name (just the event name part)
00064     if (!strcmp(name,event_table->native_events[i].base_name)) {
00065       SUBDBG("Found base_name: %s, libpfm4_idx: %#x, papi_event_code: %#x\n",
00066          event_table->native_events[i].base_name, event_table->native_events[i].libpfm4_idx, event_table->native_events[i].papi_event_code);
00067       event=i;
00068       break;
00069     }
00070   }
00071   _papi_hwi_unlock( NAMELIB_LOCK );
00072 
00073   SUBDBG("EXIT: returned: %#x\n", event);
00074   return event;
00075 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_first_event_next_pmu ( int  pmu_idx,
int  pmu_type 
) [static]

Definition at line 420 of file peu_libpfm4_events.c.

00421 {
00422     SUBDBG("ENTER: pmu_idx: %d, pmu_type: %d\n", pmu_idx, pmu_type);
00423   int pidx, ret;
00424 
00425   pfm_pmu_info_t pinfo;
00426 
00427   // start looking at the next pmu in the list
00428   pmu_idx++;
00429 
00430   while(pmu_idx<PFM_PMU_MAX) {
00431 
00432     /* clear the PMU structure (required by libpfm4) */
00433     memset(&pinfo,0,sizeof(pfm_pmu_info_t));
00434     pinfo.size = sizeof(pfm_pmu_info_t);
00435     ret=pfm_get_pmu_info(pmu_idx, &pinfo);
00436 
00437     if ((ret==PFM_SUCCESS) && pmu_is_present_and_right_type(&pinfo,pmu_type)) {
00438 
00439       pidx=pinfo.first_event;
00440       SUBDBG("First event in pmu: %s is %#x\n", pinfo.name, pidx);
00441 
00442       if (pidx<0) {
00443     /* For some reason no events available */
00444     /* despite the PMU being active.       */
00445         /* This can happen, for example with ix86arch */
00446     /* inside of VMware                           */
00447       }
00448       else {
00449          SUBDBG("EXIT: pidx: %#x\n", pidx);
00450          return pidx;
00451       }
00452     }
00453 
00454     pmu_idx++;
00455 
00456   }
00457 
00458   SUBDBG("EXIT: PAPI_ENOEVNT\n");
00459   return PAPI_ENOEVNT;
00460   
00461 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int pmu_is_present_and_right_type ( pfm_pmu_info_t *  pinfo,
int  type 
) [static]

Definition at line 78 of file peu_libpfm4_events.c.

00078                                                                           {
00079 //   SUBDBG("ENTER: pinfo: %p, pinfo->is_present: %d, pinfo->type: %#x, type: %#x\n", pinfo, pinfo->is_present, pinfo->type, type);
00080   if (!pinfo->is_present) {
00081 //    SUBDBG("EXIT: not present\n");
00082       return 0;
00083   }
00084 
00085   if ((pinfo->type==PFM_PMU_TYPE_UNCORE) && (type&PMU_TYPE_UNCORE)) {
00086 //    SUBDBG("EXIT: found PFM_PMU_TYPE_UNCORE\n");
00087       return 1;
00088   }
00089   if ((pinfo->type==PFM_PMU_TYPE_CORE) && (type&PMU_TYPE_CORE)) {
00090 //    SUBDBG("EXIT: found PFM_PMU_TYPE_CORE\n");
00091       return 1;
00092   }
00093   if ((pinfo->type==PFM_PMU_TYPE_OS_GENERIC) && (type&PMU_TYPE_OS)) {
00094 //    SUBDBG("EXIT: found PFM_PMU_TYPE_OS_GENERIC\n");
00095       return 1;
00096   }
00097 
00098 //  SUBDBG("EXIT: not right type\n");
00099   return 0;
00100 }

Here is the caller graph for this function:


Variable Documentation

int attr_idx [static]

Definition at line 33 of file peu_libpfm4_events.c.


Generated on 17 Nov 2016 for PAPI by  doxygen 1.6.1