PAPI  5.7.0.0
papi_internal.c
Go to the documentation of this file.
1 /****************************/
2 /* THIS IS OPEN SOURCE CODE */
3 /****************************/
4 
5 /*
6 * File: papi_internal.c
7 *
8 * Author: Philip Mucci
9 * mucci@cs.utk.edu
10 * Mods: dan terpstra
11 * terpstra@cs.utk.edu
12 * Mods: Min Zhou
13 * min@cs.utk.edu
14 * Mods: Kevin London
15 * london@cs.utk.edu
16 * Mods: Per Ekman
17 * pek@pdc.kth.se
18 * Mods: Haihang You
19 * you@cs.utk.edu
20 * Mods: Maynard Johnson
21 * maynardj@us.ibm.com
22 * Mods: Brian Sheely
23 * bsheely@eecs.utk.edu
24 * Mods: <Gary Mohr>
25 * <gary.mohr@bull.com>
26 * Mods: <your name here>
27 * <your email address>
28 */
29 
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <assert.h>
36 
37 #include "papi.h"
38 #include "papi_internal.h"
39 #include "papi_vector.h"
40 #include "papi_memory.h"
41 #include "sw_multiplex.h"
42 #include "extras.h"
43 #include "papi_preset.h"
44 #include "cpus.h"
45 
46 #include "papi_common_strings.h"
47 
48 /* Advanced definitons */
49 static int default_debug_handler( int errorCode );
50 static long long handle_derived( EventInfo_t * evi, long long *from );
51 
52 /* Global definitions used by other files */
61 
62 /*****************************/
63 /* Native Event Mapping Code */
64 /*****************************/
65 
66 #define NATIVE_EVENT_CHUNKSIZE 1024
67 
69  int cidx;
71  int ntv_idx;
72  char *evt_name;
73 };
74 
75 
76 // The following array is indexed by the papi event code (after the native bit has been removed)
78 static int num_native_events=0;
79 static int num_native_chunks=0;
80 
81 char **_papi_errlist= NULL;
82 static int num_error_chunks = 0;
83 
84 
85 // pointer to event:mask string associated with last enum call to a components
86 // will be NULL for non libpfm4 components
87 // this is needed because libpfm4 event codes and papi event codes do not contain mask information
88 char *papi_event_string = NULL;
89 void
90 _papi_hwi_set_papi_event_string (const char *event_string) {
91  INTDBG("event_string: %s\n", event_string);
92  if (papi_event_string != NULL) {
93  free (papi_event_string);
94  papi_event_string = NULL;
95  }
96  if (event_string != NULL) {
97  papi_event_string = strdup(event_string);
98  }
99  return;
100 }
101 char *
103  INTDBG("papi_event_string: %s\n", papi_event_string);
104  return papi_event_string;
105 }
106 void
108  if (papi_event_string != NULL) {
109  free(papi_event_string);
110  papi_event_string = NULL;
111  }
112  return;
113 }
114 // A place to keep the current papi event code so some component functions can fetch its value
115 // The current event code can be stored here prior to component calls and cleared after the component returns
116 static unsigned int papi_event_code = -1;
117 static int papi_event_code_changed = -1;
118 void
119 _papi_hwi_set_papi_event_code (unsigned int event_code, int update_flag) {
120  INTDBG("new event_code: %#x, update_flag: %d, previous event_code: %#x\n", event_code, update_flag, papi_event_code);
121 
122  // if call is just to reset and start over, set both flags to show nothing saved yet
123  if (update_flag < 0) {
125  papi_event_code = -1;
126  return;
127  }
128 
129  // if 0, it is being set prior to calling a component, if >0 it is being changed by the component
130  papi_event_code_changed = update_flag;
131  // save the event code passed in
132  papi_event_code = event_code;
133  return;
134 }
135 unsigned int
137  INTDBG("papi_event_code: %#x\n", papi_event_code);
138  return papi_event_code;
139 }
140 /* Get the index into the ESI->NativeInfoArray for the current PAPI event code */
141 int
142 _papi_hwi_get_ntv_idx (unsigned int papi_evt_code) {
143  INTDBG("ENTER: papi_evt_code: %#x\n", papi_evt_code);
144 
145  int result;
146  int event_index;
147 
148  if (papi_evt_code == 0) {
149  INTDBG("EXIT: PAPI_ENOEVNT, invalid papi event code\n");
150  return PAPI_ENOEVNT;
151  }
152 
153  event_index=papi_evt_code&PAPI_NATIVE_AND_MASK;
154  if ((event_index<0) || (event_index>=num_native_events)) {
155  INTDBG("EXIT: PAPI_ENOEVNT, invalid index into native event array\n");
156  return PAPI_ENOEVNT;
157  }
158 
159  result=_papi_native_events[event_index].ntv_idx;
160 
161  INTDBG("EXIT: result: %d\n", result);
162  return result;
163 }
164 
165 //
166 // Check for the presence of a component name or pmu name in the event string.
167 // If found check if it matches this component or one of the pmu's supported by this component.
168 //
169 // returns true if the event could be for this component and false if it is not for this component.
170 // if there is no component or pmu name then it could be for this component and returns true.
171 //
172 static int
174  INTDBG("ENTER: cidx: %d, event_name: %s\n", cidx, event_name);
175  int i;
176  int component_name = 0;
177  int pmu_name = 0;
178  char *wptr = NULL;
179 
180  // if event does not have a component name or pmu name, return to show it could be supported by this component
181  // when component and pmu names are not provided, we just have to call the components to see if they recognize the event
182  //
183 
184  // look for component names first
185  if ((wptr = strstr(event_name, ":::")) != NULL) {
186  component_name = 1;
187  } else if ((wptr = strstr(event_name, "::")) != NULL) {
188  pmu_name = 1;
189  } else {
190  INTDBG("EXIT: No Component or PMU name in event string, try this component\n");
191  // need to force all components to be called to find owner of this event
192  // ???? can we assume the default pmu when no component or pmu name is provided ????
193  return 1;
194  }
195 
196  // get a temporary copy of the component or pmu name
197  int name_len = wptr - event_name;
198  wptr = strdup(event_name);
199  wptr[name_len] = '\0';
200 
201  // if a component name was found, compare it to the component name in the component info structure
202  if (component_name) {
203 // INTDBG("component_name: %s\n", _papi_hwd[cidx]->cmp_info.name);
204  if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.name) == 0) {
205  free (wptr);
206  INTDBG("EXIT: Component %s supports this event\n", _papi_hwd[cidx]->cmp_info.name);
207  return 1;
208  }
209  }
210 
211  // if a pmu name was found, compare it to the pmu name list if the component info structure (if there is one)
212  if (pmu_name) {
213  for ( i=0 ; i<PAPI_PMU_MAX ; i++) {
214  if (_papi_hwd[cidx]->cmp_info.pmu_names[i] == NULL) {
215  continue;
216  }
217 // INTDBG("pmu_name[%d]: %p (%s)\n", i, _papi_hwd[cidx]->cmp_info.pmu_names[i], _papi_hwd[cidx]->cmp_info.pmu_names[i]);
218  if (strcmp (wptr, _papi_hwd[cidx]->cmp_info.pmu_names[i]) == 0) {
219  INTDBG("EXIT: Component %s supports PMU %s and this event\n", _papi_hwd[cidx]->cmp_info.name, wptr);
220  free (wptr);
221  return 1;
222  }
223  }
224  }
225 
226  free (wptr);
227  INTDBG("EXIT: Component does not support this event\n");
228  return 0;
229 }
230 
243 int
244 _papi_hwi_prefix_component_name( char *component_name, char *event_name, char *out, int out_len)
245 {
246  int size1, size2;
247  char temp[out_len];
248 
249  size1 = strlen(event_name);
250  size2 = strlen(component_name);
251 
252 /* sanity checks */
253  if ( size1 == 0 ) {
254  return (PAPI_EBUG); /* hopefully event_name always has length?! */
255  }
256 
257  if ( size1 >= out_len )
258  return (PAPI_ENOMEM);
259 
260 /* Guard against event_name == out */
261  memcpy( temp, event_name, out_len );
262 
263 /* no component name to prefix */
264  if ( size2 == 0 ) {
265  sprintf(out, "%s%c", temp, '\0' );
266  return (PAPI_OK);
267  }
268 
269 /* Don't prefix 'cpu' component names for now */
270  if ( strstr(component_name, "pe") ||
271  strstr(component_name, "bgq") ||
272  strstr(component_name, "bgp") ) {
273  sprintf( out, "%s%c", temp, '\0');
274  return (PAPI_OK);
275  }
276 
277 /* strlen(component_name) + ::: + strlen(event_name) + NULL */
278  if ( size1+size2+3+1 > out_len )
279  return (PAPI_ENOMEM);
280 
281  sprintf( out, "%s:::%s%c" , component_name, temp, '\0');
282  return (PAPI_OK);
283 }
284 
296 {
297  const char *start = NULL;
298 /* We assume ::: is the seperator
299  * eg:
300  * papi_component:::event_name
301  */
302 
303  start = strstr( event_name, ":::" );
304  if ( start != NULL )
305  start+= 3; /* return the actual start of event_name */
306  else
307  start = event_name;
308 
309  return (start);
310 }
311 
312 /* find the papi event code (4000xxx) associated with the specified component, native event, and event name */
313 static int
314 _papi_hwi_find_native_event(int cidx, int event, const char *event_name) {
315  INTDBG("ENTER: cidx: %x, event: %#x, event_name: %s\n", cidx, event, event_name);
316 
317  int i;
318 
319  // if no event name passed in, it can not be found
320  if (event_name == NULL) {
321  INTDBG("EXIT: PAPI_ENOEVNT\n");
322  return PAPI_ENOEVNT;
323  }
324 
325  for(i=0;i<num_native_events;i++) {
326  // if we have have not set up this event name yet, look at next
327  if (_papi_native_events[i].evt_name == NULL) {
328  continue;
329  }
330 
331  // is this entry for the correct component and event code
332  if ((_papi_native_events[i].cidx==cidx) &&
334  // if this event name matches what we want, return its papi event code
335  if (strcmp(event_name, _papi_native_events[i].evt_name) == 0) {
336  INTDBG("EXIT: event: %#x, component_event: %#x, ntv_idx: %d, event_name: %s\n",
338  return i|PAPI_NATIVE_MASK;
339  }
340  }
341  }
342 
343  INTDBG("EXIT: PAPI_ENOEVNT\n");
344  return PAPI_ENOEVNT;
345 }
346 
347 static int
348 _papi_hwi_add_native_event(int cidx, int ntv_event, int ntv_idx, const char *event_name) {
349  INTDBG("ENTER: cidx: %d, ntv_event: %#x, ntv_idx: %d, event_name: %s\n", cidx, ntv_event, ntv_idx, event_name);
350 
351  int new_native_event;
352 
354 
359  sizeof(struct native_event_info));
360  if (_papi_native_events==NULL) {
361  new_native_event=PAPI_ENOMEM;
362  goto native_alloc_early_out;
363  }
364  }
365 
369  if (event_name != NULL) {
371  } else {
373  }
374  new_native_event=num_native_events|PAPI_NATIVE_MASK;
375 
377 
378 native_alloc_early_out:
379 
381 
382  INTDBG("EXIT: new_native_event: %#x, num_native_events: %d\n", new_native_event, num_native_events);
383  return new_native_event;
384 }
385 
392 static int
393 _papi_hwi_add_error( char *error )
394 {
395  INTDBG("Adding a new Error message |%s|\n", error);
397 
400  _papi_errlist= (char **) realloc(_papi_errlist,
402  if (_papi_errlist==NULL) {
404  goto bail;
405  }
406 
407  }
408 
409  _papi_errlist[_papi_hwi_num_errors] = strdup( error );
410  if ( _papi_errlist[_papi_hwi_num_errors] == NULL )
412 
413 bail:
415 
416  return _papi_hwi_num_errors++;
417 }
418 
419 static void
421 {
422  int i;
423 
424  if ( _papi_errlist == NULL ||
425  _papi_hwi_num_errors == 0 )
426  return;
427 
428 
430  for (i=0; i < _papi_hwi_num_errors; i++ ) {
431  free( _papi_errlist[i]);
432  _papi_errlist[i] = NULL;
433  }
434 
435  free( _papi_errlist );
436  _papi_errlist = NULL;
439 
441 }
442 
443 static int
445 {
446  int i;
447 
448  for (i=0; i<_papi_hwi_num_errors; i++) {
449  if ( !strncasecmp( _papi_errlist[i], error, strlen( error ) ) )
450  return i;
451  }
452 
453  return (-1);
454 }
455 
466 int _papi_hwi_publish_error( char *error )
467 {
468  int error_code = -1;
469 
470  if ( (error_code = _papi_hwi_lookup_error( error )) < 0 )
471  error_code = _papi_hwi_add_error(error);
472 
473  return (-error_code); /* internally error_code is an index, externally, it should be <= 0 */
474 }
475 
476 
477 /* Why are the errors done this way?
478  Should they not be auto-generated the same way the Fortran ones are?
479  --vmw
480 */
481 void
483 /* we use add error to avoid the cost of lookups, we know the errors are not there yet */
484  /* 0 PAPI_OK */ _papi_hwi_add_error("No error");
485  /* 1 PAPI_EINVAL */ _papi_hwi_add_error("Invalid argument");
486  /* 2 PAPI_ENOMEM */ _papi_hwi_add_error("Insufficient memory");
487  /* 3 PAPI_ESYS */ _papi_hwi_add_error("A System/C library call failed");
488  /* 4 PAPI_ECMP */ _papi_hwi_add_error("Not supported by component");
489  /* 5 PAPI_ECLOST */ _papi_hwi_add_error("Access to the counters was lost or interrupted");
490  /* 6 PAPI_EBUG */ _papi_hwi_add_error("Internal error, please send mail to the developers");
491  /* 7 PAPI_ENOEVNT */ _papi_hwi_add_error("Event does not exist");
492  /* 8 PAPI_ECNFLCT */ _papi_hwi_add_error("Event exists, but cannot be counted due to hardware resource limits");
493  /* 9 PAPI_ENOTRUN */ _papi_hwi_add_error("EventSet is currently not running");
494  /* 10 PAPI_EISRUN */ _papi_hwi_add_error("EventSet is currently counting");
495  /* 11 PAPI_ENOEVST */ _papi_hwi_add_error("No such EventSet available");
496  /* 12 PAPI_ENOTPRESET */_papi_hwi_add_error("Event in argument is not a valid preset");
497  /* 13 PAPI_ENOCNTR */ _papi_hwi_add_error("Hardware does not support performance counters");
498  /* 14 PAPI_EMISC */ _papi_hwi_add_error("Unknown error code");
499  /* 15 PAPI_EPERM */ _papi_hwi_add_error("Permission level does not permit operation");
500  /* 16 PAPI_ENOINIT */ _papi_hwi_add_error("PAPI hasn't been initialized yet");
501  /* 17 PAPI_ENOCMP */ _papi_hwi_add_error("Component Index isn't set");
502  /* 18 PAPI_ENOSUPP */ _papi_hwi_add_error("Not supported");
503  /* 19 PAPI_ENOIMPL */ _papi_hwi_add_error("Not implemented");
504  /* 20 PAPI_EBUF */ _papi_hwi_add_error("Buffer size exceeded");
505  /* 21 PAPI_EINVAL_DOM */_papi_hwi_add_error("EventSet domain is not supported for the operation");
506  /* 22 PAPI_EATTR */ _papi_hwi_add_error("Invalid or missing event attributes");
507  /* 23 PAPI_ECOUNT */ _papi_hwi_add_error("Too many events or attributes");
508  /* 24 PAPI_ECOMBO */ _papi_hwi_add_error("Bad combination of features");
509  /* 25 PAPI_ECMP_DISABLED */_papi_hwi_add_error("Component containing event is disabled");
510 }
511 
512 int
514 {
515  return ( cidx < 0 || cidx >= papi_num_components );
516 }
517 
518 
519 int
520 _papi_hwi_component_index( int event_code ) {
521  INTDBG("ENTER: event_code: %#x\n", event_code);
522 
523  int cidx;
524  int event_index;
525 
526  /* currently assume presets are for component 0 only */
527  if (IS_PRESET(event_code)) {
528  INTDBG("EXIT: Event %#x is a PRESET, assigning component %d\n", event_code,0);
529  return 0;
530  }
531 
532  /* user defined events are treated like preset events (component 0 only) */
533  if (IS_USER_DEFINED(event_code)) {
534  INTDBG("EXIT: Event %#x is USER DEFINED, assigning component %d\n", event_code,0);
535  return 0;
536  }
537 
538  event_index=event_code&PAPI_NATIVE_AND_MASK;
539 
540  if ( (event_index < 0) || (event_index>=num_native_events)) {
541  INTDBG("EXIT: Event index %#x is out of range, num_native_events: %d\n", event_index, num_native_events);
542  return PAPI_ENOEVNT;
543  }
544 
545  cidx=_papi_native_events[event_index].cidx;
546 
547  if ((cidx<0) || (cidx >= papi_num_components)) {
548  INTDBG("EXIT: Component index %#x is out of range, papi_num_components: %d\n", cidx, papi_num_components);
549  return PAPI_ENOCMP;
550  }
551 
552  INTDBG("EXIT: Found cidx: %d event_index: %d, event_code: %#x\n", cidx, event_index, event_code);
553  return cidx;
554 }
555 
556 /* Convert an internal component event to a papi event code */
557 int
558 _papi_hwi_native_to_eventcode(int cidx, int event_code, int ntv_idx, const char *event_name) {
559  INTDBG("Entry: cidx: %d, event: %#x, ntv_idx: %d, event_name: %s\n", cidx, event_code, ntv_idx, event_name);
560 
561  int result;
562 
563  if (papi_event_code_changed > 0) {
565  INTDBG("EXIT: papi_event_code: %#x set by the component\n", result);
566  return result;
567  }
568 
569  result=_papi_hwi_find_native_event(cidx, event_code, event_name);
570  if (result==PAPI_ENOEVNT) {
571  // Need to create one
572  result=_papi_hwi_add_native_event(cidx, event_code, ntv_idx, event_name);
573  }
574 
575  INTDBG("EXIT: result: %#x\n", result);
576  return result;
577 }
578 
579 /* Convert a native_event code to an internal event code */
580 int
582  INTDBG("ENTER: event_code: %#x\n", event_code);
583 
584  int result;
585  int event_index;
586 
587  event_index=event_code&PAPI_NATIVE_AND_MASK;
588  if ((event_index < 0) || (event_index>=num_native_events)) {
589  INTDBG("EXIT: PAPI_ENOEVNT\n");
590  return PAPI_ENOEVNT;
591  }
592 
593  result=_papi_native_events[event_index].component_event;
594 
595  INTDBG("EXIT: result: %#x\n", result);
596  return result;
597 
598 }
599 
600 
601 /*********************/
602 /* Utility functions */
603 /*********************/
604 
605 void
606 PAPIERROR( char *format, ... )
607 {
608  va_list args;
609  if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
610  ( getenv( "PAPI_VERBOSE" ) ) ) {
611  va_start( args, format );
612  fprintf( stderr, "PAPI Error: " );
613  vfprintf( stderr, format, args );
614  fprintf( stderr, "\n" );
615  va_end( args );
616  }
617 }
618 
619 void
620 PAPIWARN( char *format, ... )
621 {
622  va_list args;
623  if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
624  ( getenv( "PAPI_VERBOSE" ) ) ) {
625  va_start( args, format );
626  fprintf( stderr, "PAPI Warning: " );
627  vfprintf( stderr, format, args );
628  fprintf( stderr, "\n" );
629  va_end( args );
630  }
631 }
632 
633 static int
634 default_debug_handler( int errorCode )
635 {
636  char str[PAPI_HUGE_STR_LEN];
637 
638  if ( errorCode == PAPI_OK )
639  return ( errorCode );
640  if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) {
641  PAPIERROR( "%s %d,%s,Bug! Unknown error code", PAPI_ERROR_CODE_str,
642  errorCode, "" );
643  return ( PAPI_EBUG );
644  }
645 
646  switch ( _papi_hwi_error_level ) {
647  case PAPI_VERB_ECONT:
648  case PAPI_VERB_ESTOP:
649  /* gcc 2.96 bug fix, do not change */
650  /* fprintf(stderr,"%s %d: %s: %s\n",PAPI_ERROR_CODE_str,errorCode,_papi_hwi_err[-errorCode].name,_papi_hwi_err[-errorCode].descr); */
651 
652  sprintf( str, "%s %d,%s", PAPI_ERROR_CODE_str, errorCode,
653  _papi_errlist[-errorCode] );
654  if ( errorCode == PAPI_ESYS )
655  sprintf( str + strlen( str ), ": %s", strerror( errno ) );
656 
657  PAPIERROR( str );
658 
660  abort( ); /* patch provided by will cohen of redhat */
661  else
662  return errorCode;
663  break;
664 
665  case PAPI_QUIET:
666  default:
667  return errorCode;
668  }
669  return ( PAPI_EBUG ); /* Never get here */
670 }
671 
672 static int
674 {
675  /* Allocate and clear the Dynamic Array structure */
676  if ( map->dataSlotArray != NULL )
677  papi_free( map->dataSlotArray );
678  memset( map, 0x00, sizeof ( DynamicArray_t ) );
679 
680  /* Allocate space for the EventSetInfo_t pointers */
681 
682  map->dataSlotArray =
684  sizeof ( EventSetInfo_t * ) );
685  if ( map->dataSlotArray == NULL ) {
686  return ( PAPI_ENOMEM );
687  }
688  memset( map->dataSlotArray, 0x00,
689  PAPI_INIT_SLOTS * sizeof ( EventSetInfo_t * ) );
692  map->fullSlots = 0;
693 
694  return ( PAPI_OK );
695 }
696 
697 static int
699 {
700  int number;
701  EventSetInfo_t **n;
702 
703  /*realloc existing PAPI_EVENTSET_MAP.dataSlotArray */
704 
705  number = DA->totalSlots * 2;
706  n = ( EventSetInfo_t ** ) papi_realloc( DA->dataSlotArray,
707  ( size_t ) number *
708  sizeof ( EventSetInfo_t * ) );
709  if ( n == NULL )
710  return ( PAPI_ENOMEM );
711 
712  /* Need to assign this value, what if realloc moved it? */
713 
714  DA->dataSlotArray = n;
715 
716  memset( DA->dataSlotArray + DA->totalSlots, 0x00,
717  ( size_t ) DA->totalSlots * sizeof ( EventSetInfo_t * ) );
718 
719  DA->totalSlots = number;
720  DA->availSlots = number - DA->fullSlots;
721 
722  return ( PAPI_OK );
723 }
724 
725 static int
727 {
728  return ( _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs );
729 }
730 
731 
732 
733 
734 
735 /*========================================================================*/
736 /* This function allocates space for one EventSetInfo_t structure and for */
737 /* all of the pointers in this structure. If any malloc in this function */
738 /* fails, all memory malloced to the point of failure is freed, and NULL */
739 /* is returned. Upon success, a pointer to the EventSetInfo_t data */
740 /* structure is returned. */
741 /*========================================================================*/
742 
743 
744 static int
746 {
747  EventSetInfo_t *ESI;
748 
749  ESI = ( EventSetInfo_t * ) papi_calloc( 1, sizeof ( EventSetInfo_t ) );
750  if ( ESI == NULL ) {
751  return PAPI_ENOMEM;
752  }
753 
754  *here = ESI;
755 
756  return PAPI_OK;
757 }
758 
759 int
761 {
762  INTDBG("ENTER: ESI: %p (%d), cidx: %d\n", ESI, ESI->EventSetIndex, cidx);
763  int retval;
764  size_t max_counters;
765  char *ptr;
766  unsigned int i, j;
767 
768  /* If component doesn't exist... */
769  if (_papi_hwi_invalid_cmp(cidx)) return PAPI_ECMP;
770 
771  /* Assigned at create time */
772  ESI->domain.domain = _papi_hwd[cidx]->cmp_info.default_domain;
773  ESI->granularity.granularity =
774  _papi_hwd[cidx]->cmp_info.default_granularity;
775  ESI->CmpIdx = cidx;
776 
777  /* ??? */
778  max_counters = ( size_t ) _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
779 
780  ESI->ctl_state = (hwd_control_state_t *) papi_calloc( 1, (size_t)
781  _papi_hwd[cidx]->size.control_state );
782  ESI->sw_stop = (long long *) papi_calloc( ( size_t ) max_counters,
783  sizeof ( long long ) );
784  ESI->hw_start = ( long long * ) papi_calloc( ( size_t ) max_counters,
785  sizeof ( long long ) );
786  ESI->EventInfoArray = ( EventInfo_t * ) papi_calloc( (size_t) max_counters,
787  sizeof ( EventInfo_t ) );
788 
789  /* allocate room for the native events and for the component-private */
790  /* register structures */
791  /* ugh is there a cleaner way to allocate this? vmw */
792  ESI->NativeInfoArray = ( NativeInfo_t * )
793  papi_calloc( ( size_t ) max_counters, sizeof ( NativeInfo_t ));
794 
795  ESI->NativeBits = papi_calloc(( size_t ) max_counters,
796  ( size_t ) _papi_hwd[cidx]->size.reg_value );
797 
798  /* NOTE: the next two malloc allocate blocks of memory that are later */
799  /* parcelled into overflow and profile arrays */
800  ESI->overflow.deadline = ( long long * )
801  papi_malloc( ( sizeof ( long long ) +
802  sizeof ( int ) * 3 ) * ( size_t ) max_counters );
803 
804  ESI->profile.prof = ( PAPI_sprofil_t ** )
805  papi_malloc( ( sizeof ( PAPI_sprofil_t * ) * ( size_t ) max_counters +
806  ( size_t ) max_counters * sizeof ( int ) * 4 ) );
807 
808  /* If any of these allocations failed, free things up and fail */
809 
810  if ( ( ESI->ctl_state == NULL ) ||
811  ( ESI->sw_stop == NULL ) ||
812  ( ESI->hw_start == NULL ) ||
813  ( ESI->NativeInfoArray == NULL ) ||
814  ( ESI->NativeBits == NULL ) ||
815  ( ESI->EventInfoArray == NULL ) ||
816  ( ESI->profile.prof == NULL ) ||
817  ( ESI->overflow.deadline == NULL ) ) {
818 
819  if ( ESI->sw_stop ) papi_free( ESI->sw_stop );
820  if ( ESI->hw_start ) papi_free( ESI->hw_start );
821  if ( ESI->EventInfoArray ) papi_free( ESI->EventInfoArray );
822  if ( ESI->NativeInfoArray ) papi_free( ESI->NativeInfoArray );
823  if ( ESI->NativeBits ) papi_free( ESI->NativeBits );
824  if ( ESI->ctl_state ) papi_free( ESI->ctl_state );
825  if ( ESI->overflow.deadline ) papi_free( ESI->overflow.deadline );
826  if ( ESI->profile.prof ) papi_free( ESI->profile.prof );
827  papi_free( ESI );
828  return PAPI_ENOMEM;
829  }
830 
831 
832  /* Carve up the overflow block into separate arrays */
833  ptr = ( char * ) ESI->overflow.deadline;
834  ptr += sizeof ( long long ) * max_counters;
835  ESI->overflow.threshold = ( int * ) ptr;
836  ptr += sizeof ( int ) * max_counters;
837  ESI->overflow.EventIndex = ( int * ) ptr;
838  ptr += sizeof ( int ) * max_counters;
839  ESI->overflow.EventCode = ( int * ) ptr;
840 
841  /* Carve up the profile block into separate arrays */
842  ptr = ( char * ) ESI->profile.prof +
843  ( sizeof ( PAPI_sprofil_t * ) * max_counters );
844  ESI->profile.count = ( int * ) ptr;
845  ptr += sizeof ( int ) * max_counters;
846  ESI->profile.threshold = ( int * ) ptr;
847  ptr += sizeof ( int ) * max_counters;
848  ESI->profile.EventIndex = ( int * ) ptr;
849  ptr += sizeof ( int ) * max_counters;
850  ESI->profile.EventCode = ( int * ) ptr;
851 
852  /* initialize_EventInfoArray */
853 
854  for ( i = 0; i < max_counters; i++ ) {
855  ESI->EventInfoArray[i].event_code=( unsigned int ) PAPI_NULL;
856  ESI->EventInfoArray[i].ops = NULL;
858  for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
859  ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
860  }
861  }
862 
863  /* initialize_NativeInfoArray */
864  for( i = 0; i < max_counters; i++ ) {
865  ESI->NativeInfoArray[i].ni_event = -1;
866  ESI->NativeInfoArray[i].ni_position = -1;
867  ESI->NativeInfoArray[i].ni_papi_code = -1;
868  ESI->NativeInfoArray[i].ni_owners = 0;
869  ESI->NativeInfoArray[i].ni_bits = ((unsigned char*)ESI->NativeBits) +
870  (i*_papi_hwd[cidx]->size.reg_value);
871  }
872 
873  ESI->NativeCount = 0;
874 
875  ESI->state = PAPI_STOPPED;
876 
877  /* these used to be init_config */
878  retval = _papi_hwd[cidx]->init_control_state( ESI->ctl_state );
879  retval |= _papi_hwd[cidx]->set_domain( ESI->ctl_state, ESI->domain.domain);
880 
881  return retval;
882 }
883 
884 /*========================================================================*/
885 /* This function should free memory for one EventSetInfo_t structure. */
886 /* The argument list consists of a pointer to the EventSetInfo_t */
887 /* structure, *ESI. */
888 /* The calling function should check for ESI==NULL. */
889 /*========================================================================*/
890 
891 void
893 {
895 
896 #ifdef DEBUG
897  memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
898 #endif
899  papi_free( ESI );
900 
901 }
902 
903 static int
905 {
907  int i, errorCode;
908 
910 
911  if ( map->availSlots == 0 ) {
912  errorCode = expand_dynamic_array( map );
913  if ( errorCode < PAPI_OK ) {
915  return ( errorCode );
916  }
917  }
918 
919  i = 0;
920  for ( i = 0; i < map->totalSlots; i++ ) {
921  if ( map->dataSlotArray[i] == NULL ) {
922  ESI->master = master;
923  ESI->EventSetIndex = i;
924  map->fullSlots++;
925  map->availSlots--;
926  map->dataSlotArray[i] = ESI;
928  return ( PAPI_OK );
929  }
930  }
931 
933  return ( PAPI_EBUG );
934 }
935 
936 int
938 {
939  EventSetInfo_t *ESI;
940  int retval;
941 
942  /* Is the EventSet already in existence? */
943 
944  if ( ( EventSet == NULL ) || ( handle == NULL ) )
945  return PAPI_EINVAL;
946 
947  if ( *EventSet != PAPI_NULL )
948  return PAPI_EINVAL;
949 
950  /* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
951 
952  retval = create_EventSet( &ESI );
953  if ( retval != PAPI_OK )
954  return retval;
955 
956  ESI->CmpIdx = -1; /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
957  ESI->state = PAPI_STOPPED;
958 
959  /* Add it to the global table */
960 
961  retval = add_EventSet( ESI, handle );
962  if ( retval < PAPI_OK ) {
964  return retval ;
965  }
966 
967  *EventSet = ESI->EventSetIndex;
968 
969  INTDBG( "(%p,%p): new EventSet in slot %d\n",
970  ( void * ) EventSet, handle, *EventSet );
971 
972  return retval;
973 }
974 
975 /* This function returns the index of the the next free slot
976  in the EventInfoArray. If EventCode is already in the list,
977  it returns PAPI_ECNFLCT. */
978 
979 static int
980 get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
981 {
982  int k;
983  int lowslot = PAPI_ECNFLCT;
984  int limit = EventInfoArrayLength( ESI );
985 
986  /* Check for duplicate events and get the lowest empty slot */
987 
988  for ( k = 0; k < limit; k++ ) {
989  if ( ESI->EventInfoArray[k].event_code == EventCode )
990  return ( PAPI_ECNFLCT );
991  /*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
992  if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
993  lowslot = k;
994  break;
995  }
996  }
997  return ( lowslot );
998 }
999 
1000 /* This function returns the index of the EventCode or error */
1001 /* Index to what? The index to everything stored EventCode in the */
1002 /* EventSet. */
1003 
1004 int
1006  unsigned int EventCode )
1007 {
1008  int i;
1009  int limit = EventInfoArrayLength( ESI );
1010 
1011  for ( i = 0; i < limit; i++ ) {
1012  if ( ESI->EventInfoArray[i].event_code == EventCode ) {
1013  return i;
1014  }
1015  }
1016 
1017  return PAPI_EINVAL;
1018 }
1019 
1020 /* This function only removes empty EventSets */
1021 
1022 int
1024 {
1026  int i;
1027 
1028  i = ESI->EventSetIndex;
1029 
1031 
1032  _papi_hwi_free_EventSet( ESI );
1033 
1034  /* do bookkeeping for PAPI_EVENTSET_MAP */
1035 
1036  map->dataSlotArray[i] = NULL;
1037  map->availSlots++;
1038  map->fullSlots--;
1039 
1041 
1042  return PAPI_OK;
1043 }
1044 
1045 
1046 /* this function checks if an event is already in an EventSet
1047  Success, return ESI->NativeInfoArray[] index
1048  Fail, return PAPI_ENOEVNT;
1049 */
1050 static int
1052 {
1053  INTDBG( "ENTER: ESI: %p, papi_event: %#x\n", ESI, papi_event);
1054  int i;
1055 
1056  int nevt = _papi_hwi_eventcode_to_native(papi_event);
1057 
1058  /* to find the native event from the native events list */
1059  for( i = 0; i < ESI->NativeCount; i++ ) {
1060  if ( nevt == ESI->NativeInfoArray[i].ni_event ) {
1061  // Also need to check papi event code if set because the same event with different masks
1062  // will generate the same libpfm4 event code (what was checked above). But there will be
1063  // different papi events created for it and they need to be handled separately.
1064  if (papi_event == ESI->NativeInfoArray[i].ni_papi_code) {
1065  INTDBG( "EXIT: event: %#x already mapped at index: %d\n", papi_event, i);
1066  return i;
1067  }
1068  }
1069  }
1070  INTDBG( "EXIT: PAPI_ENOEVNT\n");
1071  return PAPI_ENOEVNT;
1072 }
1073 
1074 /* This function goes through the events in an EventSet's EventInfoArray */
1075 /* And maps each event (whether native or part of a preset) to */
1076 /* an event in the EventSets NativeInfoArray. */
1077 
1078 /* We need to do this every time a native event is added to or removed */
1079 /* from an eventset. */
1080 
1081 /* It is also called after a update controlstate as the components are */
1082 /* allowed to re-arrange the native events to fit hardware constraints. */
1083 
1084 void
1086 {
1087  INTDBG("ENTER: ESI: %p, ESI->EventInfoArray: %p, ESI->NativeInfoArray: %p, ESI->NumberOfEvents: %d, ESI->NativeCount: %d\n", ESI, ESI->EventInfoArray, ESI->NativeInfoArray, ESI->NumberOfEvents, ESI->NativeCount);
1088 
1089  int i, event, k, n, preset_index = 0, nevt;
1090  int total_events = ESI->NumberOfEvents;
1091 
1092  event = 0;
1093  for( i = 0; i < total_events; i++ ) {
1094 
1095  /* find the first event that isn't PAPI_NULL */
1096  /* Is this really necessary? --vmw */
1097  while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
1098  event++;
1099  }
1100 
1101  /* If it's a preset */
1102  if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
1103  preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
1104 
1105  /* walk all sub-events in the preset */
1106  for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
1107  nevt = _papi_hwi_presets[preset_index].code[k];
1108  if ( nevt == PAPI_NULL ) {
1109  break;
1110  }
1111 
1112  INTDBG("Looking for subevent %#x\n",nevt);
1113 
1114  /* Match each sub-event to something in the Native List */
1115  for( n = 0; n < ESI->NativeCount; n++ ) {
1116  if ( nevt == ESI->NativeInfoArray[n].ni_papi_code ) {
1117  INTDBG("Found papi event: %#x, &ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_position %d\n",
1118  nevt, n, &(ESI->NativeInfoArray[n]), ESI->NativeInfoArray[n].ni_event, ESI->NativeInfoArray[n].ni_position);
1119  ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
1120  break;
1121  }
1122  }
1123  }
1124  }
1125  /* If it's a native event */
1126  else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
1127  nevt = ( int ) ESI->EventInfoArray[event].event_code;
1128 
1129  // get index into native info array for this event
1130  int nidx = event_already_in_eventset( ESI, nevt );
1131  // if not found, then we need to return an error
1132  if (nidx == PAPI_ENOEVNT) {
1133  INTDBG("EXIT: needed event not found\n");
1134  return;
1135  }
1136  ESI->EventInfoArray[event].pos[0] = ESI->NativeInfoArray[nidx].ni_position;
1137  INTDBG("nidx: %d, ni_position: %d\n", nidx, ESI->NativeInfoArray[nidx].ni_position);
1138 
1139  }
1140  /* If it's a user-defined event */
1141  else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
1142  preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_UE_AND_MASK;
1143  for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
1144  nevt = user_defined_events[preset_index].code[k];
1145  INTDBG("nevt: %#x, user_defined_events[%d].code[%d]: %#x, code[%d]: %#x\n",
1146  nevt, preset_index, k, user_defined_events[preset_index].code[k], k+1, user_defined_events[preset_index].code[k+1]);
1147 
1148  if ( nevt == PAPI_NULL ) break;
1149 
1150  /* Match each sub-event to something in the Native List */
1151  for ( n = 0; n < ESI->NativeCount; n++ ) {
1152  // if this is the event we are looking for, set its position and exit inner loop to look for next sub-event
1153  if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[n].ni_event ) {
1154  ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
1155  break;
1156  }
1157  }
1158  }
1159  }
1160  event++;
1161  }
1162  INTDBG("EXIT: \n");
1163  return;
1164 }
1165 
1166 
1167 static int
1169 {
1170  INTDBG("ENTER: ESI: %p, nevt: %#x\n", ESI, nevt);
1171 
1172  int i, max_counters;
1173  int cidx;
1174 
1175  cidx = _papi_hwi_component_index( nevt );
1176  if (cidx<0) return PAPI_ENOCMP;
1177 
1178  max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
1179 
1180  /* to find the native event from the native events list */
1181  for( i = 0; i < max_counters; i++ ) {
1182 // INTDBG("ESI->NativeInfoArray[%d]: %p, ni_event: %#x, ni_papi_event_code: %#x, ni_position: %d, ni_owners: %d\n",
1183 // i, &(ESI->NativeInfoArray[i]), ESI->NativeInfoArray[i].ni_event, ESI->NativeInfoArray[i].ni_papi_code, ESI->NativeInfoArray[i].ni_position, ESI->NativeInfoArray[i].ni_owners);
1184  if ( nevt == ESI->NativeInfoArray[i].ni_papi_code ) {
1185  ESI->NativeInfoArray[i].ni_owners--;
1186  /* to clean the entry in the nativeInfo array */
1187  if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
1188  ESI->NativeInfoArray[i].ni_event = -1;
1189  ESI->NativeInfoArray[i].ni_position = -1;
1190  ESI->NativeInfoArray[i].ni_papi_code = -1;
1191  ESI->NativeCount--;
1192  }
1193  INTDBG( "EXIT: nevt: %#x, returned: %d\n", nevt, i);
1194  return i;
1195  }
1196  }
1197  INTDBG( "EXIT: returned: -1\n");
1198  return -1;
1199 }
1200 
1201 /* since update_control_state trashes overflow settings, this puts things
1202  back into balance. */
1203 static int
1205 {
1206  int i, retval = PAPI_OK;
1207 
1208  if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
1209  for( i = 0; i < ESI->overflow.event_counter; i++ ) {
1210  retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
1211  ESI->overflow.EventIndex[i],
1212  ESI->overflow.threshold[i] );
1213  if ( retval != PAPI_OK ) {
1214  break;
1215  }
1216  }
1217  }
1218  return retval;
1219 }
1220 
1221 /* this function is called by _papi_hwi_add_event when adding native events
1222  ESI: event set to add the events to
1223  nevnt: pointer to array of native event table indexes to add
1224  size: number of native events to add
1225  out: ???
1226 
1227  return: < 0 = error
1228  0 = no new events added
1229  1 = new events added
1230 */
1231 static int
1232 add_native_events( EventSetInfo_t *ESI, unsigned int *nevt,
1233  int size, EventInfo_t *out )
1234 {
1235  INTDBG ("ENTER: ESI: %p, nevt: %p, size: %d, out: %p\n", ESI, nevt, size, out);
1236  int nidx, i, j, added_events = 0;
1237  int retval, retval2;
1238  int max_counters;
1239  hwd_context_t *context;
1240 
1241  max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1242 
1243  /* Walk through the list of native events, adding them */
1244  for( i = 0; i < size; i++ ) {
1245 
1246  /* Check to see if event is already in EventSet */
1247  nidx = event_already_in_eventset( ESI, nevt[i] );
1248 
1249  if ( nidx >= 0 ) {
1250  /* Event is already there. Set position */
1251  out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
1252  ESI->NativeInfoArray[nidx].ni_owners++;
1253  continue;
1254  }
1255 
1256  /* Event wasn't already there */
1257 
1258  if ( ESI->NativeCount == max_counters ) {
1259 
1260  /* No more room in counters! */
1261  for( j = 0; j < i; j++ ) {
1262  if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
1263  out->pos[j] = -1;
1264  continue;
1265  }
1266  INTDBG( "should not happen!\n" );
1267  }
1268  INTDBG( "EXIT: counters are full!\n" );
1269  return PAPI_ECOUNT;
1270  }
1271 
1272  /* there is an empty slot for the native event; */
1273  /* initialize the native index for the new added event */
1274  INTDBG( "Adding nevt[%d]: %#x, ESI->NativeInfoArray[%d]: %p, Component: %d\n",
1275  i, nevt[i], ESI->NativeCount, &ESI->NativeInfoArray[ESI->NativeCount], ESI->CmpIdx );
1276  ESI->NativeInfoArray[ESI->NativeCount].ni_event =
1278  ESI->NativeInfoArray[ESI->NativeCount].ni_papi_code = nevt[i];
1279 
1280  ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
1281  ESI->NativeCount++;
1282  added_events++;
1283  }
1284 
1285  INTDBG("added_events: %d\n", added_events);
1286 
1287  /* if we added events we need to tell the component so it */
1288  /* can add them too. */
1289  if ( added_events ) {
1290  /* get the context we should use for this event set */
1291  context = _papi_hwi_get_context( ESI, NULL );
1292 
1293  if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
1294 
1295  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1296  ESI->NativeInfoArray,
1297  ESI->NativeCount,
1298  context);
1299  if ( retval != PAPI_OK ) {
1300 clean:
1301  for( i = 0; i < size; i++ ) {
1302  if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
1303  out->pos[i] = -1;
1304  continue;
1305  }
1306  INTDBG( "should not happen!\n" );
1307  }
1308  /* re-establish the control state after the previous error */
1309  retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state(
1310  ESI->ctl_state,
1311  ESI->NativeInfoArray,
1312  ESI->NativeCount,
1313  context);
1314  if ( retval2 != PAPI_OK ) {
1315  PAPIERROR("update_control_state failed to re-establish working events!" );
1316  INTDBG( "EXIT: update_control_state returned: %d\n", retval2);
1317  return retval2;
1318  }
1319  INTDBG( "EXIT: update_control_state returned: %d\n", retval);
1320  return retval;
1321  }
1322  INTDBG( "EXIT: update_control_state returned: %d, we return: 1 (need remap)\n", retval);
1323  return 1; /* need remap */
1324  } else {
1325  retval = PAPI_EMISC;
1326  goto clean;
1327  }
1328  }
1329  INTDBG( "EXIT: PAPI_OK\n");
1330  return PAPI_OK;
1331 }
1332 
1333 
1334 int
1335 _papi_hwi_add_event( EventSetInfo_t * ESI, int EventCode )
1336 {
1337  INTDBG("ENTER: ESI: %p (%d), EventCode: %#x\n", ESI, ESI->EventSetIndex, EventCode);
1338 
1339  int i, j, thisindex, remap, retval = PAPI_OK;
1340  int cidx;
1341 
1342  /* Sanity check the component */
1343  cidx=_papi_hwi_component_index( EventCode );
1344  if (cidx<0) {
1345  return PAPI_ENOCMP;
1346  }
1347  if (_papi_hwd[cidx]->cmp_info.disabled) {
1348  return PAPI_ECMP_DISABLED;
1349  }
1350 
1351  /* Sanity check that the new EventCode is from the same component */
1352  /* as previous events. */
1353 
1354  if ( ESI->CmpIdx < 0 ) {
1355  if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx)) != PAPI_OK ) {
1356  INTDBG("EXIT: Error assigning eventset to component index %d\n", cidx);
1357  return retval;
1358  }
1359  } else {
1360  if ( ESI->CmpIdx != cidx ) {
1361  INTDBG("EXIT: Event is not valid for component index %d\n", cidx);
1362  return PAPI_EINVAL;
1363  }
1364  }
1365 
1366  /* Make sure the event is not present and get the next free slot. */
1367  thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1368  if ( thisindex < PAPI_OK ) {
1369  return thisindex;
1370  }
1371 
1372  INTDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
1373 
1374  /* If it is a software MPX EventSet, add it to the multiplex data structure */
1375  /* and this thread's multiplex list */
1376 
1377  if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
1378 
1379  /* Handle preset case */
1380  if ( IS_PRESET(EventCode) ) {
1381  int count;
1382  int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
1383 
1384  /* Check if it's within the valid range */
1385  if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
1386  return PAPI_EINVAL;
1387  }
1388 
1389  /* count the number of native events in this preset */
1390  count = ( int ) _papi_hwi_presets[preset_index].count;
1391 
1392  /* Check if event exists */
1393  if ( !count ) {
1394  return PAPI_ENOEVNT;
1395  }
1396 
1397  /* check if the native events have been used as overflow events */
1398  /* this is not allowed */
1399  if ( ESI->state & PAPI_OVERFLOWING ) {
1400  for( i = 0; i < count; i++ ) {
1401  for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1402  if ( ESI->overflow.EventCode[j] ==(int)
1403  ( _papi_hwi_presets[preset_index].code[i] ) ) {
1404  return PAPI_ECNFLCT;
1405  }
1406  }
1407  }
1408  }
1409 
1410  /* Try to add the preset. */
1411 
1412  remap = add_native_events( ESI,
1413  _papi_hwi_presets[preset_index].code,
1414  count, &ESI->EventInfoArray[thisindex] );
1415  if ( remap < 0 ) {
1416  return remap;
1417  }
1418  else {
1419  /* Fill in the EventCode (machine independent) information */
1420  ESI->EventInfoArray[thisindex].event_code =
1421  ( unsigned int ) EventCode;
1422  ESI->EventInfoArray[thisindex].derived =
1423  _papi_hwi_presets[preset_index].derived_int;
1424  ESI->EventInfoArray[thisindex].ops =
1425  _papi_hwi_presets[preset_index].postfix;
1426  ESI->NumberOfEvents++;
1428 
1429  }
1430  }
1431  /* Handle adding Native events */
1432  else if ( IS_NATIVE(EventCode) ) {
1433 
1434  /* Check if native event exists */
1435  if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
1436  return PAPI_ENOEVNT;
1437  }
1438 
1439  /* check if the native events have been used as overflow events */
1440  /* This is not allowed */
1441  if ( ESI->state & PAPI_OVERFLOWING ) {
1442  for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1443  if ( EventCode == ESI->overflow.EventCode[j] ) {
1444  return PAPI_ECNFLCT;
1445  }
1446  }
1447  }
1448 
1449  /* Try to add the native event. */
1450 
1451  remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
1452  &ESI->EventInfoArray[thisindex] );
1453 
1454  if ( remap < 0 ) {
1455  return remap;
1456  } else {
1457 
1458  /* Fill in the EventCode (machine independent) information */
1459  ESI->EventInfoArray[thisindex].event_code =
1460  ( unsigned int ) EventCode;
1461  ESI->NumberOfEvents++;
1463 
1464  }
1465  } else if ( IS_USER_DEFINED( EventCode ) ) {
1466  int count;
1467  int index = EventCode & PAPI_UE_AND_MASK;
1468 
1469  if ( index < 0 || index >= user_defined_events_count )
1470  return ( PAPI_EINVAL );
1471 
1472  count = ( int ) user_defined_events[index].count;
1473 
1474  for ( i = 0; i < count; i++ ) {
1475  for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
1476  if ( ESI->overflow.EventCode[j] ==
1477  (int)(user_defined_events[index].code[i]) ) {
1478  return ( PAPI_EBUG );
1479  }
1480  }
1481  }
1482 
1483  remap = add_native_events( ESI,
1484  user_defined_events[index].code,
1485  count, &ESI->EventInfoArray[thisindex] );
1486 
1487  if ( remap < 0 ) {
1488  return remap;
1489  } else {
1490  ESI->EventInfoArray[thisindex].event_code = (unsigned int) EventCode;
1491  ESI->EventInfoArray[thisindex].derived = user_defined_events[index].derived_int;
1492  ESI->EventInfoArray[thisindex].ops = user_defined_events[index].postfix;
1493  ESI->NumberOfEvents++;
1495  }
1496  } else {
1497 
1498  /* not Native, Preset, or User events */
1499 
1500  return PAPI_EBUG;
1501  }
1502  }
1503  else {
1504 
1505  /* Multiplexing is special. See multiplex.c */
1506 
1507  retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
1508  ESI->domain.domain,
1509  ESI->granularity.granularity );
1510 
1511 
1512  if ( retval < PAPI_OK ) {
1513  return retval;
1514  }
1515 
1516  /* Relevant (???) */
1517  ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;
1518  ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
1519 
1520  ESI->NumberOfEvents++;
1521 
1522  /* event is in the EventInfoArray but not mapped to the NativeEvents */
1523  /* this causes issues if you try to set overflow on the event. */
1524  /* in theory this wouldn't matter anyway. */
1525  }
1526 
1527  /* reinstate the overflows if any */
1528  retval=update_overflow( ESI );
1529 
1530  return retval;
1531 }
1532 
1533 static int
1534 remove_native_events( EventSetInfo_t *ESI, int *nevt, int size )
1535 {
1536  INTDBG( "Entry: ESI: %p, nevt: %p, size: %d\n", ESI, nevt, size);
1538  hwd_context_t *context;
1539  int i, j, zero = 0, retval;
1540 
1541  /* Remove the references to this event from the native events:
1542  for all the metrics in this event,
1543  compare to each native event in this event set,
1544  and decrement owners if they match */
1545  for( i = 0; i < size; i++ ) {
1546  int cevt = _papi_hwi_eventcode_to_native(nevt[i]);
1547 // INTDBG( "nevt[%d]: %#x, cevt: %#x\n", i, nevt[i], cevt);
1548  for( j = 0; j < ESI->NativeCount; j++ ) {
1549  if ((native[j].ni_event == cevt) && (native[j].ni_papi_code == nevt[i]) ) {
1550 // INTDBG( "native[%d]: %p, ni_papi_code: %#x, ni_event: %#x, ni_position: %d, ni_owners: %d\n",
1551 // j, &(native[j]), native[j].ni_papi_code, native[j].ni_event, native[j].ni_position, native[j].ni_owners);
1552  native[j].ni_owners--;
1553  if ( native[j].ni_owners == 0 ) {
1554  zero++;
1555  }
1556  break;
1557  }
1558  }
1559  }
1560 
1561  /* Remove any native events from the array if owners dropped to zero.
1562  The NativeInfoArray must be dense, with no empty slots, so if we
1563  remove an element, we must compact the list */
1564  for( i = 0; i < ESI->NativeCount; i++ ) {
1565 
1566  if ( native[i].ni_event == -1 ) continue;
1567 
1568  if ( native[i].ni_owners == 0 ) {
1569  int copy = 0;
1570  int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
1571  for( j = ESI->NativeCount - 1; j > i; j-- ) {
1572  if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
1573  else {
1574  /* copy j into i */
1575  native[i].ni_event = native[j].ni_event;
1576  native[i].ni_position = native[j].ni_position;
1577  native[i].ni_owners = native[j].ni_owners;
1578  /* copy opaque [j].ni_bits to [i].ni_bits */
1579  memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
1580  /* reset j to initialized state */
1581  native[j].ni_event = -1;
1582  native[j].ni_position = -1;
1583  native[j].ni_owners = 0;
1584  copy++;
1585  break;
1586  }
1587  }
1588 
1589  if ( copy == 0 ) {
1590  /* set this structure back to empty state */
1591  /* ni_owners is already 0 and contents of ni_bits doesn't matter */
1592  native[i].ni_event = -1;
1593  native[i].ni_position = -1;
1594  }
1595  }
1596  }
1597 
1598  INTDBG( "ESI->NativeCount: %d, zero: %d\n", ESI->NativeCount, zero);
1599 
1600  /* to reset hwd_control_state values */
1601  ESI->NativeCount -= zero;
1602 
1603  /* If we removed any elements,
1604  clear the now empty slots, reinitialize the index, and update the count.
1605  Then send the info down to the component to update the hwd control structure. */
1606  retval = PAPI_OK;
1607  if ( zero ) {
1608  /* get the context we should use for this event set */
1609  context = _papi_hwi_get_context( ESI, NULL );
1610  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1611  native, ESI->NativeCount, context);
1612  if ( retval == PAPI_OK )
1613  retval = update_overflow( ESI );
1614  }
1615  return ( retval );
1616 }
1617 
1618 int
1620 {
1621  int j = 0, retval, thisindex;
1622  EventInfo_t *array;
1623 
1624  thisindex =
1625  _papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1626  if ( thisindex < PAPI_OK )
1627  return ( thisindex );
1628 
1629  /* If it is a MPX EventSet, remove it from the multiplex data structure and
1630  this threads multiplex list */
1631 
1632  if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1633  retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1634  if ( retval < PAPI_OK )
1635  return ( retval );
1636  } else
1637  /* Remove the events hardware dependent stuff from the EventSet */
1638  {
1639  if ( IS_PRESET(EventCode) ) {
1640  int preset_index = EventCode & PAPI_PRESET_AND_MASK;
1641 
1642  /* Check if it's within the valid range */
1643  if ( ( preset_index < 0 ) ||
1644  ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
1645  return PAPI_EINVAL;
1646 
1647  /* Check if event exists */
1648  if ( !_papi_hwi_presets[preset_index].count )
1649  return PAPI_ENOEVNT;
1650 
1651  /* Remove the preset event. */
1652  for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
1653  j++ );
1654  retval = remove_native_events( ESI, ( int * )_papi_hwi_presets[preset_index].code, j );
1655  if ( retval != PAPI_OK )
1656  return ( retval );
1657  } else if ( IS_NATIVE(EventCode) ) {
1658  /* Check if native event exists */
1659  if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
1660  PAPI_OK )
1661  return PAPI_ENOEVNT;
1662 
1663  /* Remove the native event. */
1664  retval = remove_native_events( ESI, &EventCode, 1 );
1665  if ( retval != PAPI_OK )
1666  return ( retval );
1667  } else if ( IS_USER_DEFINED( EventCode ) ) {
1668  int index = EventCode & PAPI_UE_AND_MASK;
1669 
1670  if ( (index < 0) || (index >= user_defined_events_count) )
1671  return ( PAPI_EINVAL );
1672 
1673  for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
1674  user_defined_events[index].code[j] != 0; j++ ) {
1675  retval = remove_native_events( ESI, ( int * )user_defined_events[index].code, j);
1676 
1677  if ( retval != PAPI_OK )
1678  return ( retval );
1679  }
1680  } else
1681  return ( PAPI_ENOEVNT );
1682  }
1683  array = ESI->EventInfoArray;
1684 
1685  /* Compact the Event Info Array list if it's not the last event */
1686  /* clear the newly empty slot in the array */
1687  for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
1688  array[thisindex] = array[thisindex + 1];
1689 
1690 
1691  array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
1692  for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
1693  array[thisindex].pos[j] = PAPI_NULL;
1694  array[thisindex].ops = NULL;
1695  array[thisindex].derived = NOT_DERIVED;
1696  ESI->NumberOfEvents--;
1697 
1698  return ( PAPI_OK );
1699 }
1700 
1701 int
1703  long long *values )
1704 {
1705  INTDBG("ENTER: context: %p, ESI: %p, values: %p\n", context, ESI, values);
1706  int retval;
1707  long long *dp = NULL;
1708  int i, index;
1709 
1710  retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state,
1711  &dp, ESI->state );
1712  if ( retval != PAPI_OK ) {
1713  INTDBG("EXIT: retval: %d\n", retval);
1714  return retval;
1715  }
1716 
1717  /* This routine distributes hardware counters to software counters in the
1718  order that they were added. Note that the higher level
1719  EventInfoArray[i] entries may not be contiguous because the user
1720  has the right to remove an event.
1721  But if we do compaction after remove event, this function can be
1722  changed.
1723  */
1724 
1725  for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
1726 
1727  index = ESI->EventInfoArray[i].pos[0];
1728 
1729  if ( index == -1 )
1730  continue;
1731 
1732  INTDBG( "ESI->EventInfoArray: %p, pos[%d]: %d, dp[%d]: %lld, derived[%d]: %#x\n", ESI->EventInfoArray, i, index, index, dp[index], i, ESI->EventInfoArray[i].derived );
1733 
1734  /* If this is not a derived event */
1735 
1736  if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
1737  values[i] = dp[index];
1738  INTDBG( "value: %#llx\n", values[i] );
1739  } else { /* If this is a derived event */
1740  values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
1741 #ifdef DEBUG
1742  if ( values[i] < ( long long ) 0 ) {
1743  INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
1744  }
1745  INTDBG( "derived value: %#llx \n", values[i] );
1746 #endif
1747  }
1748  }
1749 
1750  INTDBG("EXIT: PAPI_OK\n");
1751  return PAPI_OK;
1752 }
1753 
1754 int
1756 {
1757  int i, j, num_cntrs, retval;
1758  hwd_context_t *context;
1759  int EventCode;
1761  if ( !_papi_hwi_invalid_cmp( ESI->CmpIdx ) ) {
1762  num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1763 
1764  for(i=0;i<num_cntrs;i++) {
1765 
1766  EventCode=ESI->EventInfoArray[i].event_code;
1767 
1768  /* skip if event not there */
1769  if ( EventCode == PAPI_NULL ) continue;
1770 
1771  /* If it is a MPX EventSet, remove it from the multiplex */
1772  /* data structure and this thread's multiplex list */
1773 
1774  if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1775  retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1776  if ( retval < PAPI_OK )
1777  return retval;
1778  } else {
1779 
1780  native = ESI->NativeInfoArray;
1781 
1782  /* clear out ESI->NativeInfoArray */
1783  /* do we really need to do this, seeing as we free() it later? */
1784 
1785  for( j = 0; j < ESI->NativeCount; j++ ) {
1786  native[j].ni_event = -1;
1787  native[j].ni_position = -1;
1788  native[j].ni_owners = 0;
1789  /* native[j].ni_bits?? */
1790  }
1791  }
1792 
1793  /* do we really need to do this, seeing as we free() it later? */
1794  ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
1795  for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
1796  ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
1797  }
1798  ESI->EventInfoArray[i].ops = NULL;
1800  }
1801 
1802  context = _papi_hwi_get_context( ESI, NULL );
1803  /* calling with count of 0 equals a close? */
1804  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1805  NULL, 0, context);
1806  if (retval!=PAPI_OK) {
1807  return retval;
1808  }
1809  }
1810 
1811  ESI->CmpIdx = -1;
1812  ESI->NumberOfEvents = 0;
1813  ESI->NativeCount = 0;
1814 
1815  if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
1816  papi_free( ESI->multiplex.mpx_evset );
1817 
1818  if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
1820 
1821  if ( ESI->ctl_state )
1822  papi_free( ESI->ctl_state );
1823 
1824  if ( ESI->sw_stop )
1825  papi_free( ESI->sw_stop );
1826 
1827  if ( ESI->hw_start )
1828  papi_free( ESI->hw_start );
1829 
1830  if ( ESI->EventInfoArray )
1831  papi_free( ESI->EventInfoArray );
1832 
1833  if ( ESI->NativeInfoArray )
1834  papi_free( ESI->NativeInfoArray );
1835 
1836  if ( ESI->NativeBits )
1837  papi_free( ESI->NativeBits );
1838 
1839  if ( ESI->overflow.deadline )
1840  papi_free( ESI->overflow.deadline );
1841 
1842  if ( ESI->profile.prof )
1843  papi_free( ESI->profile.prof );
1844 
1845  ESI->ctl_state = NULL;
1846  ESI->sw_stop = NULL;
1847  ESI->hw_start = NULL;
1848  ESI->EventInfoArray = NULL;
1849  ESI->NativeInfoArray = NULL;
1850  ESI->NativeBits = NULL;
1851 
1852  memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
1853  memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
1854  memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
1855  memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
1856  memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
1857  memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
1858  memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
1859  memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
1860 
1861  ESI->CpuInfo = NULL;
1862 
1863  return PAPI_OK;
1864 }
1865 
1866 int
1868 {
1869  int retval, i, j = 0, *mpxlist = NULL;
1870  EventSetInfo_t *ESI = mpx->ESI;
1871  int flags = mpx->flags;
1872 
1873  /* If there are any events in the EventSet,
1874  convert them to multiplex events */
1875 
1876  if ( ESI->NumberOfEvents ) {
1877 
1878  mpxlist =
1879  ( int * ) papi_malloc( sizeof ( int ) *
1880  ( size_t ) ESI->NumberOfEvents );
1881  if ( mpxlist == NULL )
1882  return ( PAPI_ENOMEM );
1883 
1884  /* Build the args to MPX_add_events(). */
1885 
1886  /* Remember the EventInfoArray can be sparse
1887  and the data can be non-contiguous */
1888 
1889  for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
1890  if ( ESI->EventInfoArray[i].event_code !=
1891  ( unsigned int ) PAPI_NULL )
1892  mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
1893 
1894  /* Resize the EventInfo_t array */
1895 
1896  if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
1897  ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
1898  ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
1899  retval =
1900  MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
1901  ESI->domain.domain,
1902  ESI->granularity.granularity );
1903  if ( retval != PAPI_OK ) {
1904  papi_free( mpxlist );
1905  return ( retval );
1906  }
1907  }
1908 
1909  papi_free( mpxlist );
1910  }
1911 
1912  /* Update the state before initialization! */
1913 
1914  ESI->state |= PAPI_MULTIPLEXING;
1915  if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
1916  ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
1918  ESI->multiplex.ns = ( int ) mpx->ns;
1919 
1920  return ( PAPI_OK );
1921 }
1922 
1923 #include "components_config.h"
1924 
1925 int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
1926 
1927 /*
1928  * Routine that initializes all available components.
1929  * A component is available if a pointer to its info vector
1930  * appears in the NULL terminated_papi_hwd table.
1931  */
1932 int
1934 {
1935  int retval, i = 0;
1936 
1938  if ( retval != PAPI_OK ) {
1939  return retval;
1940  }
1941 
1942  while ( _papi_hwd[i] ) {
1943 
1945  if ( retval != PAPI_OK ) {
1946  return retval;
1947  }
1948 
1949  /* We can be disabled by user before init */
1950  if (!_papi_hwd[i]->cmp_info.disabled) {
1951  retval = _papi_hwd[i]->init_component( i );
1952  _papi_hwd[i]->cmp_info.disabled=retval;
1953 
1954  /* Do some sanity checking */
1955  if (retval==PAPI_OK) {
1956  if (_papi_hwd[i]->cmp_info.num_cntrs >
1957  _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
1958  fprintf(stderr,"Warning! num_cntrs %d is more than num_mpx_cntrs %d for component %s\n",
1959  _papi_hwd[i]->cmp_info.num_cntrs,
1960  _papi_hwd[i]->cmp_info.num_mpx_cntrs,
1961  _papi_hwd[i]->cmp_info.name);
1962  }
1963 
1964  }
1965  }
1966 
1967  i++;
1968  }
1969  return PAPI_OK;
1970 }
1971 
1972 /* Machine info struct initialization using defaults */
1973 /* See _papi_mdi definition in papi_internal.h */
1974 
1975 int
1977 {
1978 
1979  int retval;
1980 
1981  memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
1982 
1983  memset( _papi_hwi_using_signal,0x0,sizeof( _papi_hwi_using_signal ));
1984 
1985  /* Global struct to maintain EventSet mapping */
1987  if ( retval != PAPI_OK ) {
1988  return retval;
1989  }
1990 
1991  _papi_hwi_system_info.pid = 0; /* Process identifier */
1992 
1993  /* PAPI_hw_info_t struct */
1994  memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
1995 
1996  return PAPI_OK;
1997 }
1998 
1999 void
2001 {
2002  int i = 0;
2004 
2006 
2008 
2009  for( i = 0; i < num_native_events; i++){
2011  }
2012 
2013  free(_papi_native_events);
2014  _papi_native_events = NULL; // In case a new library init is done.
2015  num_native_events=0; // ..
2016  num_native_chunks=0; // ..
2017 
2019 
2022  0x00, sizeof ( DynamicArray_t ) );
2023 
2025 
2028  }
2029  memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
2030 
2031 }
2032 
2033 
2034 
2035 void
2036 _papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
2037  void *context )
2038 {
2039  /* This function is not used and shouldn't be called. */
2040  ( void ) EventSet; /*unused */
2041  ( void ) address; /*unused */
2042  ( void ) overflow_vector; /*unused */
2043  ( void ) context; /*unused */
2044  return;
2045 }
2046 
2047 static long long
2048 handle_derived_add( int *position, long long *from )
2049 {
2050  int pos, i;
2051  long long retval = 0;
2052 
2053  i = 0;
2054  while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
2055  pos = position[i++];
2056  if ( pos == PAPI_NULL )
2057  break;
2058  INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
2059  retval += from[pos];
2060  }
2061  return ( retval );
2062 }
2063 
2064 static long long
2065 handle_derived_subtract( int *position, long long *from )
2066 {
2067  int pos, i;
2068  long long retval = from[position[0]];
2069 
2070  i = 1;
2071  while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
2072  pos = position[i++];
2073  if ( pos == PAPI_NULL )
2074  break;
2075  INTDBG( "Compound event, subtracting pos=%d %lld from %lld\n", pos,
2076  from[pos], retval );
2077  retval -= from[pos];
2078  }
2079  return ( retval );
2080 }
2081 
2082 static long long
2083 units_per_second( long long units, long long cycles )
2084 {
2085  return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
2086  (long long) 1000000 ) / cycles );
2087 }
2088 
2089 static long long
2090 handle_derived_ps( int *position, long long *from )
2091 {
2092  return ( units_per_second( from[position[1]], from[position[0]] ) );
2093 }
2094 static long long
2095 handle_derived_add_ps( int *position, long long *from )
2096 {
2097  long long tmp = handle_derived_add( position + 1, from );
2098  return ( units_per_second( tmp, from[position[0]] ) );
2099 }
2100 
2101 /* this function implement postfix calculation, it reads in a string where I use:
2102  | as delimiter
2103  N2 indicate No. 2 native event in the derived preset
2104  +, -, *, / as operator
2105  # as MHZ(million hz) got from _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
2106 
2107  Haihang (you@cs.utk.edu)
2108 */
2109  static long long
2110  _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
2111  {
2112  char *point = evi->ops, operand[16];
2114  int i, val, top = 0;
2115 
2116  INTDBG("ENTER: evi: %p, evi->ops: %p (%s), evi->pos[0]: %d, evi->pos[1]: %d, hw_counter: %p (%lld %lld)\n",
2117  evi, evi->ops, evi->ops, evi->pos[0], evi->pos[1], hw_counter, hw_counter[0], hw_counter[1]);
2118 
2119  memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
2120 
2121  while ( *point != '\0' ) {
2122  if ( *point == '|' ) { /* consume '|' characters */
2123  point++;
2124  } else if ( *point == 'N' ) { /* to get count for each native event */
2125  point++;
2126  i = 0;
2127  while ( isdigit(*point) ) {
2128  assert(i<16);
2129  operand[i] = *point;
2130  point++;
2131  i++;
2132  }
2133  assert(0<i && i<16);
2134  operand[i] = '\0';
2135  val = atoi( operand );
2136  assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2137  assert( 0 <= val && val < PAPI_EVENTS_IN_DERIVED_EVENT );
2138  stack[top] = ( double ) hw_counter[evi->pos[val]];
2139  top++;
2140  } else if ( *point == '#' ) { /* to get mhz */
2141  point++;
2142  assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2143  stack[top] = _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000000.0;
2144  top++;
2145  } else if ( isdigit( *point ) ) {
2146  i = 0;
2147  while ( isdigit(*point) ) {
2148  assert(i<16);
2149  operand[i] = *point;
2150  point++;
2151  i++;
2152  }
2153  assert(0<i && i<16);
2154  operand[i] = '\0';
2155  assert( top < PAPI_EVENTS_IN_DERIVED_EVENT );
2156  stack[top] = atoi( operand );
2157  top++;
2158  } else if ( *point == '+' ) { /* + calculation */
2159  point++;
2160  assert(top >= 2);
2161  stack[top - 2] += stack[top - 1];
2162  top--;
2163  } else if ( *point == '-' ) { /* - calculation */
2164  point++;
2165  assert(top >= 2);
2166  stack[top - 2] -= stack[top - 1];
2167  top--;
2168  } else if ( *point == '*' ) { /* * calculation */
2169  point++;
2170  assert(top >= 2);
2171  stack[top - 2] *= stack[top - 1];
2172  top--;
2173  } else if ( *point == '/' ) { /* / calculation */
2174  point++;
2175  assert(top >= 2);
2176  /* FIXME should handle runtime divide by zero */
2177  stack[top - 2] /= stack[top - 1];
2178  top--;
2179  } else { /* flag an error parsing the preset */
2180  PAPIERROR( "BUG! Unable to parse \"%s\"", evi->ops );
2181  return ( long long ) stack[0];
2182  }
2183  }
2184  assert(top == 1);
2185  INTDBG("EXIT: stack[0]: %lld\n", (long long)stack[0]);
2186  return ( long long ) stack[0];
2187  }
2188 
2189 static long long
2190 handle_derived( EventInfo_t * evi, long long *from )
2191 {
2192  INTDBG("ENTER: evi: %p, evi->derived: %d, from: %p\n", evi, evi->derived, from);
2193  switch ( evi->derived ) {
2194  case DERIVED_ADD:
2195  return ( handle_derived_add( evi->pos, from ) );
2196  case DERIVED_ADD_PS:
2197  return ( handle_derived_add_ps( evi->pos, from ) );
2198  case DERIVED_SUB:
2199  return ( handle_derived_subtract( evi->pos, from ) );
2200  case DERIVED_PS:
2201  return ( handle_derived_ps( evi->pos, from ) );
2202  case DERIVED_POSTFIX:
2203  return ( _papi_hwi_postfix_calc( evi, from ) );
2204  case DERIVED_CMPD: /* This type has existed for a long time, but was never implemented.
2205  Probably because its a no-op. However, if it's in a header, it
2206  should be supported. As I found out when I implemented it in
2207  Pentium 4 for testing...dkt */
2208  return ( from[evi->pos[0]] );
2209  default:
2210  PAPIERROR( "BUG! Unknown derived command %d, returning 0", evi->derived );
2211  INTDBG("EXIT: Unknown derived command %d\n", evi->derived);
2212  return ( ( long long ) 0 );
2213  }
2214 }
2215 
2216 
2217 /* table matching derived types to derived strings.
2218  used by get_info, encode_event, xml translator
2219 */
2221  {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
2222  {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
2223  {DERIVED_PS, "DERIVED_PS",
2224  "Divide by the cycle counter and convert to seconds"},
2225  {DERIVED_ADD_PS, "DERIVED_ADD_PS",
2226  "Add 2 counters then divide by the cycle counter and xl8 to secs."},
2227  {DERIVED_CMPD, "DERIVED_CMPD",
2228  "Event lives in first counter but takes 2 or more codes"},
2229  {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
2230  {DERIVED_POSTFIX, "DERIVED_POSTFIX",
2231  "Process counters based on specified postfix string"},
2232  {DERIVED_INFIX, "DERIVED_INFIX",
2233  "Process counters based on specified infix string"},
2234  {-1, NULL, NULL}
2235 };
2236 
2237 /* _papi_hwi_derived_type:
2238  Helper routine to extract a derived type from a derived string
2239  returns type value if found, otherwise returns -1
2240 */
2241 int
2242 _papi_hwi_derived_type( char *tmp, int *code )
2243 {
2244  int i = 0;
2245  while ( _papi_hwi_derived[i].name != NULL ) {
2246  if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
2247  *code = _papi_hwi_derived[i].value;
2248  return PAPI_OK;
2249  }
2250  i++;
2251  }
2252  INTDBG( "Invalid derived string %s\n", tmp );
2253  return PAPI_EINVAL;
2254 }
2255 
2256 
2257 /* _papi_hwi_derived_string:
2258  Helper routine to extract a derived string from a derived type
2259  copies derived type string into derived if found,
2260  otherwise returns PAPI_EINVAL
2261 */
2262 static int
2263 _papi_hwi_derived_string( int type, char *derived, int len )
2264 {
2265  int j;
2266 
2267  for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
2268  if ( _papi_hwi_derived[j].value == type ) {
2269  strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
2270  len );
2271  return PAPI_OK;
2272  }
2273  }
2274  INTDBG( "Invalid derived type %d\n", type );
2275  return PAPI_EINVAL;
2276 }
2277 
2278 
2279 /* _papi_hwi_get_preset_event_info:
2280  Assumes EventCode contains a valid preset code.
2281  But defensive programming says check for NULL pointers.
2282  Returns a filled in PAPI_event_info_t structure containing
2283  descriptive strings and values for the specified preset event.
2284 */
2285 int
2287 {
2288  INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2289 
2290  int i = EventCode & PAPI_PRESET_AND_MASK;
2291  unsigned int j;
2292 
2293  if ( _papi_hwi_presets[i].symbol ) { /* if the event is in the preset table */
2294  // since we are setting the whole structure to zero the strncpy calls below will
2295  // be leaving NULL terminates strings as long as they copy 1 less byte than the
2296  // buffer size of the field.
2297  memset( info, 0, sizeof ( PAPI_event_info_t ) );
2298 
2299  info->event_code = ( unsigned int ) EventCode;
2300  strncpy( info->symbol, _papi_hwi_presets[i].symbol,
2301  sizeof(info->symbol)-1);
2302 
2303  if ( _papi_hwi_presets[i].short_descr != NULL )
2304  strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
2305  sizeof ( info->short_descr )-1 );
2306 
2307  if ( _papi_hwi_presets[i].long_descr != NULL )
2308  strncpy( info->long_descr, _papi_hwi_presets[i].long_descr,
2309  sizeof ( info->long_descr )-1 );
2310 
2312  info->count = _papi_hwi_presets[i].count;
2313 
2315  info->derived, sizeof ( info->derived ) );
2316 
2317  if ( _papi_hwi_presets[i].postfix != NULL )
2318  strncpy( info->postfix, _papi_hwi_presets[i].postfix,
2319  sizeof ( info->postfix )-1 );
2320 
2321  for(j=0;j < info->count; j++) {
2322  info->code[j]=_papi_hwi_presets[i].code[j];
2323  strncpy(info->name[j], _papi_hwi_presets[i].name[j],
2324  sizeof(info->name[j])-1);
2325  }
2326 
2327  if ( _papi_hwi_presets[i].note != NULL ) {
2328  strncpy( info->note, _papi_hwi_presets[i].note,
2329  sizeof ( info->note )-1 );
2330  }
2331 
2332  return PAPI_OK;
2333  } else {
2334  return PAPI_ENOEVNT;
2335  }
2336 }
2337 
2338 
2339 /* _papi_hwi_get_user_event_info:
2340  Assumes EventCode contains a valid user event code.
2341  But defensive programming says check for NULL pointers.
2342  Returns a filled in PAPI_event_info_t structure containing
2343  descriptive strings and values for the specified preset event.
2344 */
2345 int
2347 {
2348  INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2349 
2350  unsigned int i = EventCode & PAPI_UE_AND_MASK;
2351  unsigned int j;
2352 
2353  // if event code not in valid range, return error
2354  if (i >= PAPI_MAX_USER_EVENTS) {
2355  INTDBG("EXIT: Invalid event index: %d, max value is: %d\n", i, PAPI_MAX_USER_EVENTS - 1);
2356  return( PAPI_ENOEVNT );
2357  }
2358 
2359  if ( user_defined_events[i].symbol == NULL) { /* if the event is in the preset table */
2360  INTDBG("EXIT: Event symbol for this event is NULL\n");
2361  return PAPI_ENOEVNT;
2362  }
2363 
2364  /* set whole structure to 0 */
2365  memset( info, 0, sizeof ( PAPI_event_info_t ) );
2366 
2367  info->event_code = ( unsigned int ) EventCode;
2368  strncpy( info->symbol, user_defined_events[i].symbol,
2369  sizeof(info->symbol)-1);
2370 
2371  if ( user_defined_events[i].short_descr != NULL )
2372  strncpy( info->short_descr, user_defined_events[i].short_descr,
2373  sizeof(info->short_descr)-1);
2374 
2375  if ( user_defined_events[i].long_descr != NULL )
2376  strncpy( info->long_descr, user_defined_events[i].long_descr,
2377  sizeof(info->long_descr)-1);
2378 
2379 // info->event_type = user_defined_events[i].event_type;
2380  info->count = user_defined_events[i].count;
2381 
2383  info->derived, sizeof(info->derived)-1);
2384 
2385  if ( user_defined_events[i].postfix != NULL )
2386  strncpy( info->postfix, user_defined_events[i].postfix,
2387  sizeof(info->postfix)-1);
2388 
2389  for(j=0;j < info->count; j++) {
2390  info->code[j]=user_defined_events[i].code[j];
2391  INTDBG("info->code[%d]: %#x\n", j, info->code[j]);
2392  strncpy(info->name[j], user_defined_events[i].name[j], sizeof(info->name[j])-1);
2393  }
2394 
2395  if ( user_defined_events[i].note != NULL ) {
2396  strncpy( info->note, user_defined_events[i].note, sizeof(info->note)-1);
2397  }
2398 
2399  INTDBG("EXIT: PAPI_OK: event_code: %#x, symbol: %s, short_desc: %s, long_desc: %s\n", info->event_code, info->symbol, info->short_descr, info->long_descr);
2400  return PAPI_OK;
2401 }
2402 
2403 
2404 /* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
2405  Used to enumerate the entire array, e.g. for native_avail.c */
2406 int
2407 _papi_hwi_query_native_event( unsigned int EventCode )
2408 {
2409  INTDBG("ENTER: EventCode: %#x\n", EventCode);
2410  char name[PAPI_HUGE_STR_LEN]; /* probably overkill, */
2411  /* but should always be big enough */
2412  int cidx;
2413  int nevt_code;
2414 
2415  cidx = _papi_hwi_component_index( EventCode );
2416  if (cidx<0) {
2417  INTDBG("EXIT: PAPI_ENOCMP\n");
2418  return PAPI_ENOCMP;
2419  }
2420 
2421  // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2422  _papi_hwi_set_papi_event_code(EventCode, 0);
2423 
2424  if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2425  INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2426  return nevt_code;
2427  }
2428  int ret = _papi_hwd[cidx]->ntv_code_to_name( (unsigned int)nevt_code, name, sizeof(name));
2429 
2430  INTDBG("EXIT: ret: %d\n", ret);
2431  return (ret);
2432 }
2433 
2434 /* Converts an ASCII name into a native event code usable by other routines
2435  Returns code = 0 and PAPI_OK if name not found.
2436  This allows for sparse native event arrays */
2437 int
2438 _papi_hwi_native_name_to_code( const char *in, int *out )
2439 {
2440  INTDBG("ENTER: in: %s, out: %p\n", in, out);
2441 
2442  int retval = PAPI_ENOEVNT;
2443  char name[PAPI_HUGE_STR_LEN]; /* make sure it's big enough */
2444 
2445  unsigned int i;
2446  int cidx;
2447  char *full_event_name;
2448 
2449  if (in == NULL) {
2450  INTDBG("EXIT: PAPI_EINVAL\n");
2451  return PAPI_EINVAL;
2452  }
2453 
2454  full_event_name = strdup(in);
2455 
2457 
2458  // look in each component
2459  for(cidx=0; cidx < papi_num_components; cidx++) {
2460 
2461  if (_papi_hwd[cidx]->cmp_info.disabled) continue;
2462 
2463  // if this component does not support the pmu
2464  // which defines this event, no need to call it
2465  if (is_supported_by_component(cidx, full_event_name) == 0) {
2466  continue;
2467  }
2468 
2469  INTDBG("cidx: %d, name: %s, event: %s\n",
2470  cidx, _papi_hwd[cidx]->cmp_info.name, in);
2471 
2472  // show that we do not have an event code yet
2473  // (the component may create one and update this info)
2474  // this also clears any values left over from a previous call
2476 
2477 
2478  // if component has a ntv_name_to_code function, use it to get event code
2479  if (_papi_hwd[cidx]->ntv_name_to_code != NULL) {
2480  // try and get this events event code
2481  retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
2482  if (retval==PAPI_OK) {
2483  *out = _papi_hwi_native_to_eventcode(cidx, *out, -1, in);
2484  free (full_event_name);
2485  INTDBG("EXIT: PAPI_OK event: %s code: %#x\n", in, *out);
2486  return PAPI_OK;
2487  }
2488  } else {
2489  // force the code through the work around
2490  retval = PAPI_ECMP;
2491  }
2492 
2493  /* If not implemented, work around */
2494  if ( retval==PAPI_ECMP) {
2495  i = 0;
2496  retval = _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
2497  if (retval != PAPI_OK) {
2498  free (full_event_name);
2499  INTDBG("EXIT: retval: %d\n", retval);
2500  return retval;
2501  }
2502 
2503 // _papi_hwi_lock( INTERNAL_LOCK );
2504 
2505  do {
2506  // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2508  retval = _papi_hwd[cidx]->ntv_code_to_name(i, name, sizeof(name));
2509  /* printf("%#x\nname =|%s|\ninput=|%s|\n", i, name, in); */
2510  if ( retval == PAPI_OK && in != NULL) {
2511  if ( strcasecmp( name, in ) == 0 ) {
2512  *out = _papi_hwi_native_to_eventcode(cidx, i, -1, name);
2513  free (full_event_name);
2514  INTDBG("EXIT: PAPI_OK, event: %s, code: %#x\n", in, *out);
2515  return PAPI_OK;
2516  }
2517  retval = PAPI_ENOEVNT;
2518  } else {
2519  *out = 0;
2520  retval = PAPI_ENOEVNT;
2521  break;
2522  }
2523  } while ( ( _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_EVENTS ) == PAPI_OK ) );
2524 
2525 // _papi_hwi_unlock( INTERNAL_LOCK );
2526  }
2527  }
2528 
2529  free (full_event_name);
2530  INTDBG("EXIT: retval: %d\n", retval);
2531 
2532  return retval;
2533 }
2534 
2535 /* Returns event name based on native event code.
2536  Returns NULL if name not found */
2537 int
2538 _papi_hwi_native_code_to_name( unsigned int EventCode,
2539  char *hwi_name, int len )
2540 {
2541  INTDBG("ENTER: EventCode: %#x, hwi_name: %p, len: %d\n", EventCode, hwi_name, len);
2542  int cidx;
2543  int retval;
2544  int nevt_code;
2545 
2546  cidx = _papi_hwi_component_index( EventCode );
2547  if (cidx<0) return PAPI_ENOEVNT;
2548 
2549  if ( EventCode & PAPI_NATIVE_MASK ) {
2550  // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2551  _papi_hwi_set_papi_event_code(EventCode, 0);
2552 
2553  if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2554  INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2555  return nevt_code;
2556  }
2557  if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2558  (unsigned int)nevt_code,
2559  hwi_name, len) ) == PAPI_OK ) {
2560  retval = _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name,
2561  hwi_name, hwi_name, len);
2562  INTDBG("EXIT: retval: %d\n", retval);
2563  return retval;
2564  }
2565  INTDBG("EXIT: retval: %d\n", retval);
2566  return (retval);
2567  }
2568  INTDBG("EXIT: PAPI_ENOEVNT\n");
2569  return PAPI_ENOEVNT;
2570 }
2571 
2572 
2573 
2574 /* The native event equivalent of PAPI_get_event_info */
2575 int
2576 _papi_hwi_get_native_event_info( unsigned int EventCode,
2577  PAPI_event_info_t *info )
2578 {
2579  INTDBG("ENTER: EventCode: %#x, info: %p\n", EventCode, info);
2580  int retval;
2581  int cidx;
2582  int nevt_code;
2583 
2584  cidx = _papi_hwi_component_index( EventCode );
2585  if (cidx<0) return PAPI_ENOCMP;
2586 
2587  if (_papi_hwd[cidx]->cmp_info.disabled) return PAPI_ENOCMP;
2588 
2589  if ( EventCode & PAPI_NATIVE_MASK ) {
2590  // save event code so components can get it with call to: _papi_hwi_get_papi_event_code()
2591  _papi_hwi_set_papi_event_code(EventCode, 0);
2592 
2593  /* clear the event info */
2594  memset( info, 0, sizeof ( PAPI_event_info_t ) );
2595  info->event_code = ( unsigned int ) EventCode;
2596  info->component_index = (unsigned int) cidx;
2597  retval = _papi_hwd[cidx]->ntv_code_to_info(
2598  _papi_hwi_eventcode_to_native(EventCode), info);
2599 
2600  /* If component error, it's missing the ntv_code_to_info vector */
2601  /* so we'll have to fake it. */
2602  if ( retval == PAPI_ECMP ) {
2603 
2604 
2605  INTDBG("missing NTV_CODE_TO_INFO, faking\n");
2606  /* Fill in the info structure */
2607 
2608  if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) < 0) {
2609  INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2610  return nevt_code;
2611  }
2612  if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2613  (unsigned int)nevt_code,
2614  info->symbol,
2615  sizeof(info->symbol)) ) == PAPI_OK ) {
2616 
2617  } else {
2618  INTDBG("EXIT: retval: %d\n", retval);
2619  return retval;
2620  }
2621 
2622  if ((nevt_code = _papi_hwi_eventcode_to_native(EventCode)) <0) {
2623  INTDBG("EXIT: nevt_code: %d\n", nevt_code);
2624  return nevt_code;
2625  }
2626  retval = _papi_hwd[cidx]->ntv_code_to_descr(
2627  (unsigned int)nevt_code,
2628  info->long_descr,
2629  sizeof ( info->long_descr));
2630  if (retval!=PAPI_OK) {
2631  INTDBG("Failed ntv_code_to_descr()\n");
2632  }
2633 
2634  }
2636  _papi_hwd[cidx]->cmp_info.short_name,
2637  info->symbol,
2638  info->symbol,
2639  sizeof(info->symbol) );
2640 
2641  INTDBG("EXIT: retval: %d\n", retval);
2642  return retval;
2643  }
2644 
2645  INTDBG("EXIT: PAPI_ENOEVNT\n");
2646  return PAPI_ENOEVNT;
2647 }
2648 
2651 {
2653  EventSetInfo_t *set;
2654 
2655  if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
2656  return ( NULL );
2657 
2658  set = map->dataSlotArray[eventset];
2659 #ifdef DEBUG
2660  if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
2661  ( set->master->tid != _papi_hwi_thread_id_fn( ) ) )
2662  return ( NULL );
2663 #endif
2664 
2665  return ( set );
2666 }
2667 
2668 int
2670 {
2671  /* Are we multiplexing at all */
2672  if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
2673  return 0;
2674  }
2675 
2676  /* Does the component support kernel multiplexing */
2677  if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
2678  /* Have we forced software multiplexing */
2679  if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
2680  return 1;
2681  }
2682  /* Nope, using hardware multiplexing */
2683  return 0;
2684  }
2685 
2686  /* We are multiplexing but the component does not support hardware */
2687 
2688  return 1;
2689 
2690 }
2691 
2692 hwd_context_t *
2693 _papi_hwi_get_context( EventSetInfo_t * ESI, int *is_dirty )
2694 {
2695  INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
2696  int dirty_ctx;
2697  hwd_context_t *ctx=NULL;
2698 
2699  /* assume for now the control state is clean (last updated by this ESI) */
2700  dirty_ctx = 0;
2701 
2702  /* get a context pointer based on if we are counting for a thread or for a cpu */
2703  if (ESI->state & PAPI_CPU_ATTACHED) {
2704  /* use cpu context */
2705  ctx = ESI->CpuInfo->context[ESI->CmpIdx];
2706 
2707  /* if the user wants to know if the control state was last set by the same event set, tell him */
2708  if (is_dirty != NULL) {
2709  if (ESI->CpuInfo->from_esi != ESI) {
2710  dirty_ctx = 1;
2711  }
2712  *is_dirty = dirty_ctx;
2713  }
2714  ESI->CpuInfo->from_esi = ESI;
2715 
2716  } else {
2717 
2718  /* use thread context */
2719  ctx = ESI->master->context[ESI->CmpIdx];
2720 
2721  /* if the user wants to know if the control state was last set by the same event set, tell him */
2722  if (is_dirty != NULL) {
2723  if (ESI->master->from_esi != ESI) {
2724  dirty_ctx = 1;
2725  }
2726  *is_dirty = dirty_ctx;
2727  }
2728  ESI->master->from_esi = ESI;
2729 
2730  }
2731  return( ctx );
2732 }
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:29
int _papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
#define PAPI_OK
Definition: fpapi.h:105
int atoi()
unsigned int count
Definition: papi.h:988
int _papi_hwi_convert_eventset_to_multiplex(_papi_int_multiplex_t *mpx)
#define PAPI_NATIVE_MASK
#define DERIVED_SUB
Definition: papi_internal.h:74
int _papi_hwi_get_ntv_idx(unsigned int papi_evt_code)
int errno
int _papi_hwi_using_signal[PAPI_NSIG]
Definition: extras.c:365
static unsigned int papi_event_code
int _papi_hwi_init_global_internal(void)
#define PAPI_CPU_ATTACHED
Definition: fpapi.h:37
#define IS_PRESET(EventCode)
Definition: papi.h:229
unsigned int _papi_hwi_get_papi_event_code()
#define PAPI_ENOMEM
Definition: fpapi.h:107
char * _papi_hwi_get_papi_event_string()
static const char * name
Definition: fork_overflow.c:31
static struct native_event_info * _papi_native_events
Definition: papi_internal.c:77
#define PAPI_CPU_ATTACH
Definition: papi.h:458
char * getenv()
#define PAPI_EVENTS_IN_DERIVED_EVENT
Definition: genpapifdef.c:39
int _papi_hwi_innoculate_os_vector(papi_os_vector_t *v)
Definition: papi_vector.c:200
#define PAPI_EINVAL
Definition: fpapi.h:106
unsigned long int(* _papi_hwi_thread_id_fn)(void)
Definition: threads.c:42
Hardware info structure.
Definition: papi.h:781
hwd_register_t * ni_bits
static int EventInfoArrayLength(const EventSetInfo_t *ESI)
static int is_supported_by_component(int cidx, char *event_name)
#define IS_USER_DEFINED(EventCode)
Definition: papi.h:230
char * papi_event_string
Definition: papi_internal.c:88
#define PAPI_UE_AND_MASK
#define papi_free(a)
Definition: papi_memory.h:35
int _papi_hwi_query_native_event(unsigned int EventCode)
int _papi_hwi_cleanup_eventset(EventSetInfo_t *ESI)
#define papi_malloc(a)
Definition: papi_memory.h:34
void PAPIWARN(char *format,...)
PAPI_debug_handler_t _papi_hwi_debug_handler
Definition: papi_internal.c:55
MPX_EventSet * mpx_evset
Definition: sw_multiplex.h:32
#define PAPI_MULTIPLEX_FORCE_SW
Definition: fpapi.h:46
static double array[ARRAYSIZE]
Definition: papi_l1_dca.c:23
int _papi_hwi_native_code_to_name(unsigned int EventCode, char *hwi_name, int len)
void _papi_hwi_dummy_handler(int EventSet, void *address, long long overflow_vector, void *context)
EventSetAttachInfo_t attach
static int _papi_hwi_find_native_event(int cidx, int event, const char *event_name)
hwd_register_t * NativeBits
long unsigned int size_t
void _papi_hwi_free_papi_event_string()
static long long handle_derived_subtract(int *position, long long *from)
static int _papi_hwi_derived_string(int type, char *derived, int len)
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
EventSetDomainInfo_t domain
int EventSet
int _papi_hwi_errno
Definition: papi_internal.c:57
int _papi_hwi_remove_EventSet(EventSetInfo_t *ESI)
int _papi_hwi_derived_type(char *tmp, int *code)
va_start(arg_list, fmt)
#define PAPI_EBUG
Definition: fpapi.h:111
static long long _papi_hwi_postfix_calc(EventInfo_t *evi, long long *hw_counter)
#define DERIVED_ADD
Definition: papi_internal.h:70
#define PAPI_ECMP_DISABLED
Definition: fpapi.h:130
int retval
Definition: zero_fork.c:53
static struct timeval start
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
unsigned int code[PAPI_MAX_INFO_TERMS]
Definition: papi.h:1004
char derived[PAPI_MIN_STR_LEN]
Definition: papi.h:996
void _papi_hwi_init_errors(void)
int _papi_hwi_remove_event(EventSetInfo_t *ESI, int EventCode)
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
#define DERIVED_CMPD
Definition: papi_internal.h:73
int _papi_hwi_get_user_event_info(int EventCode, PAPI_event_info_t *info)
PAPI_address_map_t * map
Definition: papi.h:715
#define PAPI_INIT_SLOTS
Definition: papi.h:462
double tmp
PAPI_shlib_info_t shlib_info
Return codes and api definitions.
#define INTDBG(format, args...)
Definition: papi_debug.h:65
static long long handle_derived_add(int *position, long long *from)
#define PAPI_ECMP
Definition: fpapi.h:109
int MPX_add_events(MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
Definition: sw_multiplex.c:676
#define PAPI_ESYS
Definition: fpapi.h:108
unsigned int event_type
Definition: papi_preset.h:30
#define PAPI_ENOCMP
Definition: fpapi.h:122
static int cidx
#define PAPI_MAX_PRESET_EVENTS
Definition: fpapi.h:16
static int _papi_hwi_add_error(char *error)
#define PAPI_MAX_USER_EVENTS
#define PAPI_VERB_ESTOP
Definition: fpapi.h:40
static void _papi_hwi_cleanup_errors()
papi_os_vector_t _papi_os_vector
Definition: aix.c:1288
#define PAPI_EMISC
Definition: fpapi.h:119
inline_static int _papi_hwi_lock(int lck)
Definition: threads.h:64
int _papi_hwi_native_to_eventcode(int cidx, int event_code, int ntv_idx, const char *event_name)
EventSetOverflowInfo_t overflow
#define PAPI_PMU_MAX
Definition: papi.h:470
static int event_already_in_eventset(EventSetInfo_t *ESI, int papi_event)
#define PAPI_OVERFLOW_HARDWARE
Definition: papi.h:413
EventSetInheritInfo_t inherit
struct _CpuInfo * CpuInfo
DynamicArray_t global_eventset_map
struct _ThreadInfo * master
#define IS_NATIVE(EventCode)
Definition: papi.h:228
static int allocate_eventset_map(DynamicArray_t *map)
#define NOT_DERIVED
Definition: papi_internal.h:69
int _papi_hwi_read(hwd_context_t *context, EventSetInfo_t *ESI, long long *values)
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
PAPI_sprofil_t ** prof
#define PAPI_HUGE_STR_LEN
Definition: fpapi.h:42
hwi_presets_t _papi_hwi_presets[PAPI_MAX_PRESET_EVENTS]
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:78
#define PAPI_VERB_ECONT
Definition: fpapi.h:39
#define DERIVED_INFIX
Definition: papi_internal.h:76
static int native
int _papi_hwi_innoculate_vector(papi_vector_t *v)
Definition: papi_vector.c:109
int _papi_hwi_lookup_EventCodeIndex(const EventSetInfo_t *ESI, unsigned int EventCode)
static int update_overflow(EventSetInfo_t *ESI)
#define NATIVE_EVENT_CHUNKSIZE
Definition: papi_internal.c:66
#define PAPI_MULTIPLEXING
Definition: fpapi.h:35
int _papi_hwi_add_event(EventSetInfo_t *ESI, int EventCode)
int _papi_hwi_get_native_event_info(unsigned int EventCode, PAPI_event_info_t *info)
#define PAPI_NULL
Definition: fpapi.h:13
unsigned int event_type
Definition: papi.h:993
void PAPIERROR(char *format,...)
static const hwi_describe_t _papi_hwi_derived[]
void _papi_hwi_shutdown_global_internal(void)
int _papi_hwi_get_preset_event_info(int EventCode, PAPI_event_info_t *info)
int mpx_add_event(MPX_EventSet **mpx_events, int EventCode, int domain, int granularity)
Definition: sw_multiplex.c:305
static int num_native_chunks
Definition: papi_internal.c:79
long long ret
Definition: iozone.c:1346
#define DERIVED_PS
Definition: papi_internal.h:71
static long long units_per_second(long long units, long long cycles)
int _papi_hwi_error_level
Definition: papi_internal.c:54
char short_descr[PAPI_MIN_STR_LEN]
Definition: papi.h:968
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
static int default_debug_handler(int errorCode)
static int num_error_chunks
Definition: papi_internal.c:82
int _papi_hwi_shutdown_cpu(CpuInfo_t *cpu)
Definition: cpus.c:306
NativeInfo_t * NativeInfoArray
int _papi_hwi_num_errors
Definition: papi_internal.c:58
char * short_descr
Definition: papi_preset.h:25
EventInfo_t * EventInfoArray
#define PAPI_STOPPED
Definition: fpapi.h:29
static int remove_native_events(EventSetInfo_t *ESI, int *nevt, int size)
long long * hw_start
#define PAPI_ERROR_CODE_str
Definition: papi_internal.h:41
static long long handle_derived_ps(int *position, long long *from)
PAPI_hw_info_t hw_info
EventSetMultiplexInfo_t multiplex
EventSetGranularityInfo_t granularity
hwd_context_t * _papi_hwi_get_context(EventSetInfo_t *ESI, int *is_dirty)
EventSetInfo_t ** dataSlotArray
static int val[12]
Definition: activity.c:47
int pos[PAPI_EVENTS_IN_DERIVED_EVENT]
va_end(arg_list)
int user_defined_events_count
Definition: papi_internal.c:60
long long * sw_stop
int(* PAPI_debug_handler_t)(int code)
Definition: papi.h:686
void _papi_hwi_set_papi_event_code(unsigned int event_code, int update_flag)
char name[PAPI_MAX_INFO_TERMS][PAPI_2MAX_STR_LEN]
Definition: papi.h:1010
int papi_num_components
#define INTERNAL_LOCK
Definition: papi_internal.h:86
#define papi_realloc(a, b)
Definition: papi_memory.h:36
int _papi_hwi_assign_eventset(EventSetInfo_t *ESI, int cidx)
static int add_native_fail_clean(EventSetInfo_t *ESI, int nevt)
hwi_presets_t user_defined_events[PAPI_MAX_USER_EVENTS]
Definition: papi_internal.c:59
char * long_descr
Definition: papi_preset.h:26
int _papi_hwi_init_global(void)
static char stack[2 *PAPI_HUGE_STR_LEN]
Definition: papi_preset.c:791
int component_index
Definition: papi.h:975
char ** _papi_errlist
Definition: papi_internal.c:81
int mpx_remove_event(MPX_EventSet **mpx_events, int EventCode)
Definition: sw_multiplex.c:418
#define PAPI_ENOEVNT
Definition: fpapi.h:112
int cpu_max_mhz
Definition: papi.h:797
static int _papi_hwi_lookup_error(char *error)
unsigned int code[PAPI_MAX_INFO_TERMS]
Definition: papi_preset.h:32
#define ISLEVEL(a)
Definition: papi_debug.h:54
char * name[PAPI_MAX_INFO_TERMS]
Definition: papi_preset.h:33
int _papi_hwi_component_index(int event_code)
#define PAPI_NATIVE_AND_MASK
unsigned int event_code
#define PAPI_PRESET_AND_MASK
struct papi_vectors * _papi_hwd[]
#define PAPI_NOT_INITED
Definition: fpapi.h:17
int _papi_hwi_publish_error(char *error)
static int _papi_hwi_add_native_event(int cidx, int ntv_event, int ntv_idx, const char *event_name)
int _papi_hwi_invalid_cmp(int cidx)
#define DEBUG_THREADS
Definition: papi_debug.h:30
void _papi_hwi_free_EventSet(EventSetInfo_t *ESI)
static long long handle_derived(EventInfo_t *evi, long long *from)
int _papi_hwi_prefix_component_name(char *component_name, char *event_name, char *out, int out_len)
int _papi_hwi_eventcode_to_native(int event_code)
char postfix[PAPI_2MAX_STR_LEN]
Definition: papi.h:999
#define PAPI_ECNFLCT
Definition: fpapi.h:113
#define PAPI_OVERFLOWING
Definition: fpapi.h:33
#define PAPI_ECOUNT
Definition: fpapi.h:128
EventSetInfo_t * ESI
EventSetProfileInfo_t profile
static int add_native_events(EventSetInfo_t *ESI, unsigned int *nevt, int size, EventInfo_t *out)
int init_level
Definition: papi_internal.c:53
hwd_control_state_t * ctl_state
#define DERIVED_ADD_PS
Definition: papi_internal.h:72
unsigned int event_code
Definition: papi.h:965
char * symbol
Definition: papi_preset.h:24
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
static long long handle_derived_add_ps(int *position, long long *from)
int _papi_hwi_cleanup_all_presets(void)
Definition: papi_preset.c:114
#define DERIVED_POSTFIX
Definition: papi_internal.h:75
char note[PAPI_HUGE_STR_LEN]
Definition: papi.h:1014
unsigned int count
Definition: papi_preset.h:29
static int create_EventSet(EventSetInfo_t **here)
#define PAPI_QUIET
Definition: fpapi.h:38
static int add_EventSet(EventSetInfo_t *ESI, ThreadInfo_t *master)
static int get_free_EventCodeIndex(const EventSetInfo_t *ESI, unsigned int EventCode)
void _papi_hwi_map_events_to_native(EventSetInfo_t *ESI)
int _papi_hwi_native_name_to_code(const char *in, int *out)
static long count
const char * _papi_hwi_strip_component_prefix(const char *event_name)
static int expand_dynamic_array(DynamicArray_t *DA)
int _papi_hwi_create_eventset(int *EventSet, ThreadInfo_t *handle)
#define papi_calloc(a, b)
Definition: papi_memory.h:37
void _papi_hwi_set_papi_event_string(const char *event_string)
Definition: papi_internal.c:90
static int papi_event_code_changed
int i
Definition: fileop.c:140
char * postfix
Definition: papi_preset.h:31
int sz
Definition: fileop.c:80
EventSetCpuInfo_t cpu
static int num_native_events
Definition: papi_internal.c:78