PAPI  5.3.2.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 
36 #include "papi.h"
37 #include "papi_internal.h"
38 #include "papi_vector.h"
39 #include "papi_memory.h"
40 #include "sw_multiplex.h"
41 #include "extras.h"
42 #include "papi_preset.h"
43 #include "cpus.h"
44 
45 #include "papi_common_strings.h"
46 
47 #include "papi_user_events.h"
48 
49 /* Advanced definitons */
50 static int default_debug_handler( int errorCode );
51 static long long handle_derived( EventInfo_t * evi, long long *from );
52 
53 /* Global definitions used by other files */
60 
61 /*****************************/
62 /* Native Event Mapping Code */
63 /*****************************/
64 
65 #define NATIVE_EVENT_CHUNKSIZE 1024
66 
68  int cidx;
70 };
71 
72 
74 static int num_native_events=0;
75 static int num_native_chunks=0;
76 
77 char **_papi_errlist= NULL;
78 static int num_error_chunks = 0;
79 
80 
81 
94 int
95 _papi_hwi_prefix_component_name( char *component_name, char *event_name, char *out, int out_len)
96 {
97  int size1, size2;
98  char temp[out_len];
99 
100  size1 = strlen(event_name);
101  size2 = strlen(component_name);
102 
103 /* sanity checks */
104  if ( size1 == 0 ) {
105  return (PAPI_EBUG); /* hopefully event_name always has length?! */
106  }
107 
108  if ( size1 >= out_len )
109  return (PAPI_ENOMEM);
110 
111 /* Guard against event_name == out */
112  memcpy( temp, event_name, out_len );
113 
114 /* no component name to prefix */
115  if ( size2 == 0 ) {
116  sprintf(out, "%s%c", temp, '\0' );
117  return (PAPI_OK);
118  }
119 
120 /* Don't prefix 'cpu' component names for now */
121  if ( strstr(component_name, "pe") ||
122  strstr(component_name, "bgq") ||
123  strstr(component_name, "bgp") ) {
124  sprintf( out, "%s%c", temp, '\0');
125  return (PAPI_OK);
126  }
127 
128 /* strlen(component_name) + ::: + strlen(event_name) + NULL */
129  if ( size1+size2+3+1 > out_len )
130  return (PAPI_ENOMEM);
131 
132  sprintf( out, "%s:::%s%c" , component_name, temp, '\0');
133  return (PAPI_OK);
134 }
135 
147 {
148  char *start = NULL;
149 /* We assume ::: is the seperator
150  * eg:
151  * papi_component:::event_name
152  */
153 
154  start = strstr( event_name, ":::" );
155  if ( start != NULL )
156  start+= 3; /* return the actual start of event_name */
157  else
158  start = event_name;
159 
160  return (start);
161 }
162 
163 static int
165 
166  int i;
167 
168  for(i=0;i<num_native_events;i++) {
169  if ((_papi_native_events[i].cidx==cidx) &&
170  (_papi_native_events[i].component_event==event)) {
171  return i|PAPI_NATIVE_MASK;
172  }
173  }
174 
175  return PAPI_ENOEVNT;
176 
177 }
178 
179 static int
181 
182  int new_native_event;
183 
184  SUBDBG("Creating Event %#x which is comp %d internal %#x\n",
186 
188 
191  _papi_native_events=realloc(_papi_native_events,
192  num_native_chunks*NATIVE_EVENT_CHUNKSIZE*
193  sizeof(struct native_event_info));
194  if (_papi_native_events==NULL) {
195  new_native_event=PAPI_ENOMEM;
196  goto native_alloc_early_out;
197  }
198  }
199 
200  _papi_native_events[num_native_events].cidx=cidx;
201  _papi_native_events[num_native_events].component_event=event;
202  new_native_event=num_native_events|PAPI_NATIVE_MASK;
203 
205 
206 native_alloc_early_out:
207 
209 
210  return new_native_event;
211 }
212 
219 static int
220 _papi_hwi_add_error( char *error )
221 {
222  SUBDBG("Adding a new Error message |%s|\n", error);
224 
227  _papi_errlist=realloc(_papi_errlist,
228  num_error_chunks*NATIVE_EVENT_CHUNKSIZE*sizeof(char *));
229  if (_papi_errlist==NULL) {
231  goto bail;
232  }
233 
234  }
235 
236  _papi_errlist[_papi_hwi_num_errors] = strdup( error );
237  if ( _papi_errlist[_papi_hwi_num_errors] == NULL )
239 
240 bail:
242 
243  return _papi_hwi_num_errors++;
244 }
245 
246 static void
248 {
249  int i;
250 
251  if ( _papi_errlist == NULL ||
252  _papi_hwi_num_errors == 0 )
253  return;
254 
255 
257  for (i=0; i < _papi_hwi_num_errors; i++ ) {
258  free( _papi_errlist[i]);
259  _papi_errlist[i] = NULL;
260  }
261 
262  free( _papi_errlist );
263  _papi_errlist = NULL;
264  _papi_hwi_num_errors = 0;
266 
268 }
269 
270 static int
271 _papi_hwi_lookup_error( char *error )
272 {
273  int i;
274 
275  for (i=0; i<_papi_hwi_num_errors; i++) {
276  if ( !strncasecmp( _papi_errlist[i], error, strlen( error ) ) )
277  return i;
278 
279  }
280 
281  return (-1);
282 }
283 
294 int _papi_hwi_publish_error( char *error )
295 {
296  int error_code = -1;
297 
298  if ( (error_code = _papi_hwi_lookup_error( error )) < 0 )
299  error_code = _papi_hwi_add_error(error);
300 
301  return (-error_code); /* internally error_code is an index, externally, it should be <= 0 */
302 }
303 
304 void
306 /* we use add error to avoid the cost of lookups, we know the errors are not there yet */
307  _papi_hwi_add_error("No error");
308  _papi_hwi_add_error("Invalid argument");
309  _papi_hwi_add_error("Insufficient memory");
310  _papi_hwi_add_error("A System/C library call failed");
311  _papi_hwi_add_error("Not supported by component");
312  _papi_hwi_add_error("Access to the counters was lost or interrupted");
313  _papi_hwi_add_error("Internal error, please send mail to the developers");
314  _papi_hwi_add_error("Event does not exist");
315  _papi_hwi_add_error("Event exists, but cannot be counted due to hardware resource limits");
316  _papi_hwi_add_error("EventSet is currently not running");
317  _papi_hwi_add_error("EventSet is currently counting");
318  _papi_hwi_add_error("No such EventSet available");
319  _papi_hwi_add_error("Event in argument is not a valid preset");
320  _papi_hwi_add_error("Hardware does not support performance counters");
321  _papi_hwi_add_error("Unknown error code");
322  _papi_hwi_add_error("Permission level does not permit operation");
323  _papi_hwi_add_error("PAPI hasn't been initialized yet");
324  _papi_hwi_add_error("Component Index isn't set");
325  _papi_hwi_add_error("Not supported");
326  _papi_hwi_add_error("Not implemented");
327  _papi_hwi_add_error("Buffer size exceeded");
328  _papi_hwi_add_error("EventSet domain is not supported for the operation");
329  _papi_hwi_add_error("Invalid or missing event attributes");
330  _papi_hwi_add_error("Too many events or attributes");
331  _papi_hwi_add_error("Bad combination of features");
332 }
333 
334 int
336 {
337  return ( cidx < 0 || cidx >= papi_num_components );
338 }
339 
340 
341 int
342 _papi_hwi_component_index( int event_code ) {
343 
344  int cidx;
345  int event_index;
346 
347  SUBDBG("Trying to find component for native_event %#x\n",event_code);
348 
349  /* currently assume presets are for component 0 only */
350  if (event_code&PAPI_PRESET_MASK) {
351  SUBDBG("Event %#x is a PRESET, assigning component %d\n",
352  event_code,0);
353  return 0;
354  }
355 
356  event_index=event_code&PAPI_NATIVE_AND_MASK;
357 
358  if ( (event_index < 0) || (event_index>=num_native_events)) {
359  SUBDBG("Event index %#x is out of range\n",event_index);
360  return PAPI_ENOEVNT;
361  }
362 
363  cidx=_papi_native_events[event_index].cidx;
364 
365  SUBDBG("Found event code %d from %d, %#x\n",cidx,event_index,event_code);
366 
367  if ((cidx<0) || (cidx >= papi_num_components)) return PAPI_ENOCMP;
368 
369  return cidx;
370 }
371 
372 /* Convert a component and internal event to a native_event */
373 int
374 _papi_hwi_native_to_eventcode(int cidx, int event_code) {
375 
376  int result;
377 
378  SUBDBG("Looking for component %d event %#x\n",cidx,event_code);
379 
380  result=_papi_hwi_find_native_event(cidx,event_code);
381  if (result==PAPI_ENOEVNT) {
382  /* Need to allocate */
383  result=_papi_hwi_add_native_event(event_code,cidx);
384  }
385 
386  return result;
387 }
388 
389 /* Convert a native_event code to an internal event code */
390 int
392 
393  int result;
394  int event_index;
395 
396  SUBDBG("Looking for event for native_event %#x\n",event_code);
397 
398  event_index=event_code&PAPI_NATIVE_AND_MASK;
399  if (event_index>=num_native_events) return PAPI_ENOEVNT;
400 
401  result=_papi_native_events[event_index].component_event;
402 
403  SUBDBG("Found result %#x\n",result);
404 
405  return result;
406 
407 }
408 
409 
410 /*********************/
411 /* Utility functions */
412 /*********************/
413 
414 void
415 PAPIERROR( char *format, ... )
416 {
417  va_list args;
418  if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
419  ( getenv( "PAPI_VERBOSE" ) ) ) {
420  va_start( args, format );
421  fprintf( stderr, "PAPI Error: " );
422  vfprintf( stderr, format, args );
423  fprintf( stderr, ".\n" );
424  va_end( args );
425  }
426 }
427 
428 static int
429 default_debug_handler( int errorCode )
430 {
431  char str[PAPI_HUGE_STR_LEN];
432 
433  if ( errorCode == PAPI_OK )
434  return ( errorCode );
435  if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) {
436  PAPIERROR( "%s %d,%s,Bug! Unknown error code", PAPI_ERROR_CODE_str,
437  errorCode, "" );
438  return ( PAPI_EBUG );
439  }
440 
441  switch ( _papi_hwi_error_level ) {
442  case PAPI_VERB_ECONT:
443  case PAPI_VERB_ESTOP:
444  /* gcc 2.96 bug fix, do not change */
445  /* fprintf(stderr,"%s %d: %s: %s\n",PAPI_ERROR_CODE_str,errorCode,_papi_hwi_err[-errorCode].name,_papi_hwi_err[-errorCode].descr); */
446 
447  sprintf( str, "%s %d,%s", PAPI_ERROR_CODE_str, errorCode,
448  _papi_errlist[-errorCode] );
449  if ( errorCode == PAPI_ESYS )
450  sprintf( str + strlen( str ), ": %s", strerror( errno ) );
451 
452  PAPIERROR( str );
453 
455  abort( ); /* patch provided by will cohen of redhat */
456  else
457  return errorCode;
458  break;
459 
460  case PAPI_QUIET:
461  default:
462  return errorCode;
463  }
464  return ( PAPI_EBUG ); /* Never get here */
465 }
466 
467 static int
469 {
470  /* Allocate and clear the Dynamic Array structure */
471  if ( map->dataSlotArray != NULL )
472  papi_free( map->dataSlotArray );
473  memset( map, 0x00, sizeof ( DynamicArray_t ) );
474 
475  /* Allocate space for the EventSetInfo_t pointers */
476 
477  map->dataSlotArray =
479  sizeof ( EventSetInfo_t * ) );
480  if ( map->dataSlotArray == NULL ) {
481  return ( PAPI_ENOMEM );
482  }
483  memset( map->dataSlotArray, 0x00,
487  map->fullSlots = 0;
488 
489  return ( PAPI_OK );
490 }
491 
492 static int
494 {
495  int number;
496  EventSetInfo_t **n;
497 
498  /*realloc existing PAPI_EVENTSET_MAP.dataSlotArray */
499 
500  number = DA->totalSlots * 2;
501  n = ( EventSetInfo_t ** ) papi_realloc( DA->dataSlotArray,
502  ( size_t ) number *
503  sizeof ( EventSetInfo_t * ) );
504  if ( n == NULL )
505  return ( PAPI_ENOMEM );
506 
507  /* Need to assign this value, what if realloc moved it? */
508 
509  DA->dataSlotArray = n;
510 
511  memset( DA->dataSlotArray + DA->totalSlots, 0x00,
512  ( size_t ) DA->totalSlots * sizeof ( EventSetInfo_t * ) );
513 
514  DA->totalSlots = number;
515  DA->availSlots = number - DA->fullSlots;
516 
517  return ( PAPI_OK );
518 }
519 
520 static int
522 {
523  return ( _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs );
524 }
525 
526 
527 
528 
529 
530 /*========================================================================*/
531 /* This function allocates space for one EventSetInfo_t structure and for */
532 /* all of the pointers in this structure. If any malloc in this function */
533 /* fails, all memory malloced to the point of failure is freed, and NULL */
534 /* is returned. Upon success, a pointer to the EventSetInfo_t data */
535 /* structure is returned. */
536 /*========================================================================*/
537 
538 
539 static int
541 {
542  EventSetInfo_t *ESI;
543 
544  ESI = ( EventSetInfo_t * ) papi_calloc( 1, sizeof ( EventSetInfo_t ) );
545  if ( ESI == NULL ) {
546  return PAPI_ENOMEM;
547  }
548 
549  *here = ESI;
550 
551  return PAPI_OK;
552 }
553 
554 int
556 {
557  int retval;
558  size_t max_counters;
559  char *ptr;
560  unsigned int i, j;
561 
562  /* If component doesn't exist... */
563  if (_papi_hwi_invalid_cmp(cidx)) return PAPI_ECMP;
564 
565  /* Assigned at create time */
566  ESI->domain.domain = _papi_hwd[cidx]->cmp_info.default_domain;
567  ESI->granularity.granularity =
568  _papi_hwd[cidx]->cmp_info.default_granularity;
569  ESI->CmpIdx = cidx;
570 
571  /* ??? */
572  max_counters = ( size_t ) _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
573 
574  ESI->ctl_state = (hwd_control_state_t *) papi_calloc( 1, (size_t)
575  _papi_hwd[cidx]->size.control_state );
576  ESI->sw_stop = (long long *) papi_calloc( ( size_t ) max_counters,
577  sizeof ( long long ) );
578  ESI->hw_start = ( long long * ) papi_calloc( ( size_t ) max_counters,
579  sizeof ( long long ) );
580  ESI->EventInfoArray = ( EventInfo_t * ) papi_calloc( (size_t) max_counters,
581  sizeof ( EventInfo_t ) );
582 
583  /* allocate room for the native events and for the component-private */
584  /* register structures */
585  /* ugh is there a cleaner way to allocate this? vmw */
586  ESI->NativeInfoArray = ( NativeInfo_t * )
587  papi_calloc( ( size_t ) max_counters, sizeof ( NativeInfo_t ));
588 
589  ESI->NativeBits = papi_calloc(( size_t ) max_counters,
590  ( size_t ) _papi_hwd[cidx]->size.reg_value );
591 
592  /* NOTE: the next two malloc allocate blocks of memory that are later */
593  /* parcelled into overflow and profile arrays */
594  ESI->overflow.deadline = ( long long * )
595  papi_malloc( ( sizeof ( long long ) +
596  sizeof ( int ) * 3 ) * ( size_t ) max_counters );
597 
598  ESI->profile.prof = ( PAPI_sprofil_t ** )
599  papi_malloc( ( sizeof ( PAPI_sprofil_t * ) * ( size_t ) max_counters +
600  ( size_t ) max_counters * sizeof ( int ) * 4 ) );
601 
602  /* If any of these allocations failed, free things up and fail */
603 
604  if ( ( ESI->ctl_state == NULL ) ||
605  ( ESI->sw_stop == NULL ) ||
606  ( ESI->hw_start == NULL ) ||
607  ( ESI->NativeInfoArray == NULL ) ||
608  ( ESI->NativeBits == NULL ) ||
609  ( ESI->EventInfoArray == NULL ) ||
610  ( ESI->profile.prof == NULL ) ||
611  ( ESI->overflow.deadline == NULL ) ) {
612 
613  if ( ESI->sw_stop ) papi_free( ESI->sw_stop );
614  if ( ESI->hw_start ) papi_free( ESI->hw_start );
615  if ( ESI->EventInfoArray ) papi_free( ESI->EventInfoArray );
616  if ( ESI->NativeInfoArray ) papi_free( ESI->NativeInfoArray );
617  if ( ESI->NativeBits ) papi_free( ESI->NativeBits );
618  if ( ESI->ctl_state ) papi_free( ESI->ctl_state );
619  if ( ESI->overflow.deadline ) papi_free( ESI->overflow.deadline );
620  if ( ESI->profile.prof ) papi_free( ESI->profile.prof );
621  papi_free( ESI );
622  return PAPI_ENOMEM;
623  }
624 
625 
626  /* Carve up the overflow block into separate arrays */
627  ptr = ( char * ) ESI->overflow.deadline;
628  ptr += sizeof ( long long ) * max_counters;
629  ESI->overflow.threshold = ( int * ) ptr;
630  ptr += sizeof ( int ) * max_counters;
631  ESI->overflow.EventIndex = ( int * ) ptr;
632  ptr += sizeof ( int ) * max_counters;
633  ESI->overflow.EventCode = ( int * ) ptr;
634 
635  /* Carve up the profile block into separate arrays */
636  ptr = ( char * ) ESI->profile.prof +
637  ( sizeof ( PAPI_sprofil_t * ) * max_counters );
638  ESI->profile.count = ( int * ) ptr;
639  ptr += sizeof ( int ) * max_counters;
640  ESI->profile.threshold = ( int * ) ptr;
641  ptr += sizeof ( int ) * max_counters;
642  ESI->profile.EventIndex = ( int * ) ptr;
643  ptr += sizeof ( int ) * max_counters;
644  ESI->profile.EventCode = ( int * ) ptr;
645 
646  /* initialize_EventInfoArray */
647 
648  for ( i = 0; i < max_counters; i++ ) {
649  ESI->EventInfoArray[i].event_code=( unsigned int ) PAPI_NULL;
650  ESI->EventInfoArray[i].ops = NULL;
652  for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
653  ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
654  }
655  }
656 
657  /* initialize_NativeInfoArray */
658  for( i = 0; i < max_counters; i++ ) {
659  ESI->NativeInfoArray[i].ni_event = -1;
660  ESI->NativeInfoArray[i].ni_position = -1;
661  ESI->NativeInfoArray[i].ni_owners = 0;
662  ESI->NativeInfoArray[i].ni_bits = ((unsigned char*)ESI->NativeBits) +
663  (i*_papi_hwd[cidx]->size.reg_value);
664  }
665 
666  ESI->NativeCount = 0;
667 
668  ESI->state = PAPI_STOPPED;
669 
670  /* these used to be init_config */
671  retval = _papi_hwd[cidx]->init_control_state( ESI->ctl_state );
672  retval |= _papi_hwd[cidx]->set_domain( ESI->ctl_state, ESI->domain.domain);
673 
674  return retval;
675 }
676 
677 /*========================================================================*/
678 /* This function should free memory for one EventSetInfo_t structure. */
679 /* The argument list consists of a pointer to the EventSetInfo_t */
680 /* structure, *ESI. */
681 /* The calling function should check for ESI==NULL. */
682 /*========================================================================*/
683 
684 void
686 {
688 
689 #ifdef DEBUG
690  memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
691 #endif
692  papi_free( ESI );
693 
694 }
695 
696 static int
698 {
699  DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
700  int i, errorCode;
701 
703 
704  if ( map->availSlots == 0 ) {
705  errorCode = expand_dynamic_array( map );
706  if ( errorCode < PAPI_OK ) {
708  return ( errorCode );
709  }
710  }
711 
712  i = 0;
713  for ( i = 0; i < map->totalSlots; i++ ) {
714  if ( map->dataSlotArray[i] == NULL ) {
715  ESI->master = master;
716  ESI->EventSetIndex = i;
717  map->fullSlots++;
718  map->availSlots--;
719  map->dataSlotArray[i] = ESI;
721  return ( PAPI_OK );
722  }
723  }
724 
726  return ( PAPI_EBUG );
727 }
728 
729 int
731 {
732  EventSetInfo_t *ESI;
733  int retval;
734 
735  /* Is the EventSet already in existence? */
736 
737  if ( ( EventSet == NULL ) || ( handle == NULL ) )
738  return PAPI_EINVAL;
739 
740  if ( *EventSet != PAPI_NULL )
741  return PAPI_EINVAL;
742 
743  /* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
744 
745  retval = create_EventSet( &ESI );
746  if ( retval != PAPI_OK )
747  return retval;
748 
749  ESI->CmpIdx = -1; /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
750  ESI->state = PAPI_STOPPED;
751 
752  /* Add it to the global table */
753 
754  retval = add_EventSet( ESI, handle );
755  if ( retval < PAPI_OK ) {
757  return retval ;
758  }
759 
760  *EventSet = ESI->EventSetIndex;
761 
762  INTDBG( "(%p,%p): new EventSet in slot %d\n",
763  ( void * ) EventSet, handle, *EventSet );
764 
765  return retval;
766 }
767 
768 /* This function returns the index of the the next free slot
769  in the EventInfoArray. If EventCode is already in the list,
770  it returns PAPI_ECNFLCT. */
771 
772 static int
773 get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
774 {
775  int k;
776  int lowslot = PAPI_ECNFLCT;
777  int limit = EventInfoArrayLength( ESI );
778 
779  /* Check for duplicate events and get the lowest empty slot */
780 
781  for ( k = 0; k < limit; k++ ) {
782  if ( ESI->EventInfoArray[k].event_code == EventCode )
783  return ( PAPI_ECNFLCT );
784  /*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
785  if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
786  lowslot = k;
787  break;
788  }
789  }
790  return ( lowslot );
791 }
792 
793 /* This function returns the index of the EventCode or error */
794 /* Index to what? The index to everything stored EventCode in the */
795 /* EventSet. */
796 
797 int
799  unsigned int EventCode )
800 {
801  int i;
802  int limit = EventInfoArrayLength( ESI );
803 
804  for ( i = 0; i < limit; i++ ) {
805  if ( ESI->EventInfoArray[i].event_code == EventCode ) {
806  return i;
807  }
808  }
809 
810  return PAPI_EINVAL;
811 }
812 
813 /* This function only removes empty EventSets */
814 
815 int
817 {
818  DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
819  int i;
820 
821  i = ESI->EventSetIndex;
822 
824 
826 
827  /* do bookkeeping for PAPI_EVENTSET_MAP */
828 
829  map->dataSlotArray[i] = NULL;
830  map->availSlots++;
831  map->fullSlots--;
832 
834 
835  return PAPI_OK;
836 }
837 
838 
839 /* this function checks if an event is already in an EventSet
840  Success, return ESI->NativeInfoArray[] index
841  Fail, return PAPI_ENOEVNT;
842 */
843 static int
845 {
846  int i;
847 
848  /* to find the native event from the native events list */
849  for( i = 0; i < ESI->NativeCount; i++ ) {
850  if ( _papi_hwi_eventcode_to_native(nevt) ==
851  ESI->NativeInfoArray[i].ni_event ) {
852  INTDBG( "found native event already mapped: %#x\n", nevt );
853  return i;
854  }
855  }
856  return PAPI_ENOEVNT;
857 }
858 
859 /* This function goes through the events in an EventSet's EventInfoArray */
860 /* And maps each event (whether native or part of a preset) to */
861 /* an event in the EventSets NativeInfoArray. */
862 
863 /* We need to do this every time a native event is added to or removed */
864 /* from an eventset. */
865 
866 /* It is also called after a update controlstate as the components are */
867 /* allowed to re-arrange the native events to fit hardware constraints. */
868 
869 void
871 {
872 
873  int i, event, k, n, preset_index = 0, nevt;
874  int total_events = ESI->NumberOfEvents;
875 
876  APIDBG("Mapping %d events in EventSet %d\n",
877  total_events,ESI->EventSetIndex);
878 
879  event = 0;
880  for( i = 0; i < total_events; i++ ) {
881 
882  /* find the first event that isn't PAPI_NULL */
883  /* Is this really necessary? --vmw */
884  while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
885  event++;
886  }
887 
888  /* If it's a preset */
889  if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
890  preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
891 
892  /* walk all sub-events in the preset */
893  for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
894  nevt = _papi_hwi_presets[preset_index].code[k];
895  if ( nevt == PAPI_NULL ) {
896  break;
897  }
898 
899  APIDBG("Loking for subevent %#x\n",nevt);
900 
901  /* Match each sub-event to something in the Native List */
902  for( n = 0; n < ESI->NativeCount; n++ ) {
903  if ( _papi_hwi_eventcode_to_native(nevt) ==
904  ESI->NativeInfoArray[n].ni_event ) {
905  APIDBG("Found event %#x at position %d\n",
906  nevt,
907  ESI->NativeInfoArray[n].ni_position);
909  break;
910  }
911  }
912  }
913  }
914  /* It's a native event */
915  else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
916  nevt = ( int ) ESI->EventInfoArray[event].event_code;
917 
918  /* Look for the event in the NativeInfoArray */
919  for( n = 0; n < ESI->NativeCount; n++ ) {
920  if ( _papi_hwi_eventcode_to_native(nevt) ==
921  ESI->NativeInfoArray[n].ni_event ) {
923  break;
924  }
925  }
926  /* It's a user-defined event */
927  } else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
928  for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
929  nevt = _papi_user_events[preset_index].events[k];
930  if ( nevt == PAPI_NULL ) break;
931 
932  /* Match each sub-event to something in the Native List */
933  for ( n = 0; n < ESI->NativeCount; n++ ) {
936  }
937  }
938  }
939  }
940  event++;
941  }
942 }
943 
944 
945 static int
947 {
948  int i, max_counters;
949  int cidx;
950 
951  cidx = _papi_hwi_component_index( nevt );
952  if (cidx<0) return PAPI_ENOCMP;
953 
954  max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
955 
956  /* to find the native event from the native events list */
957  for( i = 0; i < max_counters; i++ ) {
958  if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[i].ni_event ) {
959  ESI->NativeInfoArray[i].ni_owners--;
960  /* to clean the entry in the nativeInfo array */
961  if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
962  ESI->NativeInfoArray[i].ni_event = -1;
963  ESI->NativeInfoArray[i].ni_position = -1;
964  ESI->NativeCount--;
965  }
966  INTDBG( "add_events fail, and remove added native events "
967  "of the event: %#x\n", nevt );
968  return i;
969  }
970  }
971  return -1;
972 }
973 
974 /* since update_control_state trashes overflow settings, this puts things
975  back into balance. */
976 static int
978 {
979  int i, retval = PAPI_OK;
980 
981  if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
982  for( i = 0; i < ESI->overflow.event_counter; i++ ) {
983  retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
984  ESI->overflow.EventIndex[i],
985  ESI->overflow.threshold[i] );
986  if ( retval != PAPI_OK ) {
987  break;
988  }
989  }
990  }
991  return retval;
992 }
993 
994 /* this function is called by _papi_hwi_add_event when adding native events
995  ESI: event set to add the events to
996  nevnt: pointer to array of native event table indexes to add
997  size: number of native events to add
998  out: ???
999 
1000  return: < 0 = error
1001  0 = no new events added
1002  1 = new events added
1003 */
1004 static int
1005 add_native_events( EventSetInfo_t *ESI, unsigned int *nevt,
1006  int size, EventInfo_t *out )
1007 {
1008  int nidx, i, j, added_events = 0;
1009  int retval, retval2;
1010  int max_counters;
1011  hwd_context_t *context;
1012 
1013  max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1014 
1015  /* Walk through the list of native events, adding them */
1016  for( i = 0; i < size; i++ ) {
1017 
1018  /* Check to see if event is already in EventSet */
1019  nidx = event_already_in_eventset( ESI, nevt[i] );
1020 
1021  if ( nidx >= 0 ) {
1022  /* Event is already there. Set position */
1023  out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
1024  ESI->NativeInfoArray[nidx].ni_owners++;
1025 
1026  } else {
1027 
1028  /* Event wasn't already there */
1029 
1030  if ( ESI->NativeCount == max_counters ) {
1031 
1032  /* No more room in counters! */
1033  for( j = 0; j < i; j++ ) {
1034  if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
1035  out->pos[j] = -1;
1036  continue;
1037  }
1038  INTDBG( "should not happen!\n" );
1039  }
1040  INTDBG( "counters are full!\n" );
1041  return PAPI_ECOUNT;
1042  }
1043  else {
1044 
1045  /* there is an empty slot for the native event; */
1046  /* initialize the native index for the new added event */
1047  INTDBG( "Adding %#x to ESI %p Component %d\n",
1048  nevt[i], ESI, ESI->CmpIdx );
1049  ESI->NativeInfoArray[ESI->NativeCount].ni_event =
1051 
1052  ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
1053  ESI->NativeCount++;
1054  added_events++;
1055  }
1056  }
1057  }
1058 
1059  /* if we added events we need to tell the component so it */
1060  /* can add them too. */
1061  if ( added_events ) {
1062  /* get the context we should use for this event set */
1063  context = _papi_hwi_get_context( ESI, NULL );
1064 
1065  if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
1066 
1067  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1068  ESI->NativeInfoArray,
1069  ESI->NativeCount,
1070  context);
1071  if ( retval != PAPI_OK ) {
1072 clean:
1073  for( i = 0; i < size; i++ ) {
1074  if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
1075  out->pos[i] = -1;
1076  continue;
1077  }
1078  INTDBG( "should not happen!\n" );
1079  }
1080  /* re-establish the control state after the previous error */
1081  retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state(
1082  ESI->ctl_state,
1083  ESI->NativeInfoArray,
1084  ESI->NativeCount,
1085  context);
1086  if ( retval2 != PAPI_OK ) {
1087  PAPIERROR("update_control_state failed to re-establish "
1088  "working events!" );
1089  return retval2;
1090  }
1091  return retval;
1092  }
1093  return 1; /* need remap */
1094  } else {
1095  retval = PAPI_EMISC;
1096  goto clean;
1097  }
1098  }
1099  return PAPI_OK;
1100 }
1101 
1102 
1103 int
1104 _papi_hwi_add_event( EventSetInfo_t * ESI, int EventCode )
1105 {
1106  int i, j, thisindex, remap, retval = PAPI_OK;
1107  int cidx;
1108 
1109  cidx=_papi_hwi_component_index( EventCode );
1110  if (cidx<0) return PAPI_ENOCMP;
1111 
1112  /* Sanity check that the new EventCode is from the same component */
1113  /* as previous events. */
1114 
1115  if ( ESI->CmpIdx < 0 ) {
1116  if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx)) != PAPI_OK ) {
1117  return retval;
1118  }
1119  } else {
1120  if ( ESI->CmpIdx != cidx ) {
1121  return PAPI_EINVAL;
1122  }
1123  }
1124 
1125  /* Make sure the event is not present and get the next free slot. */
1126  thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1127  if ( thisindex < PAPI_OK ) {
1128  return thisindex;
1129  }
1130 
1131  APIDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
1132 
1133  /* If it is a software MPX EventSet, add it to the multiplex data structure */
1134  /* and this thread's multiplex list */
1135 
1136  if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
1137 
1138  /* Handle preset case */
1139  if ( IS_PRESET(EventCode) ) {
1140  int count;
1141  int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
1142 
1143  /* Check if it's within the valid range */
1144  if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
1145  return PAPI_EINVAL;
1146  }
1147 
1148  /* count the number of native events in this preset */
1149  count = ( int ) _papi_hwi_presets[preset_index].count;
1150 
1151  /* Check if event exists */
1152  if ( !count ) {
1153  return PAPI_ENOEVNT;
1154  }
1155 
1156  /* check if the native events have been used as overflow events */
1157  /* this is not allowed */
1158  if ( ESI->state & PAPI_OVERFLOWING ) {
1159  for( i = 0; i < count; i++ ) {
1160  for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1161  if ( ESI->overflow.EventCode[j] ==(int)
1162  ( _papi_hwi_presets[preset_index].code[i] ) ) {
1163  return PAPI_ECNFLCT;
1164  }
1165  }
1166  }
1167  }
1168 
1169  /* Try to add the preset. */
1170 
1171  remap = add_native_events( ESI,
1172  _papi_hwi_presets[preset_index].code,
1173  count, &ESI->EventInfoArray[thisindex] );
1174  if ( remap < 0 ) {
1175  return remap;
1176  }
1177  else {
1178  /* Fill in the EventCode (machine independent) information */
1179  ESI->EventInfoArray[thisindex].event_code =
1180  ( unsigned int ) EventCode;
1181  ESI->EventInfoArray[thisindex].derived =
1182  _papi_hwi_presets[preset_index].derived_int;
1183  ESI->EventInfoArray[thisindex].ops =
1184  _papi_hwi_presets[preset_index].postfix;
1185  ESI->NumberOfEvents++;
1187 
1188  }
1189  }
1190  /* Handle adding Native events */
1191  else if ( IS_NATIVE(EventCode) ) {
1192 
1193  /* Check if native event exists */
1194  if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
1195  return PAPI_ENOEVNT;
1196  }
1197 
1198  /* check if the native events have been used as overflow events */
1199  /* This is not allowed */
1200  if ( ESI->state & PAPI_OVERFLOWING ) {
1201  for( j = 0; j < ESI->overflow.event_counter; j++ ) {
1202  if ( EventCode == ESI->overflow.EventCode[j] ) {
1203  return PAPI_ECNFLCT;
1204  }
1205  }
1206  }
1207 
1208  /* Try to add the native event. */
1209 
1210  remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
1211  &ESI->EventInfoArray[thisindex] );
1212 
1213  if ( remap < 0 ) {
1214  return remap;
1215  } else {
1216 
1217  /* Fill in the EventCode (machine independent) information */
1218  ESI->EventInfoArray[thisindex].event_code =
1219  ( unsigned int ) EventCode;
1220  ESI->NumberOfEvents++;
1222 
1223  }
1224  } else if ( IS_USER_DEFINED( EventCode ) ) {
1225  int count;
1226  int index = EventCode & PAPI_UE_AND_MASK;
1227 
1228  if ( index < 0 || index >= (int)_papi_user_events_count )
1229  return ( PAPI_EINVAL );
1230 
1231  count = ( int ) _papi_user_events[index].count;
1232 
1233  for ( i = 0; i < count; i++ ) {
1234  for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
1235  if ( ESI->overflow.EventCode[j] ==
1236  _papi_user_events[index].events[i] ) {
1237  return ( PAPI_EBUG );
1238  }
1239  }
1240  }
1241 
1242  remap = add_native_events( ESI,
1243  (unsigned int*)_papi_user_events[index].events,
1244  count, &ESI->EventInfoArray[thisindex] );
1245 
1246  if ( remap < 0 ) {
1247  return remap;
1248  } else {
1249  ESI->EventInfoArray[thisindex].event_code
1250  = (unsigned int) EventCode;
1251  ESI->EventInfoArray[thisindex].derived
1252  = DERIVED_POSTFIX;
1253  ESI->EventInfoArray[thisindex].ops
1254  = _papi_user_events[index].operation;
1255  ESI->NumberOfEvents++;
1257  }
1258  } else {
1259 
1260  /* not Native, Preset, or User events */
1261 
1262  return PAPI_EBUG;
1263  }
1264  }
1265  else {
1266 
1267  /* Multiplexing is special. See multiplex.c */
1268 
1269  retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
1270  ESI->domain.domain,
1271  ESI->granularity.granularity );
1272 
1273 
1274  if ( retval < PAPI_OK ) {
1275  return retval;
1276  }
1277 
1278  /* Relevant (???) */
1279  ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;
1280  ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
1281 
1282  ESI->NumberOfEvents++;
1283 
1284  /* event is in the EventInfoArray but not mapped to the NativeEvents */
1285  /* this causes issues if you try to set overflow on the event. */
1286  /* in theory this wouldn't matter anyway. */
1287  }
1288 
1289  /* reinstate the overflows if any */
1290  retval=update_overflow( ESI );
1291 
1292  return retval;
1293 }
1294 
1295 static int
1297 {
1299  hwd_context_t *context;
1300  int i, j, zero = 0, retval;
1301 
1302  /* Remove the references to this event from the native events:
1303  for all the metrics in this event,
1304  compare to each native event in this event set,
1305  and decrement owners if they match */
1306  for( i = 0; i < size; i++ ) {
1307  for( j = 0; j < ESI->NativeCount; j++ ) {
1308  if ( native[j].ni_event == _papi_hwi_eventcode_to_native(nevt[i]) ) {
1309  native[j].ni_owners--;
1310  if ( native[j].ni_owners == 0 ) {
1311  zero++;
1312  }
1313  break;
1314  }
1315  }
1316  }
1317 
1318  /* Remove any native events from the array if owners dropped to zero.
1319  The NativeInfoArray must be dense, with no empty slots, so if we
1320  remove an element, we must compact the list */
1321  for( i = 0; i < ESI->NativeCount; i++ ) {
1322 
1323  if ( native[i].ni_event == -1 ) continue;
1324 
1325  if ( native[i].ni_owners == 0 ) {
1326  int copy = 0;
1327  int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
1328  for( j = ESI->NativeCount - 1; j > i; j-- ) {
1329  if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
1330  else {
1331  /* copy j into i */
1332  native[i].ni_event = native[j].ni_event;
1333  native[i].ni_position = native[j].ni_position;
1334  native[i].ni_owners = native[j].ni_owners;
1335  /* copy opaque [j].ni_bits to [i].ni_bits */
1336  memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
1337  /* reset j to initialized state */
1338  native[j].ni_event = -1;
1339  native[j].ni_position = -1;
1340  native[j].ni_owners = 0;
1341  copy++;
1342  break;
1343  }
1344  }
1345 
1346  if ( copy == 0 ) {
1347  /* set this structure back to empty state */
1348  /* ni_owners is already 0 and contents of ni_bits doesn't matter */
1349  native[i].ni_event = -1;
1350  native[i].ni_position = -1;
1351  }
1352  }
1353  }
1354 
1355  /* to reset hwd_control_state values */
1356  ESI->NativeCount -= zero;
1357 
1358  /* If we removed any elements,
1359  clear the now empty slots, reinitialize the index, and update the count.
1360  Then send the info down to the component to update the hwd control structure. */
1361  retval = PAPI_OK;
1362  if ( zero ) {
1363  /* get the context we should use for this event set */
1364  context = _papi_hwi_get_context( ESI, NULL );
1365  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1366  native, ESI->NativeCount, context);
1367  if ( retval == PAPI_OK )
1368  retval = update_overflow( ESI );
1369  }
1370  return ( retval );
1371 }
1372 
1373 int
1375 {
1376  int j = 0, retval, thisindex;
1377  EventInfo_t *array;
1378 
1379  thisindex =
1380  _papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
1381  if ( thisindex < PAPI_OK )
1382  return ( thisindex );
1383 
1384  /* If it is a MPX EventSet, remove it from the multiplex data structure and
1385  this threads multiplex list */
1386 
1387  if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1388  retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1389  if ( retval < PAPI_OK )
1390  return ( retval );
1391  } else
1392  /* Remove the events hardware dependent stuff from the EventSet */
1393  {
1394  if ( IS_PRESET(EventCode) ) {
1395  int preset_index = EventCode & PAPI_PRESET_AND_MASK;
1396 
1397  /* Check if it's within the valid range */
1398  if ( ( preset_index < 0 ) ||
1399  ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
1400  return PAPI_EINVAL;
1401 
1402  /* Check if event exists */
1403  if ( !_papi_hwi_presets[preset_index].count )
1404  return PAPI_ENOEVNT;
1405 
1406  /* Remove the preset event. */
1407  for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
1408  j++ );
1410  (int *)_papi_hwi_presets[preset_index].code, j );
1411  if ( retval != PAPI_OK )
1412  return ( retval );
1413  } else if ( IS_NATIVE(EventCode) ) {
1414  /* Check if native event exists */
1415  if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
1416  PAPI_OK )
1417  return PAPI_ENOEVNT;
1418 
1419  /* Remove the native event. */
1420  retval = remove_native_events( ESI, &EventCode, 1 );
1421  if ( retval != PAPI_OK )
1422  return ( retval );
1423  } else if ( IS_USER_DEFINED( EventCode ) ) {
1424  int index = EventCode & PAPI_UE_AND_MASK;
1425 
1426  if ( (index < 0) || (index >= (int)_papi_user_events_count) )
1427  return ( PAPI_EINVAL );
1428 
1429  for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
1430  _papi_user_events[index].events[j] != 0; j++ ) {
1432  _papi_user_events[index].events, j);
1433 
1434  if ( retval != PAPI_OK )
1435  return ( retval );
1436  }
1437  } else
1438  return ( PAPI_ENOEVNT );
1439  }
1440  array = ESI->EventInfoArray;
1441 
1442  /* Compact the Event Info Array list if it's not the last event */
1443  /* clear the newly empty slot in the array */
1444  for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
1445  array[thisindex] = array[thisindex + 1];
1446 
1447 
1448  array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
1449  for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
1450  array[thisindex].pos[j] = PAPI_NULL;
1451  array[thisindex].ops = NULL;
1452  array[thisindex].derived = NOT_DERIVED;
1453  ESI->NumberOfEvents--;
1454 
1455  return ( PAPI_OK );
1456 }
1457 
1458 int
1460  long long *values )
1461 {
1462  int retval;
1463  long long *dp = NULL;
1464  int i, index;
1465 
1466  retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state,
1467  &dp, ESI->state );
1468  if ( retval != PAPI_OK ) {
1469  return retval;
1470  }
1471 
1472  /* This routine distributes hardware counters to software counters in the
1473  order that they were added. Note that the higher level
1474  EventInfoArray[i] entries may not be contiguous because the user
1475  has the right to remove an event.
1476  But if we do compaction after remove event, this function can be
1477  changed.
1478  */
1479 
1480  for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
1481 
1482  index = ESI->EventInfoArray[i].pos[0];
1483 
1484  if ( index == -1 )
1485  continue;
1486 
1487  INTDBG( "Event index %d, position is %#x\n", i, index );
1488 
1489  /* If this is not a derived event */
1490 
1491  if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
1492  values[i] = dp[index];
1493  INTDBG( "value: %#llx\n", values[i] );
1494  } else { /* If this is a derived event */
1495  values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
1496 #ifdef DEBUG
1497  if ( values[i] < ( long long ) 0 ) {
1498  INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
1499  }
1500  INTDBG( "derived value: %#llx \n", values[i] );
1501 #endif
1502  }
1503  }
1504 
1505  return PAPI_OK;
1506 }
1507 
1508 int
1510 {
1511  int i, j, num_cntrs, retval;
1512  hwd_context_t *context;
1513  int EventCode;
1515  if ( !_papi_hwi_invalid_cmp( ESI->CmpIdx ) ) {
1516  num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
1517 
1518  for(i=0;i<num_cntrs;i++) {
1519 
1520  EventCode=ESI->EventInfoArray[i].event_code;
1521 
1522  /* skip if event not there */
1523  if ( EventCode == PAPI_NULL ) continue;
1524 
1525  /* If it is a MPX EventSet, remove it from the multiplex */
1526  /* data structure and this thread's multiplex list */
1527 
1528  if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
1529  retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
1530  if ( retval < PAPI_OK )
1531  return retval;
1532  } else {
1533 
1534  native = ESI->NativeInfoArray;
1535 
1536  /* clear out ESI->NativeInfoArray */
1537  /* do we really need to do this, seeing as we free() it later? */
1538 
1539  for( j = 0; j < ESI->NativeCount; j++ ) {
1540  native[j].ni_event = -1;
1541  native[j].ni_position = -1;
1542  native[j].ni_owners = 0;
1543  /* native[j].ni_bits?? */
1544  }
1545  }
1546 
1547  /* do we really need to do this, seeing as we free() it later? */
1548  ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
1549  for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
1550  ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
1551  }
1552  ESI->EventInfoArray[i].ops = NULL;
1554  }
1555 
1556  context = _papi_hwi_get_context( ESI, NULL );
1557  /* calling with count of 0 equals a close? */
1558  retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
1559  NULL, 0, context);
1560  if (retval!=PAPI_OK) {
1561  return retval;
1562  }
1563  }
1564 
1565  ESI->CmpIdx = -1;
1566  ESI->NumberOfEvents = 0;
1567  ESI->NativeCount = 0;
1568 
1569  if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
1570  papi_free( ESI->multiplex.mpx_evset );
1571 
1572  if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
1574 
1575  if ( ESI->ctl_state )
1576  papi_free( ESI->ctl_state );
1577 
1578  if ( ESI->sw_stop )
1579  papi_free( ESI->sw_stop );
1580 
1581  if ( ESI->hw_start )
1582  papi_free( ESI->hw_start );
1583 
1584  if ( ESI->EventInfoArray )
1585  papi_free( ESI->EventInfoArray );
1586 
1587  if ( ESI->NativeInfoArray )
1588  papi_free( ESI->NativeInfoArray );
1589 
1590  if ( ESI->NativeBits )
1591  papi_free( ESI->NativeBits );
1592 
1593  if ( ESI->overflow.deadline )
1594  papi_free( ESI->overflow.deadline );
1595 
1596  if ( ESI->profile.prof )
1597  papi_free( ESI->profile.prof );
1598 
1599  ESI->ctl_state = NULL;
1600  ESI->sw_stop = NULL;
1601  ESI->hw_start = NULL;
1602  ESI->EventInfoArray = NULL;
1603  ESI->NativeInfoArray = NULL;
1604  ESI->NativeBits = NULL;
1605 
1606  memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
1607  memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
1608  memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
1609  memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
1610  memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
1611  memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
1612  memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
1613  memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
1614 
1615  ESI->CpuInfo = NULL;
1616 
1617  return PAPI_OK;
1618 }
1619 
1620 int
1622 {
1623  int retval, i, j = 0, *mpxlist = NULL;
1624  EventSetInfo_t *ESI = mpx->ESI;
1625  int flags = mpx->flags;
1626 
1627  /* If there are any events in the EventSet,
1628  convert them to multiplex events */
1629 
1630  if ( ESI->NumberOfEvents ) {
1631 
1632  mpxlist =
1633  ( int * ) papi_malloc( sizeof ( int ) *
1634  ( size_t ) ESI->NumberOfEvents );
1635  if ( mpxlist == NULL )
1636  return ( PAPI_ENOMEM );
1637 
1638  /* Build the args to MPX_add_events(). */
1639 
1640  /* Remember the EventInfoArray can be sparse
1641  and the data can be non-contiguous */
1642 
1643  for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
1644  if ( ESI->EventInfoArray[i].event_code !=
1645  ( unsigned int ) PAPI_NULL )
1646  mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
1647 
1648  /* Resize the EventInfo_t array */
1649 
1650  if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
1651  ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
1652  ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
1653  retval =
1654  MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
1655  ESI->domain.domain,
1656  ESI->granularity.granularity );
1657  if ( retval != PAPI_OK ) {
1658  papi_free( mpxlist );
1659  return ( retval );
1660  }
1661  }
1662 
1663  papi_free( mpxlist );
1664  }
1665 
1666  /* Update the state before initialization! */
1667 
1668  ESI->state |= PAPI_MULTIPLEXING;
1669  if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
1670  ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
1672  ESI->multiplex.ns = ( int ) mpx->ns;
1673 
1674  return ( PAPI_OK );
1675 }
1676 
1677 #include "components_config.h"
1678 
1679 int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
1680 
1681 /*
1682  * Routine that initializes all available components.
1683  * A component is available if a pointer to its info vector
1684  * appears in the NULL terminated_papi_hwd table.
1685  */
1686 int
1688 {
1689  int retval, i = 0;
1690 
1692  if ( retval != PAPI_OK ) {
1693  return retval;
1694  }
1695 
1696  while ( _papi_hwd[i] ) {
1697 
1698  retval = _papi_hwi_innoculate_vector( _papi_hwd[i] );
1699  if ( retval != PAPI_OK ) {
1700  return retval;
1701  }
1702 
1703  /* We can be disabled by user before init */
1704  if (!_papi_hwd[i]->cmp_info.disabled) {
1705  retval = _papi_hwd[i]->init_component( i );
1706  _papi_hwd[i]->cmp_info.disabled=retval;
1707 
1708  /* Do some sanity checking */
1709  if (retval==PAPI_OK) {
1710  if (_papi_hwd[i]->cmp_info.num_cntrs >
1711  _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
1712  fprintf(stderr,"Warning! num_cntrs is more than num_mpx_cntrs\n");
1713  }
1714 
1715  }
1716  }
1717 
1718  i++;
1719  }
1720  return PAPI_OK;
1721 }
1722 
1723 /* Machine info struct initialization using defaults */
1724 /* See _papi_mdi definition in papi_internal.h */
1725 
1726 int
1728 {
1729 
1730  int retval;
1731 
1732  memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
1733 
1735 
1736  /* Global struct to maintain EventSet mapping */
1737  retval = allocate_eventset_map( &_papi_hwi_system_info.global_eventset_map );
1738  if ( retval != PAPI_OK ) {
1739  return retval;
1740  }
1741 
1742  _papi_hwi_system_info.pid = 0; /* Process identifier */
1743 
1744  /* PAPI_hw_info_t struct */
1745  memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
1746 
1747  return PAPI_OK;
1748 }
1749 
1750 void
1752 {
1754 
1756 
1758 
1759  papi_free( _papi_hwi_system_info.global_eventset_map.dataSlotArray );
1760  memset( &_papi_hwi_system_info.global_eventset_map,
1761  0x00, sizeof ( DynamicArray_t ) );
1762 
1764 
1765  if ( _papi_hwi_system_info.shlib_info.map ) {
1766  papi_free( _papi_hwi_system_info.shlib_info.map );
1767  }
1768  memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
1769 
1770 }
1771 
1772 
1773 
1774 void
1775 _papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
1776  void *context )
1777 {
1778  /* This function is not used and shouldn't be called. */
1779  ( void ) EventSet; /*unused */
1780  ( void ) address; /*unused */
1781  ( void ) overflow_vector; /*unused */
1782  ( void ) context; /*unused */
1783  return;
1784 }
1785 
1786 static long long
1787 handle_derived_add( int *position, long long *from )
1788 {
1789  int pos, i;
1790  long long retval = 0;
1791 
1792  i = 0;
1793  while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
1794  pos = position[i++];
1795  if ( pos == PAPI_NULL )
1796  break;
1797  INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
1798  retval += from[pos];
1799  }
1800  return ( retval );
1801 }
1802 
1803 static long long
1804 handle_derived_subtract( int *position, long long *from )
1805 {
1806  int pos, i;
1807  long long retval = from[position[0]];
1808 
1809  i = 1;
1810  while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
1811  pos = position[i++];
1812  if ( pos == PAPI_NULL )
1813  break;
1814  INTDBG( "Compound event, subtracting pos=%d %lld from %lld\n", pos,
1815  from[pos], retval );
1816  retval -= from[pos];
1817  }
1818  return ( retval );
1819 }
1820 
1821 static long long
1822 units_per_second( long long units, long long cycles )
1823 {
1824  return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
1825  (long long) 1000000 ) / cycles );
1826 }
1827 
1828 static long long
1829 handle_derived_ps( int *position, long long *from )
1830 {
1831  return ( units_per_second( from[position[1]], from[position[0]] ) );
1832 }
1833 static long long
1834 handle_derived_add_ps( int *position, long long *from )
1835 {
1836  long long tmp = handle_derived_add( position + 1, from );
1837  return ( units_per_second( tmp, from[position[0]] ) );
1838 }
1839 
1840 /* this function implement postfix calculation, it reads in a string where I use:
1841  | as delimiter
1842  N2 indicate No. 2 native event in the derived preset
1843  +, -, *, /, % as operator
1844  # as MHZ(million hz) got from _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
1845 
1846  Haihang (you@cs.utk.edu)
1847 */
1848 static long long
1849 _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
1850 {
1851  char *point = evi->ops, operand[16];
1852  double stack[PAPI_EVENTS_IN_DERIVED_EVENT];
1853  int i, top = 0;
1854 
1855  memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
1856 
1857  while ( *point != '\0' ) {
1858  if ( *point == 'N' ) { /* to get count for each native event */
1859  i = 0;
1860  point++;
1861  do {
1862  operand[i] = *point;
1863  point++;
1864  i++;
1865  } while ( *point != '|' );
1866  operand[i] = '\0';
1867  stack[top] = ( double ) hw_counter[evi->pos[atoi( operand )]];
1868  top++;
1869  point++;
1870  } else if ( *point == '#' ) { /* to get mhz, ignore the rest char's */
1871  stack[top] = _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000000.0;
1872  top++;
1873  do {
1874  point++;
1875  } while ( *point != '|' );
1876  point++;
1877  } else if ( isdigit( *point ) ) { /* to get integer, I suppose only integer will be used,
1878  no error check here, please only use integer */
1879  i = 0;
1880  do {
1881  operand[i] = *point;
1882  point++;
1883  i++;
1884  } while ( *point != '|' );
1885  operand[i] = '\0';
1886  stack[top] = atoi( operand );
1887  top++;
1888  point++;
1889  } else if ( *point == '+' ) { /* + calculation */
1890  stack[top - 2] += stack[top - 1];
1891  top--;
1892  do {
1893  point++;
1894  } while ( *point != '|' );
1895  point++;
1896  } else if ( *point == '-' ) { /* - calculation */
1897  stack[top - 2] -= stack[top - 1];
1898  top--;
1899  do {
1900  point++;
1901  } while ( *point != '|' );
1902  point++;
1903  } else if ( *point == '*' ) { /* * calculation */
1904  stack[top - 2] *= stack[top - 1];
1905  top--;
1906  do {
1907  point++;
1908  } while ( *point != '|' );
1909  point++;
1910  } else if ( *point == '/' ) { /* / calculation */
1911  stack[top - 2] /= stack[top - 1];
1912  top--;
1913  do {
1914  point++;
1915  } while ( *point != '|' );
1916  point++;
1917  } else { /* do nothing */
1918  do {
1919  point++;
1920  } while ( *point != '|' );
1921  point++;
1922  }
1923  }
1924  return ( long long ) stack[0];
1925 }
1926 
1927 static long long
1928 handle_derived( EventInfo_t * evi, long long *from )
1929 {
1930  switch ( evi->derived ) {
1931  case DERIVED_ADD:
1932  return ( handle_derived_add( evi->pos, from ) );
1933  case DERIVED_ADD_PS:
1934  return ( handle_derived_add_ps( evi->pos, from ) );
1935  case DERIVED_SUB:
1936  return ( handle_derived_subtract( evi->pos, from ) );
1937  case DERIVED_PS:
1938  return ( handle_derived_ps( evi->pos, from ) );
1939  case DERIVED_POSTFIX:
1940  return ( _papi_hwi_postfix_calc( evi, from ) );
1941  case DERIVED_CMPD: /* This type has existed for a long time, but was never implemented.
1942  Probably because its a no-op. However, if it's in a header, it
1943  should be supported. As I found out when I implemented it in
1944  Pentium 4 for testing...dkt */
1945  return ( from[evi->pos[0]] );
1946  default:
1947  PAPIERROR( "BUG! Unknown derived command %d, returning 0",
1948  evi->derived );
1949  return ( ( long long ) 0 );
1950  }
1951 }
1952 
1953 
1954 /* table matching derived types to derived strings.
1955  used by get_info, encode_event, xml translator
1956 */
1958  {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
1959  {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
1960  {DERIVED_PS, "DERIVED_PS",
1961  "Divide by the cycle counter and convert to seconds"},
1962  {DERIVED_ADD_PS, "DERIVED_ADD_PS",
1963  "Add 2 counters then divide by the cycle counter and xl8 to secs."},
1964  {DERIVED_CMPD, "DERIVED_CMPD",
1965  "Event lives in first counter but takes 2 or more codes"},
1966  {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
1967  {DERIVED_POSTFIX, "DERIVED_POSTFIX",
1968  "Process counters based on specified postfix string"},
1969  {-1, NULL, NULL}
1970 };
1971 
1972 /* _papi_hwi_derived_type:
1973  Helper routine to extract a derived type from a derived string
1974  returns type value if found, otherwise returns -1
1975 */
1976 int
1977 _papi_hwi_derived_type( char *tmp, int *code )
1978 {
1979  int i = 0;
1980  while ( _papi_hwi_derived[i].name != NULL ) {
1981  if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
1982  *code = _papi_hwi_derived[i].value;
1983  return PAPI_OK;
1984  }
1985  i++;
1986  }
1987  INTDBG( "Invalid derived string %s\n", tmp );
1988  return PAPI_EINVAL;
1989 }
1990 
1991 
1992 /* _papi_hwi_derived_string:
1993  Helper routine to extract a derived string from a derived type
1994  copies derived type string into derived if found,
1995  otherwise returns PAPI_EINVAL
1996 */
1997 static int
1998 _papi_hwi_derived_string( int type, char *derived, int len )
1999 {
2000  int j;
2001 
2002  for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
2003  if ( _papi_hwi_derived[j].value == type ) {
2004  strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
2005  len );
2006  return PAPI_OK;
2007  }
2008  }
2009  INTDBG( "Invalid derived type %d\n", type );
2010  return PAPI_EINVAL;
2011 }
2012 
2013 
2014 /* _papi_hwi_get_preset_event_info:
2015  Assumes EventCode contains a valid preset code.
2016  But defensive programming says check for NULL pointers.
2017  Returns a filled in PAPI_event_info_t structure containing
2018  descriptive strings and values for the specified preset event.
2019 */
2020 int
2022 {
2023  int i = EventCode & PAPI_PRESET_AND_MASK;
2024  unsigned int j;
2025 
2026  if ( _papi_hwi_presets[i].symbol ) { /* if the event is in the preset table */
2027  /* set whole structure to 0 */
2028  memset( info, 0, sizeof ( PAPI_event_info_t ) );
2029 
2030  info->event_code = ( unsigned int ) EventCode;
2031  strncpy( info->symbol, _papi_hwi_presets[i].symbol,
2032  sizeof(info->symbol));
2033 
2034  if ( _papi_hwi_presets[i].short_descr != NULL )
2035  strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
2036  sizeof ( info->short_descr ) );
2037 
2038  if ( _papi_hwi_presets[i].long_descr != NULL )
2039  strncpy( info->long_descr, _papi_hwi_presets[i].long_descr,
2040  sizeof ( info->long_descr ) );
2041 
2043  info->count = _papi_hwi_presets[i].count;
2044 
2046  info->derived, sizeof ( info->derived ) );
2047 
2048  if ( _papi_hwi_presets[i].postfix != NULL )
2049  strncpy( info->postfix, _papi_hwi_presets[i].postfix,
2050  sizeof ( info->postfix ) );
2051 
2052  for(j=0;j < info->count; j++) {
2053  info->code[j]=_papi_hwi_presets[i].code[j];
2054  strncpy(info->name[j], _papi_hwi_presets[i].name[j],
2055  sizeof(info->name[j]));
2056  }
2057 
2058  if ( _papi_hwi_presets[i].note != NULL ) {
2059  strncpy( info->note, _papi_hwi_presets[i].note,
2060  sizeof ( info->note ) );
2061  }
2062 
2063  return PAPI_OK;
2064  } else {
2065  return PAPI_ENOEVNT;
2066  }
2067 }
2068 
2069 
2070 /* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
2071  Used to enumerate the entire array, e.g. for native_avail.c */
2072 int
2073 _papi_hwi_query_native_event( unsigned int EventCode )
2074 {
2075  char name[PAPI_HUGE_STR_LEN]; /* probably overkill, */
2076  /* but should always be big enough */
2077  int cidx;
2078 
2079  cidx = _papi_hwi_component_index( EventCode );
2080  if (cidx<0) return PAPI_ENOCMP;
2081 
2082  return ( _papi_hwd[cidx]->ntv_code_to_name(
2083  _papi_hwi_eventcode_to_native(EventCode),
2084  name, sizeof(name)));
2085 }
2086 
2087 /* Converts an ASCII name into a native event code usable by other routines
2088  Returns code = 0 and PAPI_OK if name not found.
2089  This allows for sparse native event arrays */
2090 int
2091 _papi_hwi_native_name_to_code( char *in, int *out )
2092 {
2093  int retval = PAPI_ENOEVNT;
2094  char name[PAPI_HUGE_STR_LEN]; /* make sure it's big enough */
2095  unsigned int i;
2096  int cidx;
2097 
2098  SUBDBG("checking all %d components\n",papi_num_components);
2100 
2101 
2102  for(cidx=0; cidx < papi_num_components; cidx++) {
2103 
2104  if (_papi_hwd[cidx]->cmp_info.disabled) continue;
2105 
2106  /* first check each component for name_to_code */
2107  retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
2108  *out = _papi_hwi_native_to_eventcode(cidx,*out);
2109 
2110  /* If not implemented, work around */
2111  if ( retval==PAPI_ECMP) {
2112  i = 0;
2113  _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
2114 
2115  // _papi_hwi_lock( INTERNAL_LOCK );
2116 
2117  do {
2118  retval = _papi_hwd[cidx]->ntv_code_to_name(
2119  i,
2120  name, sizeof(name));
2121  /* printf("%#x\nname =|%s|\ninput=|%s|\n", i, name, in); */
2122  if ( retval == PAPI_OK && in != NULL) {
2123  if ( strcasecmp( name, in ) == 0 ) {
2124  *out = _papi_hwi_native_to_eventcode(cidx,i);
2125  break;
2126  } else {
2127  retval = PAPI_ENOEVNT;
2128  }
2129  } else {
2130  *out = 0;
2131  retval = PAPI_ENOEVNT;
2132  break;
2133  }
2134  } while ( ( _papi_hwd[cidx]->ntv_enum_events( &i,
2135  PAPI_ENUM_EVENTS ) ==
2136  PAPI_OK ) );
2137 
2138  // _papi_hwi_unlock( INTERNAL_LOCK );
2139  }
2140 
2141  if ( retval == PAPI_OK ) return retval;
2142  }
2143 
2144  return retval;
2145 }
2146 
2147 /* Returns event name based on native event code.
2148  Returns NULL if name not found */
2149 int
2150 _papi_hwi_native_code_to_name( unsigned int EventCode,
2151  char *hwi_name, int len )
2152 {
2153  int cidx;
2154  int retval;
2155 
2156  cidx = _papi_hwi_component_index( EventCode );
2157  if (cidx<0) return PAPI_ENOEVNT;
2158 
2159  if ( EventCode & PAPI_NATIVE_MASK ) {
2160  if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2161  _papi_hwi_eventcode_to_native(EventCode),
2162  hwi_name, len) ) == PAPI_OK ) {
2163  return
2164  _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name,
2165  hwi_name, hwi_name, len);
2166  } else {
2167  return (retval);
2168  }
2169  }
2170  return PAPI_ENOEVNT;
2171 }
2172 
2173 
2174 
2175 /* The native event equivalent of PAPI_get_event_info */
2176 int
2177 _papi_hwi_get_native_event_info( unsigned int EventCode,
2178  PAPI_event_info_t *info )
2179 {
2180  int retval;
2181  int cidx;
2182 
2183  cidx = _papi_hwi_component_index( EventCode );
2184  if (cidx<0) return PAPI_ENOCMP;
2185 
2186  if (_papi_hwd[cidx]->cmp_info.disabled) return PAPI_ENOCMP;
2187 
2188  if ( EventCode & PAPI_NATIVE_MASK ) {
2189 
2190  /* clear the event info */
2191  memset( info, 0, sizeof ( PAPI_event_info_t ) );
2192  info->event_code = ( unsigned int ) EventCode;
2193 
2194  retval = _papi_hwd[cidx]->ntv_code_to_info(
2195  _papi_hwi_eventcode_to_native(EventCode), info);
2196 
2197  /* If component error, it's missing the ntv_code_to_info vector */
2198  /* so we'll have to fake it. */
2199  if ( retval == PAPI_ECMP ) {
2200 
2201 
2202  SUBDBG("missing NTV_CODE_TO_INFO, faking\n");
2203  /* Fill in the info structure */
2204 
2205  if ( (retval = _papi_hwd[cidx]->ntv_code_to_name(
2206  _papi_hwi_eventcode_to_native(EventCode),
2207  info->symbol,
2208  sizeof(info->symbol)) ) == PAPI_OK ) {
2209 
2210  } else {
2211  SUBDBG("failed ntv_code_to_name\n");
2212  return retval;
2213  }
2214 
2215  retval = _papi_hwd[cidx]->ntv_code_to_descr(
2216  _papi_hwi_eventcode_to_native(EventCode),
2217  info->long_descr,
2218  sizeof ( info->long_descr));
2219  if (retval!=PAPI_OK) {
2220  SUBDBG("Failed ntv_code_to_descr()\n");
2221  }
2222 
2223  }
2225  _papi_hwd[cidx]->cmp_info.short_name,
2226  info->symbol,
2227  info->symbol,
2228  sizeof(info->symbol) );
2229 
2230  return retval;
2231  }
2232 
2233  return PAPI_ENOEVNT;
2234 }
2235 
2238 {
2239  const DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
2240  EventSetInfo_t *set;
2241 
2242  if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
2243  return ( NULL );
2244 
2245  set = map->dataSlotArray[eventset];
2246 #ifdef DEBUG
2247  if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
2248  ( set->master->tid != _papi_hwi_thread_id_fn( ) ) )
2249  return ( NULL );
2250 #endif
2251 
2252  return ( set );
2253 }
2254 
2255 int
2257 {
2258  /* Are we multiplexing at all */
2259  if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
2260  return 0;
2261  }
2262 
2263  /* Does the component support kernel multiplexing */
2264  if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
2265  /* Have we forced software multiplexing */
2266  if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
2267  return 1;
2268  }
2269  /* Nope, using hardware multiplexing */
2270  return 0;
2271  }
2272 
2273  /* We are multiplexing but the component does not support hardware */
2274 
2275  return 1;
2276 
2277 }
2278 
2279 hwd_context_t *
2280 _papi_hwi_get_context( EventSetInfo_t * ESI, int *is_dirty )
2281 {
2282  INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
2283  int dirty_ctx;
2284  hwd_context_t *ctx=NULL;
2285 
2286  /* assume for now the control state is clean (last updated by this ESI) */
2287  dirty_ctx = 0;
2288 
2289  /* get a context pointer based on if we are counting for a thread or for a cpu */
2290  if (ESI->state & PAPI_CPU_ATTACHED) {
2291  /* use cpu context */
2292  ctx = ESI->CpuInfo->context[ESI->CmpIdx];
2293 
2294  /* if the user wants to know if the control state was last set by the same event set, tell him */
2295  if (is_dirty != NULL) {
2296  if (ESI->CpuInfo->from_esi != ESI) {
2297  dirty_ctx = 1;
2298  }
2299  *is_dirty = dirty_ctx;
2300  }
2301  ESI->CpuInfo->from_esi = ESI;
2302 
2303  } else {
2304 
2305  /* use thread context */
2306  ctx = ESI->master->context[ESI->CmpIdx];
2307 
2308  /* if the user wants to know if the control state was last set by the same event set, tell him */
2309  if (is_dirty != NULL) {
2310  if (ESI->master->from_esi != ESI) {
2311  dirty_ctx = 1;
2312  }
2313  *is_dirty = dirty_ctx;
2314  }
2315  ESI->master->from_esi = ESI;
2316 
2317  }
2318  return( ctx );
2319 }
char event_name[2][PAPI_MAX_STR_LEN]
Definition: data_range.c:23
int _papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
#define PAPI_HUGE_STR_LEN
Definition: fpapi.h:42
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
int atoi()
unsigned int count
Definition: papi.h:982
memset(eventId, 0, size)
int _papi_hwi_convert_eventset_to_multiplex(_papi_int_multiplex_t *mpx)
#define PAPI_NATIVE_MASK
#define DERIVED_SUB
Definition: papi_internal.h:74
int errno
int _papi_hwi_using_signal[PAPI_NSIG]
Definition: extras.c:363
#define PAPI_ENOMEM
Definition: fpapi.h:107
int _papi_hwi_init_global_internal(void)
#define IS_PRESET(EventCode)
Definition: papi.h:227
static struct native_event_info * _papi_native_events
Definition: papi_internal.c:73
#define PAPI_EMISC
Definition: fpapi.h:119
#define PAPI_CPU_ATTACH
Definition: papi.h:455
char * getenv()
#define PAPI_EVENTS_IN_DERIVED_EVENT
Definition: genpapifdef.c:39
int _papi_hwi_innoculate_os_vector(papi_os_vector_t *v)
Definition: papi_vector.c:200
Hardware info structure.
Definition: papi.h:775
hwd_register_t * ni_bits
static int EventInfoArrayLength(const EventSetInfo_t *ESI)
long long flags
Definition: iozone.c:12330
#define PAPI_NULL
Definition: fpapi.h:13
#define IS_USER_DEFINED(EventCode)
Definition: papi.h:228
#define papi_free(a)
Definition: papi_memory.h:35
int _papi_hwi_query_native_event(unsigned int EventCode)
int _papi_hwi_cleanup_eventset(EventSetInfo_t *ESI)
start
Definition: iozone.c:22736
#define papi_malloc(a)
Definition: papi_memory.h:34
PAPI_debug_handler_t _papi_hwi_debug_handler
Definition: papi_internal.c:56
#define PAPI_ENOEVNT
Definition: fpapi.h:112
MPX_EventSet * mpx_evset
Definition: sw_multiplex.h:32
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:964
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
#define PAPI_VERB_ECONT
Definition: fpapi.h:39
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:961
device[deviceId] domain[domainId] event
Definition: linux-cuda.c:306
hwd_register_t * NativeBits
int events[PAPI_EVENTS_IN_DERIVED_EVENT]
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 _papi_hwi_errno
Definition: papi_internal.c:58
int _papi_hwi_remove_EventSet(EventSetInfo_t *ESI)
int _papi_hwi_derived_type(char *tmp, int *code)
return PAPI_OK
Definition: linux-nvml.c:458
int count
Definition: iozone.c:22422
#define PAPI_ENOCMP
Definition: fpapi.h:122
static long long _papi_hwi_postfix_calc(EventInfo_t *evi, long long *hw_counter)
#define DERIVED_ADD
Definition: papi_internal.h:70
#define PAPI_PRESET_MASK
void
Definition: iozone.c:18627
char note[PAPI_HUGE_STR_LEN]
Definition: papi.h:1008
return PAPI_EINVAL
Definition: linux-nvml.c:408
void _papi_hwi_init_errors(void)
int _papi_hwi_remove_event(EventSetInfo_t *ESI, int EventCode)
EventSetInfo_t * _papi_hwi_lookup_EventSet(int eventset)
#define PAPI_STOPPED
Definition: fpapi.h:29
#define DERIVED_CMPD
Definition: papi_internal.h:73
#define PAPI_OVERFLOWING
Definition: fpapi.h:33
void double value
Definition: iozone.c:18781
static double
Definition: fileop.c:1281
int _papi_hwi_native_name_to_code(char *in, int *out)
#define PAPI_INIT_SLOTS
Definition: papi.h:459
#define PAPI_ECNFLCT
Definition: fpapi.h:113
PAPI_shlib_info_t shlib_info
Return codes and api definitions.
#define INTDBG(format, args...)
Definition: papi_debug.h:65
static long long handle_derived_add(int *position, long long *from)
#define APIDBG(format, args...)
Definition: papi_debug.h:64
int MPX_add_events(MPX_EventSet **mpx_events, int *event_list, int num_events, int domain, int granularity)
Definition: sw_multiplex.c:676
#define PAPI_ECOUNT
Definition: fpapi.h:128
unsigned int event_type
Definition: papi_preset.h:30
static int event_already_in_eventset(EventSetInfo_t *ESI, int nevt)
char * _papi_hwi_strip_component_prefix(char *event_name)
#define PAPI_MULTIPLEXING
Definition: fpapi.h:35
static int _papi_hwi_add_error(char *error)
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
EventSetOverflowInfo_t overflow
#define PAPI_OVERFLOW_HARDWARE
Definition: papi.h:410
EventSetInheritInfo_t inherit
struct _CpuInfo * CpuInfo
#define PAPI_MULTIPLEX_FORCE_SW
Definition: fpapi.h:46
DynamicArray_t global_eventset_map
static int _papi_hwi_add_native_event(int event, int cidx)
struct _ThreadInfo * master
#define IS_NATIVE(EventCode)
Definition: papi.h:226
static int allocate_eventset_map(DynamicArray_t *map)
static int _papi_hwi_find_native_event(int cidx, int event)
#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
static int cidx
Definition: event_info.c:40
#define PAPI_ECMP
Definition: fpapi.h:109
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:962
hwi_presets_t _papi_hwi_presets[PAPI_MAX_PRESET_EVENTS]
static int native
Definition: event_info.c:39
inline_static int _papi_hwi_unlock(int lck)
Definition: threads.h:78
#define PAPI_CPU_ATTACHED
Definition: fpapi.h:37
int _papi_hwi_innoculate_vector(papi_vector_t *v)
Definition: papi_vector.c:109
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
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:65
int _papi_hwi_add_event(EventSetInfo_t *ESI, int EventCode)
long long
Definition: iozone.c:19827
int _papi_hwi_get_native_event_info(unsigned int EventCode, PAPI_event_info_t *info)
unsigned int event_type
Definition: papi.h:987
void PAPIERROR(char *format,...)
static const hwi_describe_t _papi_hwi_derived[]
int(* PAPI_debug_handler_t)(int code)
Definition: papi.h:680
void _papi_hwi_shutdown_global_internal(void)
int _papi_hwi_get_preset_event_info(int EventCode, PAPI_event_info_t *info)
char events[MAX_EVENTS][BUFSIZ]
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:75
#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:55
nvmlDevice_t handle
Definition: linux-nvml.c:399
static int default_debug_handler(int errorCode)
static int num_error_chunks
Definition: papi_internal.c:78
int _papi_hwi_shutdown_cpu(CpuInfo_t *cpu)
Definition: cpus.c:306
NativeInfo_t * NativeInfoArray
int _papi_hwi_num_errors
Definition: papi_internal.c:59
char * short_descr
Definition: papi_preset.h:25
EventInfo_t * EventInfoArray
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
#define PAPI_ESYS
Definition: fpapi.h:108
unsigned int code[PAPI_MAX_INFO_TERMS]
Definition: papi.h:998
#define PAPI_ERROR_CODE_str
Definition: papi_internal.h:41
static long long handle_derived_ps(int *position, long long *from)
#define PAPI_QUIET
Definition: fpapi.h:38
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:57
PAPI_hw_info_t hw_info
again struct sockaddr sizeof(struct sockaddr_in))
int _papi_hwi_native_to_eventcode(int cidx, int event_code)
EventSetMultiplexInfo_t multiplex
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]
int EventSet
long long * sw_stop
int _papi_hwi_publish_error(char *error)
#define PAPI_MAX_PRESET_EVENTS
Definition: fpapi.h:16
int papi_num_components
#define PAPI_EBUG
Definition: fpapi.h:111
#define INTERNAL_LOCK
Definition: papi_internal.h:85
#define papi_realloc(a, b)
Definition: papi_memory.h:36
char operation[USER_EVENT_OPERATION_LEN]
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)
PAPI_address_map_t * map
Definition: papi.h:709
char ** _papi_errlist
Definition: papi_internal.c:77
int mpx_remove_event(MPX_EventSet **mpx_events, int EventCode)
Definition: sw_multiplex.c:418
int cpu_max_mhz
Definition: papi.h:791
static int _papi_hwi_lookup_error(char *error)
int
Definition: iozone.c:18528
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
unsigned int event_code
#define PAPI_UE_AND_MASK
#define PAPI_PRESET_AND_MASK
#define PAPI_VERB_ESTOP
Definition: fpapi.h:40
struct papi_vectors * _papi_hwd[]
int _papi_hwi_invalid_cmp(int cidx)
user_defined_event_t * _papi_user_events
#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)
Definition: papi_internal.c:95
int _papi_hwi_eventcode_to_native(int event_code)
EventSetInfo_t * ESI
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:54
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:959
char * symbol
Definition: papi_preset.h:24
char derived[PAPI_MIN_STR_LEN]
Definition: papi.h:990
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)
char postfix[PAPI_2MAX_STR_LEN]
Definition: papi.h:993
size1
Definition: iozone.c:12039
int _papi_hwi_cleanup_all_presets(void)
Definition: papi_preset.c:107
unsigned int _papi_user_events_count
#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)
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:1004
#define PAPI_NOT_INITED
Definition: fpapi.h:17
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
int n
Definition: mendes-alt.c:164
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:74
char * ptr
Definition: iozone.c:23586