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