PAPI  5.7.0.0
papi_native_avail.c File Reference
Include dependency graph for papi_native_avail.c:

Go to the source code of this file.

Data Structures

struct  command_flags_t
 

Macros

#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 int 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
 

Macro Definition Documentation

◆ EVT_LINE

#define EVT_LINE   80

Definition at line 53 of file papi_native_avail.c.

◆ EVT_LINE_BUF_SIZE

#define EVT_LINE_BUF_SIZE   4096

Definition at line 54 of file papi_native_avail.c.

Function Documentation

◆ check_event()

static void check_event ( PAPI_event_info_t info)
static

Definition at line 181 of file papi_native_avail.c.

182 {
183  int EventSet = PAPI_NULL;
184 
185  // if this event has already passed the check test, no need to try this one again
186  if (event_available) {
187  return;
188  }
189 
191  if (PAPI_add_named_event (EventSet, info->symbol) == PAPI_OK) {
193  event_available = 1;
194  } // else printf("********** PAPI_add_named_event( %s ) failed: event could not be added \n", info->symbol);
195  if ( PAPI_destroy_eventset( &EventSet ) != PAPI_OK ) {
196  printf("********** Call to destroy eventset failed when trying to check event '%s' **********\n", info->symbol);
197  }
198  }
199 
200  return;
201 }
#define PAPI_OK
Definition: fpapi.h:105
int EventSet
add PAPI preset or native hardware event by name to an EventSet
Create a new empty PAPI EventSet.
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
#define PAPI_NULL
Definition: fpapi.h:13
unsigned int event_available
int PAPI_destroy_eventset(int *EventSet)
Definition: papi.c:2014
int PAPI_remove_named_event(int EventSet, const char *EventName)
Definition: papi.c:1961
Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_event_output()

static int format_event_output ( PAPI_event_info_t info,
int  offset 
)
static

Definition at line 204 of file papi_native_avail.c.

205 {
206  unsigned int i, j = 0;
207  char event_line_buffer[EVT_LINE_BUF_SIZE];
208  char event_line_units[100];
209 
210  /* indent by offset */
211  if ( offset ) {
212  // this one is used for event qualifiers
213  sprintf(event_line_buffer, "| %-73s|\n", info->symbol);
214  }
215  else {
216  // this one is used for new events
217  sprintf(event_line_buffer, "| %-73s%4s|\n", info->symbol, "<-->");
218  }
219 
220  while ( j <= strlen( info->long_descr ) ) {
221  // The event_line_buffer is used to collect an event or mask name and its description.
222  // The description will be folded to keep the length of output lines reasonable. So this
223  // buffer may contain multiple lines of print output. Check to make sure there is room
224  // for another line of print output. If there is not enough room for another output line
225  // just exit the loop and truncate the description field (the buffer is big enough this
226  // should not happen).
227  if ((EVT_LINE_BUF_SIZE - strlen(event_line_buffer)) < EVT_LINE) {
228  printf ("Event or mask description has been truncated.\n");
229  break;
230  }
231 
232  // get amount of description that will fit in an output line
233  i = EVT_LINE - 12 - 2;
234  // start of a description line
235  strcat(event_line_buffer,"| " );
236  // if we need to copy less than what fits in this line, move it and exit loop
237  if (i > strlen(&info->long_descr[j])) {
238  strcat( event_line_buffer, &info->long_descr[j]);
239  space_pad( event_line_buffer, i - strlen(&info->long_descr[j]));
240  strcat( event_line_buffer, "|\n" );
241  break;
242  }
243 
244  // move what will fit into the line then loop back to do the rest in a new line
245  int k = strlen(event_line_buffer);
246  strncat( event_line_buffer, &info->long_descr[j], i );
247  event_line_buffer[k+i] = '\0';
248  strcat( event_line_buffer, "|\n" );
249 
250  // bump index past what we copied
251  j += i;
252  }
253 
254  // also show the units for this event if a unit name has been set
255  event_line_units[0] = '\0';
256  if (info->units[0] != 0) {
257  sprintf(event_line_units, "| Units: %-66s|\n", info->units );
258  }
259 
260  // get the amount of used space in the output buffer
261  int out_buf_used = 0;
262  if ((event_output_buffer_size > 0) && (event_output_buffer != NULL)) {
263  out_buf_used = strlen(event_output_buffer);
264  }
265 
266  // if this will not fit in output buffer, make it bigger
267  if (event_output_buffer_size < out_buf_used + strlen(event_line_buffer) + strlen(event_line_units) + 1) {
268  if (event_output_buffer_size == 0) {
271  } else {
272  event_output_buffer_size += 1024;
274  }
275  }
276 
277  // make sure we got the memory we asked for
278  if (event_output_buffer == NULL) {
279  fprintf(stderr,"Error! Allocation of output buffer memory failed.\n");
280  return errno;
281  }
282 
283  strcat(event_output_buffer, event_line_buffer);
284  strcat(event_output_buffer, event_line_units);
285 
286  return 0;
287 }
int errno
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:976
off64_t offset
Definition: iozone.c:1279
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
#define EVT_LINE
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
static void space_pad(char *str, int spaces)
unsigned int event_output_buffer_size
char * event_output_buffer
#define EVT_LINE_BUF_SIZE
int i
Definition: fileop.c:140
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 355 of file papi_native_avail.c.

356 {
357  int i, k;
358  int num_events;
359  int num_cmp_events = 0;
360  int retval;
361  PAPI_event_info_t info;
362  const PAPI_hw_info_t *hwinfo = NULL;
363  command_flags_t flags;
364  int enum_modifier;
365  int numcmp, cid;
366 
367  /* Initialize before parsing the input arguments */
369  if ( retval != PAPI_VER_CURRENT ) {
370  fprintf(stderr, "Error! PAPI_library_init\n");
371  return retval;
372  }
373 
374  /* Parse the command-line arguments */
375  parse_args( argc, argv, &flags );
376 
377  /* Set enum modifier mask */
378  if ( flags.dear )
379  enum_modifier = PAPI_NTV_ENUM_DEAR;
380  else if ( flags.darr )
381  enum_modifier = PAPI_NTV_ENUM_DARR;
382  else if ( flags.iear )
383  enum_modifier = PAPI_NTV_ENUM_IEAR;
384  else if ( flags.iarr )
385  enum_modifier = PAPI_NTV_ENUM_IARR;
386  else if ( flags.opcm )
387  enum_modifier = PAPI_NTV_ENUM_OPCM;
388  else
389  enum_modifier = PAPI_ENUM_EVENTS;
390 
392  if ( retval != PAPI_OK ) {
393  fprintf(stderr,"Error! PAPI_set_debug\n");
394  return retval;
395  }
396 
397  retval = papi_print_header( "Available native events and hardware information.\n", &hwinfo );
398  if ( retval != PAPI_OK ) {
399  fprintf(stderr,"Error! PAPI_get_hardware_info\n");
400  return 2;
401  }
402 
403  /* Do this code if the event name option was specified on the commandline */
404  if ( flags.named ) {
405  if ( PAPI_event_name_to_code( flags.name, &i ) == PAPI_OK ) {
406  if ( PAPI_get_event_info( i, &info ) == PAPI_OK ) {
407  printf( "Event name: %s\n", info.symbol);
408  printf( "Description: %s\n", info.long_descr );
409 
410  /* handle the PAPI component-style events which have a component:::event type */
411  char *ptr;
412  if ((ptr=strstr(flags.name, ":::"))) {
413  ptr+=3;
414  /* handle libpfm4-style events which have a pmu::event type event name */
415  } else if ((ptr=strstr(flags.name, "::"))) {
416  ptr+=2;
417  }
418  else {
419  ptr=flags.name;
420  }
421 
422  /* if event qualifiers exist but none specified, process all */
423  if ( !strchr( ptr, ':' ) ) {
425  printf( "\nQualifiers: Name -- Description\n" );
426  do {
427  retval = PAPI_get_event_info( i, &info );
428  if ( retval == PAPI_OK ) {
429  if ( parse_event_qualifiers( &info ) ) {
430  printf( " Info: %10s -- %s\n", info.symbol, info.long_descr );
431  }
432  }
433  } while ( PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK );
434  }
435  }
436  }
437  } else {
438  printf("Sorry, an event by the name '%s' could not be found.\n",
439  flags.name);
440  printf("Is it typed correctly?\n\n");
441  exit( 1 );
442  }
443  return 0;
444  }
445 
446  // Look at all the events and qualifiers and print the information the user has asked for */
447 
448  numcmp = PAPI_num_components( );
449 
450  num_events = 0;
451 
452  for ( cid = 0; cid < numcmp; cid++ ) {
453  const PAPI_component_info_t *component;
454  component=PAPI_get_component_info(cid);
455 
456  /* Skip disabled components */
457  if (component->disabled) continue;
458 
459  printf( "===============================================================================\n" );
460  printf( " Native Events in Component: %s\n",component->name);
461  printf( "===============================================================================\n" );
462 
463  // show this component has not found any events yet
464  num_cmp_events = 0;
465 
466  /* Always ASK FOR the first event */
467  /* Don't just assume it'll be the first numeric value */
468  i = 0 | PAPI_NATIVE_MASK;
469 
471 
472  if (retval==PAPI_OK) {
473  do {
474  memset( &info, 0, sizeof ( info ) );
475  retval = PAPI_get_event_info( i, &info );
476 
477  /* This event may not exist */
478  if ( retval != PAPI_OK ) continue;
479 
480  /* Bail if event name doesn't contain include string */
481  if ( flags.include && !strstr( info.symbol, flags.istr ) ) continue;
482 
483  /* Bail if event name does contain exclude string */
484  if ( flags.xclude && strstr( info.symbol, flags.xstr ) ) continue;
485 
486  // if not the first event in this component, put out a divider
487  if (num_cmp_events) {
488  printf( "--------------------------------------------------------------------------------\n" );
489  }
490 
491  /* count only events that are actually processed */
492  num_events++;
493  num_cmp_events++;
494 
495  if (flags.check){
496  check_event(&info);
497  }
498 
499  format_event_output( &info, 0);
500 
501  /* modifier = PAPI_NTV_ENUM_GROUPS returns event codes with a
502  groups id for each group in which this
503  native event lives, in bits 16 - 23 of event code
504  terminating with PAPI_ENOEVNT at the end of the list.
505  */
506 
507  /* This is an IBM Power issue */
508  if ( flags.groups ) {
509  k = i;
510  if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) == PAPI_OK ) {
511  printf( "Groups: " );
512  do {
513  printf( "%4d", ( ( k & PAPI_NTV_GROUP_AND_MASK ) >>
514  PAPI_NTV_GROUP_SHIFT ) - 1 );
515  } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) ==PAPI_OK );
516  printf( "\n" );
517  }
518  }
519 
520  // If the user has asked us to check the events then we need to
521  // walk the list of qualifiers and try to check the event with each one.
522  // Even if the user does not want to display the qualifiers this is necessary
523  // to be able to correctly report which events can be used on this system.
524  //
525  // We also need to walk the list if the user wants to see the qualifiers.
526 
527  if (flags.qualifiers || flags.check){
528  k = i;
529  if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK ) {
530  // clear event string using first mask
531  char first_event_mask_string[PAPI_HUGE_STR_LEN] = "";
532 
533  do {
534  retval = PAPI_get_event_info( k, &info );
535  if ( retval == PAPI_OK ) {
536  // if first event mask string not set yet, set it now
537  if (strlen(first_event_mask_string) == 0) {
538  strcpy (first_event_mask_string, info.symbol);
539  }
540 
541  if ( flags.check ) {
542  check_event(&info);
543  }
544  // now test if the event qualifiers should be displayed to the user
545  if ( flags.qualifiers ) {
546  if ( parse_event_qualifiers( &info ) )
547  format_event_output( &info, 2);
548  }
549  }
550  } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK );
551  // if we are validating events and the event_available flag is not set yet, try a few more combinations
552  if (flags.check && (event_available == 0)) {
553  // try using the event with the first mask defined for the event and the cpu mask
554  // this is a kludge but many of the uncore events require an event specific mask (usually
555  // the first one defined will do) and they all require the cpu mask
556  strcpy (info.symbol, first_event_mask_string);
557  strcat (info.symbol, ":cpu=1");
558  check_event(&info);
559  }
560  if (flags.check && (event_available == 0)) {
561  // an even bigger kludge is that there are 4 snpep_unc_pcu events which require the 'ff' and 'cpu' qualifiers to work correctly.
562  // if nothing else has worked, this code will try those two qualifiers with the current event name to see if it works
563  strcpy (info.symbol, first_event_mask_string);
564  char *wptr = strrchr (info.symbol, ':');
565  if (wptr != NULL) {
566  *wptr = '\0';
567  strcat (info.symbol, ":ff=64:cpu=1");
568  check_event(&info);
569  }
570  }
571  }
572  }
573  print_event_output(flags.check);
574  } while (PAPI_enum_cmp_event( &i, enum_modifier, cid ) == PAPI_OK );
575  }
576  }
577 
578  if (num_cmp_events != 0) {
579  printf( "--------------------------------------------------------------------------------\n" );
580  }
581  printf( "\nTotal events reported: %d\n", num_events );
582 
583  if (num_events==0) {
584  printf("\nNo events detected! Check papi_component_avail to find out why.\n");
585  printf("\n");
586  }
587 
588 
589  return 0;
590 }
#define PAPI_OK
Definition: fpapi.h:105
static void check_event(PAPI_event_info_t *info)
#define PAPI_NATIVE_MASK
const PAPI_component_info_t * PAPI_get_component_info(int cidx)
Definition: papi.c:796
static void parse_args(int argc, char **argv, command_flags_t *f)
Hardware info structure.
Definition: papi.h:781
static int num_events
int PAPI_num_components(void)
Definition: papi.c:4387
int PAPI_enum_event(int *EventCode, int modifier)
Definition: papi.c:1152
#define PAPI_VER_CURRENT
Definition: fpapi.h:14
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
int PAPI_event_name_to_code(const char *in, int *out)
Definition: papi.c:1004
int retval
Definition: zero_fork.c:53
int PAPI_get_event_info(int EventCode, PAPI_event_info_t *info)
Definition: papi.c:835
static int parse_event_qualifiers(PAPI_event_info_t *info)
int PAPI_library_init(int version)
Definition: papi.c:500
#define PAPI_NTV_GROUP_SHIFT
Definition: papi.h:527
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
#define PAPI_HUGE_STR_LEN
Definition: fpapi.h:42
#define PAPI_VERB_ECONT
Definition: fpapi.h:39
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:630
int PAPI_enum_cmp_event(int *EventCode, int modifier, int cidx)
Definition: papi.c:1357
unsigned int event_available
#define PAPI_NTV_GROUP_AND_MASK
Definition: papi.h:526
static void print_event_output(int val_flag)
void exit()
int PAPI_set_debug(int level)
Definition: papi.c:3126
int i
Definition: fileop.c:140
static int format_event_output(PAPI_event_info_t *info, int offset)
Here is the call graph for this function:

◆ no_str_arg()

static int no_str_arg ( char *  arg)
static

Definition at line 98 of file papi_native_avail.c.

99 {
100  return ( ( arg == NULL ) || ( strlen( arg ) == 0 ) || ( arg[0] == '-' ) );
101 }
Here is the caller graph for this function:

◆ parse_args()

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

Definition at line 104 of file papi_native_avail.c.

105 {
106  int i;
107 
108  /* Look for all currently defined commands */
109  memset( f, 0, sizeof ( command_flags_t ) );
110  f->qualifiers = 1;
111  f->groups = 1;
112 
113  for ( i = 1; i < argc; i++ ) {
114  if ( !strcmp( argv[i], "--darr" ) )
115  f->darr = 1;
116  else if ( !strcmp( argv[i], "--dear" ) )
117  f->dear = 1;
118  else if ( !strcmp( argv[i], "--iarr" ) )
119  f->iarr = 1;
120  else if ( !strcmp( argv[i], "--iear" ) )
121  f->iear = 1;
122  else if ( !strcmp( argv[i], "--opcm" ) )
123  f->opcm = 1;
124  else if ( !strcmp( argv[i], "--noqual" ) )
125  f->qualifiers = 0;
126  else if ( !strcmp( argv[i], "--nogroups" ) )
127  f->groups = 0;
128  else if ( !strcmp( argv[i], "-e" ) ) {
129  f->named = 1;
130  i++;
131  f->name = argv[i];
132  if ( i >= argc || no_str_arg( f->name ) ) {
133  printf( "Invalid argument for -e\n");
134  exit(1);
135  }
136  } else if ( !strcmp( argv[i], "-i" ) ) {
137  f->include = 1;
138  i++;
139  f->istr = argv[i];
140  if ( i >= argc || no_str_arg( f->istr ) ) {
141  printf( "Invalid argument for -i\n");
142  exit(1);
143  }
144  } else if ( !strcmp( argv[i], "-x" ) ) {
145  f->xclude = 1;
146  i++;
147  f->xstr = argv[i];
148  if ( i >= argc || no_str_arg( f->xstr ) ) {
149  printf( "Invalid argument for -x\n");
150  exit(1);
151  }
152  } else if ( strstr( argv[i], "-h" ) ) {
153  f->help = 1;
154  } else if ( !strcmp( argv[i], "-c" ) || !strcmp( argv[i], "--check" ) ) {
155  f->check = 1;
156  } else {
157  printf( "%s is not supported\n", argv[i] );
158  exit(1);
159  }
160  }
161 
162  /* if help requested, print and bail */
163  if ( f->help ) {
164  print_help( argv);
165  exit( 1 );
166  }
167 }
double f(double a)
Definition: cpi.c:23
static int no_str_arg(char *arg)
static void print_help(char **argv)
void exit()
int i
Definition: fileop.c:140
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_event_qualifiers()

static int parse_event_qualifiers ( PAPI_event_info_t info)
static

Definition at line 320 of file papi_native_avail.c.

321 {
322  char *pmask,*ptr;
323 
324  /* handle the PAPI component-style events which have a component:::event type */
325  if ((ptr=strstr(info->symbol, ":::"))) {
326  ptr+=3;
327  /* handle libpfm4-style events which have a pmu::event type event name */
328  } else if ((ptr=strstr(info->symbol, "::"))) {
329  ptr+=2;
330  }
331  else {
332  ptr=info->symbol;
333  }
334 
335  if ( ( pmask = strchr( ptr, ':' ) ) == NULL ) {
336  return ( 0 );
337  }
338  memmove( info->symbol, pmask, ( strlen(pmask) + 1 ) * sizeof(char) );
339 
340  // The description field contains the event description followed by a tag 'masks:'
341  // and then the mask description (if there was a mask with this event). The following
342  // code isolates the mask description part of this information.
343 
344  pmask = strstr( info->long_descr, "masks:" );
345  if ( pmask == NULL ) {
346  info->long_descr[0] = 0;
347  } else {
348  pmask += 6; // bump pointer past 'masks:' identifier in description
349  memmove( info->long_descr, pmask, (strlen(pmask) + 1) * sizeof(char) );
350  }
351  return ( 1 );
352 }
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
Here is the caller graph for this function:

◆ print_event_output()

static void print_event_output ( int  val_flag)
static

Definition at line 290 of file papi_native_avail.c.

291 {
292  // first we need to update the available flag at the beginning of the buffer
293  // this needs to reflect if this event name by itself or the event name with one of the qualifiers worked
294  // if none of the combinations worked then we will show the event as not available
295  char *val_flag_ptr = strstr(event_output_buffer, "<-->");
296  if (val_flag_ptr != NULL) {
297  if ((val_flag) && (event_available == 0)) {
298  // event is not available, update the place holder (replace the <--> with <NA>)
299  *(val_flag_ptr+1) = 'N';
300  *(val_flag_ptr+2) = 'A';
301  } else {
302  event_available = 0; // reset this flag for next event
303  // event is available, just remove the place holder (replace the <--> with spaces)
304  *val_flag_ptr = ' ';
305  *(val_flag_ptr+1) = ' ';
306  *(val_flag_ptr+2) = ' ';
307  *(val_flag_ptr+3) = ' ';
308  }
309  }
310 
311  // now we can finally send this events output to the user
312  printf( "%s", event_output_buffer);
313 // printf( "--------------------------------------------------------------------------------\n" );
314 
315  event_output_buffer[0] = '\0'; // start the next event with an empty buffer
316  return;
317 }
unsigned int event_available
char * event_output_buffer
Here is the caller graph for this function:

◆ print_help()

static void print_help ( char **  argv)
static

Definition at line 74 of file papi_native_avail.c.

75 {
76  printf( "This is the PAPI native avail program.\n" );
77  printf( "It provides availability and details about PAPI Native Events.\n" );
78  printf( "Usage: %s [options]\n", argv[0] );
79  printf( "Options:\n\n" );
80  printf( "\nGeneral command options:\n" );
81  printf( "\t-h, --help print this help message\n" );
82  printf( "\t-c, --check attempts to add each event\n");
83  printf( "\t-e EVENTNAME display detailed information about named native event\n" );
84  printf( "\t-i EVENTSTR include only event names that contain EVENTSTR\n" );
85  printf( "\t-x EVENTSTR exclude any event names that contain EVENTSTR\n" );
86  printf( "\t--noqual suppress display of event qualifiers (mask and flag) information\n" );
87  printf( "\nProcessor-specific options:\n");
88  printf( "\t--darr display events supporting Data Address Range Restriction\n" );
89  printf( "\t--dear display Data Event Address Register events only\n" );
90  printf( "\t--iarr display events supporting Instruction Address Range Restriction\n" );
91  printf( "\t--iear display Instruction Event Address Register events only\n" );
92  printf( "\t--opcm display events supporting OpCode Matching\n" );
93  printf( "\t--nogroups suppress display of Event grouping information\n" );
94  printf( "\n" );
95 }
Here is the caller graph for this function:

◆ space_pad()

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

Definition at line 170 of file papi_native_avail.c.

171 {
172  while ( spaces-- > 0 )
173  strcat( str, " " );
174 }
Here is the caller graph for this function:

Variable Documentation

◆ event_available

unsigned int event_available = 0

Definition at line 176 of file papi_native_avail.c.

◆ event_output_buffer

char* event_output_buffer = NULL

Definition at line 178 of file papi_native_avail.c.

◆ event_output_buffer_size

unsigned int event_output_buffer_size = 0

Definition at line 177 of file papi_native_avail.c.