native_avail.c File Reference

Include dependency graph for native_avail.c:

Go to the source code of this file.

Data Structures

struct  command_flags_t

Defines

#define EVT_LINE   80
#define EVT_LINE_BUF_SIZE   4096

Functions

static void print_help (char **argv)
static int no_str_arg (char *arg)
static void parse_args (int argc, char **argv, command_flags_t *f)
static void space_pad (char *str, int spaces)
static void check_event (PAPI_event_info_t *info)
static void format_event_output (PAPI_event_info_t *info, int offset)
static void print_event_output (int val_flag)
static int parse_event_qualifiers (PAPI_event_info_t *info)
int main (int argc, char **argv)

Variables

unsigned int event_available = 0
unsigned int event_output_buffer_size = 0
char * event_output_buffer = NULL

Define Documentation

#define EVT_LINE   80

Definition at line 46 of file native_avail.c.

#define EVT_LINE_BUF_SIZE   4096

Definition at line 47 of file native_avail.c.


Function Documentation

static void check_event ( PAPI_event_info_t info  )  [static]

Definition at line 173 of file native_avail.c.

00174 {
00175     int EventSet = PAPI_NULL;
00176 
00177     // if this event has already passed the check test, no need to try this one again
00178     if (event_available) {
00179         return;
00180     }
00181 
00182     if (PAPI_create_eventset (&EventSet) == PAPI_OK) {
00183         if (PAPI_add_named_event (EventSet, info->symbol) == PAPI_OK) {
00184             PAPI_remove_named_event (EventSet, info->symbol);
00185             event_available = 1;
00186         } // else printf("********** PAPI_add_named_event( %s ) failed: event could not be added \n", info->symbol);
00187         if ( PAPI_destroy_eventset( &EventSet ) != PAPI_OK ) {
00188             printf("**********  Call to destroy eventset failed when trying to check event '%s'  **********\n", info->symbol);
00189         }
00190     }
00191 
00192     return;
00193 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void format_event_output ( PAPI_event_info_t info,
int  offset 
) [static]

Definition at line 196 of file native_avail.c.

00197 {
00198     unsigned int i, j = 0;
00199     char event_line_buffer[EVT_LINE_BUF_SIZE];
00200     char event_line_units[100];
00201 
00202     /* indent by offset */
00203     if ( offset ) {
00204         // this one is used for event qualifiers
00205         sprintf(event_line_buffer, "|     %-73s|\n", info->symbol);
00206     }
00207     else {
00208         // this one is used for new events
00209         sprintf(event_line_buffer, "| %-73s%4s|\n", info->symbol, "<-->");
00210     }
00211 
00212     while ( j <= strlen( info->long_descr ) ) {
00213         // The event_line_buffer is used to collect an event or mask name and its description.
00214         // The description will be folded to keep the length of output lines reasonable.  So this
00215         // buffer may contain multiple lines of print output.  Check to make sure there is room
00216         // for another line of print output.  If there is not enough room for another output line
00217         // just exit the loop and truncate the description field (the buffer is big enough this
00218         // should not happen).
00219         if ((EVT_LINE_BUF_SIZE - strlen(event_line_buffer)) < EVT_LINE) {
00220             printf ("Event or mask description has been truncated.\n");
00221             break;
00222         }
00223 
00224         // get amount of description that will fit in an output line
00225         i = EVT_LINE - 12 - 2;
00226         // start of a description line
00227         strcat(event_line_buffer,"|            " );
00228         // if we need to copy less than what fits in this line, move it and exit loop
00229         if (i > strlen(&info->long_descr[j])) {
00230             strcat( event_line_buffer, &info->long_descr[j]);
00231             space_pad( event_line_buffer, i - strlen(&info->long_descr[j]));
00232             strcat( event_line_buffer, "|\n" );
00233             break;
00234         }
00235 
00236         // move what will fit into the line then loop back to do the rest in a new line
00237         int k = strlen(event_line_buffer);
00238         strncat( event_line_buffer, &info->long_descr[j], i );
00239         event_line_buffer[k+i] = '\0';
00240         strcat( event_line_buffer, "|\n" );
00241 
00242         // bump index past what we copied
00243         j += i;
00244     }
00245 
00246     // also show the units for this event if a unit name has been set
00247     event_line_units[0] = '\0';
00248     if (info->units[0] != 0) {
00249         sprintf(event_line_units, "|     Units: %-66s|\n", info->units );
00250     }
00251 
00252     // get the amount of used space in the output buffer
00253     int out_buf_used = 0;
00254     if ((event_output_buffer_size > 0) && (event_output_buffer != NULL)) {
00255         out_buf_used = strlen(event_output_buffer);
00256     }
00257 
00258     // if this will not fit in output buffer, make it bigger
00259     if (event_output_buffer_size < out_buf_used + strlen(event_line_buffer) + strlen(event_line_units) + 1) {
00260         if (event_output_buffer_size == 0) {
00261             event_output_buffer_size = 1024;
00262             event_output_buffer = calloc(1, event_output_buffer_size);
00263         } else {
00264             event_output_buffer_size += 1024;
00265             event_output_buffer = realloc(event_output_buffer, event_output_buffer_size);
00266         }
00267     }
00268 
00269     // make sure we got the memory we asked for
00270     if (event_output_buffer == NULL) {
00271         test_fail( __FILE__, __LINE__, "Allocation of output buffer memory failed.\n", errno );
00272     }
00273 
00274     strcat(event_output_buffer, event_line_buffer);
00275     strcat(event_output_buffer, event_line_units);
00276 
00277     return;
00278 }

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 346 of file native_avail.c.

00347 {
00348     int i, k;
00349     int num_events;
00350     int num_cmp_events = 0;
00351     int retval;
00352     PAPI_event_info_t info;
00353     const PAPI_hw_info_t *hwinfo = NULL;
00354     command_flags_t flags;
00355     int enum_modifier;
00356     int numcmp, cid;
00357 
00358     /* Set TESTS_QUIET variable */
00359     tests_quiet( argc, argv );
00360 
00361     /* Initialize before parsing the input arguments */
00362     retval = PAPI_library_init( PAPI_VER_CURRENT );
00363     if ( retval != PAPI_VER_CURRENT ) {
00364         test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
00365     }
00366 
00367     /* Parse the command-line arguments */
00368     parse_args( argc, argv, &flags );
00369 
00370     /* Set enum modifier mask */
00371     if ( flags.dear )
00372         enum_modifier = PAPI_NTV_ENUM_DEAR;
00373     else if ( flags.darr )
00374         enum_modifier = PAPI_NTV_ENUM_DARR;
00375     else if ( flags.iear )
00376         enum_modifier = PAPI_NTV_ENUM_IEAR;
00377     else if ( flags.iarr )
00378         enum_modifier = PAPI_NTV_ENUM_IARR;
00379     else if ( flags.opcm )
00380         enum_modifier = PAPI_NTV_ENUM_OPCM;
00381     else
00382         enum_modifier = PAPI_ENUM_EVENTS;
00383 
00384 
00385     if ( !TESTS_QUIET ) {
00386         retval = PAPI_set_debug( PAPI_VERB_ECONT );
00387         if ( retval != PAPI_OK ) {
00388             test_fail( __FILE__, __LINE__, "PAPI_set_debug", retval );
00389         }
00390     }
00391 
00392     retval = papi_print_header( "Available native events and hardware information.\n", &hwinfo );
00393     if ( retval != PAPI_OK ) {
00394         test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
00395     }
00396 
00397     /* Do this code if the event name option was specified on the commandline */
00398     if ( flags.named ) {
00399         if ( PAPI_event_name_to_code( flags.name, &i ) == PAPI_OK ) {
00400             if ( PAPI_get_event_info( i, &info ) == PAPI_OK ) {
00401                 printf( "Event name:     %s\n", info.symbol);
00402                 printf( "Description:    %s\n", info.long_descr );
00403 
00404                 /* handle the PAPI component-style events which have a component:::event type */
00405                 char *ptr;
00406                 if ((ptr=strstr(flags.name, ":::"))) {
00407                     ptr+=3;
00408                     /* handle libpfm4-style events which have a pmu::event type event name */
00409                 } else if ((ptr=strstr(flags.name, "::"))) {
00410                     ptr+=2;
00411                 }
00412                 else {
00413                     ptr=flags.name;
00414                 }
00415 
00416                 /* if event qualifiers exist but none specified, process all */
00417                 if ( !strchr( ptr, ':' ) ) {
00418                     if ( PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK ) {
00419                         printf( "\nQualifiers:         Name -- Description\n" );
00420                         do {
00421                             retval = PAPI_get_event_info( i, &info );
00422                             if ( retval == PAPI_OK ) {
00423                                 if ( parse_event_qualifiers( &info ) ) {
00424                                     printf( "      Info:   %10s -- %s\n", info.symbol, info.long_descr );
00425                                 }
00426                             }
00427                         } while ( PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK );
00428                     }
00429                 }
00430             }
00431         } else {
00432             printf("Sorry, an event by the name '%s' could not be found.\n",
00433                     flags.name);
00434             printf("Is it typed correctly?\n\n");
00435             exit( 1 );
00436         }
00437         test_pass( __FILE__, NULL, 0 );
00438         exit( 0 );
00439     }
00440 
00441     // Look at all the events and qualifiers and print the information the user has asked for */
00442 
00443     numcmp = PAPI_num_components(  );
00444 
00445     num_events = 0;
00446 
00447     for ( cid = 0; cid < numcmp; cid++ ) {
00448         const PAPI_component_info_t *component;
00449         component=PAPI_get_component_info(cid);
00450 
00451         /* Skip disabled components */
00452         if (component->disabled) continue;
00453 
00454         printf( "===============================================================================\n" );
00455         printf( " Native Events in Component: %s\n",component->name);
00456         printf( "===============================================================================\n" );
00457 
00458         // show this component has not found any events yet
00459         num_cmp_events = 0;
00460 
00461         /* Always ASK FOR the first event */
00462         /* Don't just assume it'll be the first numeric value */
00463         i = 0 | PAPI_NATIVE_MASK;
00464 
00465         retval=PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cid );
00466 
00467         if (retval==PAPI_OK) {
00468             do {
00469                 memset( &info, 0, sizeof ( info ) );
00470                 retval = PAPI_get_event_info( i, &info );
00471 
00472                 /* This event may not exist */
00473                 if ( retval != PAPI_OK ) continue;
00474 
00475                 /* Bail if event name doesn't contain include string */
00476                 if ( flags.include && !strstr( info.symbol, flags.istr ) ) continue;
00477                                      
00478                 /* Bail if event name does contain exclude string */
00479                 if ( flags.xclude && strstr( info.symbol, flags.xstr ) ) continue;
00480 
00481                 // if not the first event in this component, put out a divider
00482                 if (num_cmp_events) {
00483                     printf( "--------------------------------------------------------------------------------\n" );
00484                 }
00485 
00486                 /* count only events that are actually processed */
00487                 num_events++;
00488                 num_cmp_events++;
00489 
00490                 if (flags.check){
00491                     check_event(&info);
00492                 }
00493 
00494                 format_event_output( &info, 0);
00495 
00496                 /*      modifier = PAPI_NTV_ENUM_GROUPS returns event codes with a
00497                         groups id for each group in which this
00498                         native event lives, in bits 16 - 23 of event code
00499                         terminating with PAPI_ENOEVNT at the end of the list.
00500                         */
00501 
00502                 /* This is an IBM Power issue */
00503                 if ( flags.groups ) {
00504                     k = i;
00505                     if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) == PAPI_OK ) {
00506                         printf( "Groups: " );
00507                         do {
00508                             printf( "%4d", ( ( k & PAPI_NTV_GROUP_AND_MASK ) >>
00509                                         PAPI_NTV_GROUP_SHIFT ) - 1 );
00510                         } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) ==PAPI_OK );
00511                         printf( "\n" );
00512                     }
00513                 }
00514 
00515                 // If the user has asked us to check the events then we need to
00516                 // walk the list of qualifiers and try to check the event with each one.
00517                 // Even if the user does not want to display the qualifiers this is necessary
00518                 // to be able to correctly report which events can be used on this system.
00519                 //
00520                 // We also need to walk the list if the user wants to see the qualifiers.
00521 
00522                 if (flags.qualifiers || flags.check){
00523                     k = i;
00524                     if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK ) {
00525                         // clear event string using first mask
00526                         char first_event_mask_string[PAPI_HUGE_STR_LEN] = "";
00527 
00528                         do {
00529                             retval = PAPI_get_event_info( k, &info );
00530                             if ( retval == PAPI_OK ) {
00531                                 // if first event mask string not set yet, set it now
00532                                 if (strlen(first_event_mask_string) == 0) {
00533                                     strcpy (first_event_mask_string, info.symbol);
00534                                 }
00535 
00536                                 if ( flags.check ) {
00537                                     check_event(&info);
00538                                 }
00539                                 // now test if the event qualifiers should be displayed to the user
00540                                 if ( flags.qualifiers ) {
00541                                     if ( parse_event_qualifiers( &info ) )
00542                                         format_event_output( &info, 2);
00543                                 }
00544                             }
00545                         } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK );
00546                         // if we are validating events and the event_available flag is not set yet, try a few more combinations
00547                         if (flags.check  && (event_available == 0)) {
00548                             // try using the event with the first mask defined for the event and the cpu mask
00549                             // this is a kludge but many of the uncore events require an event specific mask (usually
00550                             // the first one defined will do) and they all require the cpu mask
00551                             strcpy (info.symbol, first_event_mask_string);
00552                             strcat (info.symbol, ":cpu=1");
00553                             check_event(&info);
00554                         }
00555                         if (flags.check  && (event_available == 0)) {
00556                             // an even bigger kludge is that there are 4 snpep_unc_pcu events which require the 'ff' and 'cpu' qualifiers to work correctly.
00557                             // if nothing else has worked, this code will try those two qualifiers with the current event name to see if it works
00558                             strcpy (info.symbol, first_event_mask_string);
00559                             char *wptr = strrchr (info.symbol, ':');
00560                             if (wptr != NULL) {
00561                                 *wptr = '\0';
00562                                 strcat (info.symbol, ":ff=64:cpu=1");
00563                                 check_event(&info);
00564                             }
00565                         }
00566                     }
00567                 }
00568                 print_event_output(flags.check);
00569             } while (PAPI_enum_cmp_event( &i, enum_modifier, cid ) == PAPI_OK );
00570         }
00571     }
00572 
00573     if (num_cmp_events != 0) {
00574         printf( "--------------------------------------------------------------------------------\n" );
00575     }
00576     printf( "\nTotal events reported: %d\n", num_events );
00577 
00578     test_pass( __FILE__, NULL, 0 );
00579     exit( 0 );
00580 }

Here is the call graph for this function:

static int no_str_arg ( char *  arg  )  [static]

Definition at line 90 of file native_avail.c.

00091 {
00092     return ( ( arg == NULL ) || ( strlen( arg ) == 0 ) || ( arg[0] == '-' ) );
00093 }

Here is the caller graph for this function:

static void parse_args ( int  argc,
char **  argv,
command_flags_t f 
) [static]

Definition at line 96 of file native_avail.c.

00097 {
00098     int i;
00099 
00100     /* Look for all currently defined commands */
00101     memset( f, 0, sizeof ( command_flags_t ) );
00102     f->qualifiers = 1;
00103     f->groups = 1;
00104 
00105     for ( i = 1; i < argc; i++ ) {
00106         if ( !strcmp( argv[i], "--darr" ) )
00107             f->darr = 1;
00108         else if ( !strcmp( argv[i], "--dear" ) )
00109             f->dear = 1;
00110         else if ( !strcmp( argv[i], "--iarr" ) )
00111             f->iarr = 1;
00112         else if ( !strcmp( argv[i], "--iear" ) )
00113             f->iear = 1;
00114         else if ( !strcmp( argv[i], "--opcm" ) )
00115             f->opcm = 1;
00116         else if ( !strcmp( argv[i], "--noqual" ) )
00117             f->qualifiers = 0;
00118         else if ( !strcmp( argv[i], "--nogroups" ) )
00119             f->groups = 0;
00120         else if ( !strcmp( argv[i], "-e" ) ) {
00121             f->named = 1;
00122             i++;
00123             f->name = argv[i];
00124             if ( i >= argc || no_str_arg( f->name ) ) {
00125                 printf( "Invalid argument for -e\n");
00126                 exit(1);
00127             }
00128         } else if ( !strcmp( argv[i], "-i" ) ) {
00129             f->include = 1;
00130             i++;
00131             f->istr = argv[i];
00132             if ( i >= argc || no_str_arg( f->istr ) ) {
00133                 printf( "Invalid argument for -i\n");
00134                 exit(1);
00135             }
00136         } else if ( !strcmp( argv[i], "-x" ) ) {
00137             f->xclude = 1;
00138             i++;
00139             f->xstr = argv[i];
00140             if ( i >= argc || no_str_arg( f->xstr ) ) {
00141                 printf( "Invalid argument for -x\n");
00142                 exit(1);
00143             }
00144         } else if ( !strcmp( argv[i], "-h" ) || !strcmp( argv[i], "--help" ) ) {
00145             f->help = 1;
00146         } else if ( !strcmp( argv[i], "-c" ) || !strcmp( argv[i], "--check" ) ) {
00147             f->check = 1;
00148         } else {
00149             printf( "%s is not supported\n", argv[i] );
00150             exit(1);
00151         }
00152     }
00153 
00154     /* if help requested, print and bail */
00155     if ( f->help ) {
00156         print_help( argv);
00157         exit( 1 );
00158     }
00159 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse_event_qualifiers ( PAPI_event_info_t info  )  [static]

Definition at line 311 of file native_avail.c.

00312 {
00313     char *pmask,*ptr;
00314 
00315     /* handle the PAPI component-style events which have a component:::event type */
00316     if ((ptr=strstr(info->symbol, ":::"))) {
00317         ptr+=3;
00318         /* handle libpfm4-style events which have a pmu::event type event name */
00319     } else if ((ptr=strstr(info->symbol, "::"))) {
00320         ptr+=2;
00321     }
00322     else {
00323         ptr=info->symbol;
00324     }
00325 
00326     if ( ( pmask = strchr( ptr, ':' ) ) == NULL ) {
00327         return ( 0 );
00328     }
00329     memmove( info->symbol, pmask, ( strlen(pmask) + 1 ) * sizeof(char) );
00330 
00331     //  The description field contains the event description followed by a tag 'masks:'
00332     //  and then the mask description (if there was a mask with this event).  The following
00333     //  code isolates the mask description part of this information.
00334 
00335     pmask = strstr( info->long_descr, "masks:" );
00336     if ( pmask == NULL ) {
00337         info->long_descr[0] = 0;
00338     } else {
00339         pmask += 6;        // bump pointer past 'masks:' identifier in description
00340         memmove( info->long_descr, pmask, (strlen(pmask) + 1) * sizeof(char) );
00341     }
00342     return ( 1 );
00343 }

Here is the caller graph for this function:

static void print_event_output ( int  val_flag  )  [static]

Definition at line 281 of file native_avail.c.

00282 {
00283     // first we need to update the available flag at the beginning of the buffer
00284     // this needs to reflect if this event name by itself or the event name with one of the qualifiers worked
00285     // if none of the combinations worked then we will show the event as not available
00286     char *val_flag_ptr = strstr(event_output_buffer, "<-->");
00287     if (val_flag_ptr != NULL) {
00288         if ((val_flag) && (event_available == 0)) {
00289             // event is not available, update the place holder (replace the <--> with <NA>)
00290             *(val_flag_ptr+1) = 'N';
00291             *(val_flag_ptr+2) = 'A';
00292         } else {
00293             event_available = 0;       // reset this flag for next event
00294             // event is available, just remove the place holder (replace the <--> with spaces)
00295             *val_flag_ptr = ' ';
00296             *(val_flag_ptr+1) = ' ';
00297             *(val_flag_ptr+2) = ' ';
00298             *(val_flag_ptr+3) = ' ';
00299         }
00300     }
00301 
00302     // now we can finally send this events output to the user
00303     printf( "%s", event_output_buffer);
00304 //  printf( "--------------------------------------------------------------------------------\n" );
00305 
00306     event_output_buffer[0] = '\0';          // start the next event with an empty buffer
00307     return;
00308 }

Here is the caller graph for this function:

static void print_help ( char **  argv  )  [static]

Definition at line 67 of file native_avail.c.

00068 {
00069     printf( "This is the PAPI native avail program.\n" );
00070     printf( "It provides availability and detail information for PAPI native events.\n" );
00071     printf( "Usage: %s [options]\n", argv[0] );
00072     printf( "\nOptions:\n" );
00073     printf( "   --help, -h   print this help message\n" );
00074     printf( "   --check, -c  attempts to add each event\n");
00075     printf( "   -e EVENTNAME display detailed information about named native event\n" );
00076     printf( "   -i EVENTSTR  include only event names that contain EVENTSTR\n" );
00077     printf( "   -x EVENTSTR  exclude any event names that contain EVENTSTR\n" );
00078     printf( "   --noqual     suppress display of event qualifiers (mask and flag) information\n" );
00079     printf( "\nProcessor-specific options\n");
00080     printf( "  --darr        display events supporting Data Address Range Restriction\n" );
00081     printf( "  --dear        display Data Event Address Register events only\n" );
00082     printf( "  --iarr        display events supporting Instruction Address Range Restriction\n" );
00083     printf( "  --iear        display Instruction Event Address Register events only\n" );
00084     printf( "  --opcm        display events supporting OpCode Matching\n" );
00085     printf( "  --nogroups    suppress display of Event grouping information\n" );
00086     printf( "\n" );
00087 }

Here is the caller graph for this function:

static void space_pad ( char *  str,
int  spaces 
) [static]

Definition at line 162 of file native_avail.c.

00163 {
00164     while ( spaces-- > 0 )
00165         strcat( str, " " );
00166 }

Here is the caller graph for this function:


Variable Documentation

unsigned int event_available = 0

Definition at line 168 of file native_avail.c.

char* event_output_buffer = NULL

Definition at line 170 of file native_avail.c.

unsigned int event_output_buffer_size = 0

Definition at line 169 of file native_avail.c.


Generated on 8 Sep 2016 for PAPI by  doxygen 1.6.1