PAPI  5.0.1.0
papi_internal.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00005 /* 
00006 * File:    papi_internal.c
00007 *
00008 * Author:  Philip Mucci
00009 *          mucci@cs.utk.edu
00010 * Mods:    dan terpstra
00011 *          terpstra@cs.utk.edu
00012 * Mods:    Min Zhou
00013 *          min@cs.utk.edu
00014 * Mods:    Kevin London
00015 *      london@cs.utk.edu
00016 * Mods:    Per Ekman
00017 *          pek@pdc.kth.se
00018 * Mods:    Haihang You
00019 *          you@cs.utk.edu
00020 * Mods:    Maynard Johnson
00021 *          maynardj@us.ibm.com
00022 * Mods:    Brian Sheely
00023 *          bsheely@eecs.utk.edu
00024 * Mods:    <Gary Mohr>
00025 *          <gary.mohr@bull.com>
00026 * Mods:    <your name here>
00027 *          <your email address>
00028 */
00029 
00030 #include <stdarg.h>
00031 #include <stdio.h>
00032 #include <errno.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 
00036 #include "papi.h"
00037 #include "papi_internal.h"
00038 #include "papi_vector.h"
00039 #include "papi_memory.h"
00040 #include "sw_multiplex.h"
00041 #include "extras.h"
00042 #include "papi_preset.h"
00043 
00044 #include "papi_common_strings.h"
00045 
00046 #include "papi_user_events.h"
00047 
00048 /* Advanced definitons */
00049 static int default_debug_handler( int errorCode );
00050 static long long handle_derived( EventInfo_t * evi, long long *from );
00051 
00052 /* Global definitions used by other files */
00053 int init_level = PAPI_NOT_INITED;
00054 int _papi_hwi_error_level = PAPI_QUIET;
00055 PAPI_debug_handler_t _papi_hwi_debug_handler = default_debug_handler;
00056 papi_mdi_t _papi_hwi_system_info;
00057 int _papi_hwi_errno = PAPI_OK;
00058 int _papi_hwi_num_errors = 0;
00059 
00060 /*****************************/
00061 /* Native Event Mapping Code */
00062 /*****************************/
00063 
00064 #define NATIVE_EVENT_CHUNKSIZE 1024
00065 
00066 struct native_event_info {
00067   int cidx;
00068   int component_event;
00069 };
00070 
00071 
00072 static struct native_event_info *_papi_native_events=NULL;
00073 static int num_native_events=0;
00074 static int num_native_chunks=0;
00075 
00076 char **_papi_errlist= NULL;
00077 static int num_error_chunks = 0;
00078 
00079 
00080 
00093 int
00094 _papi_hwi_prefix_component_name( char *component_name, char *event_name, char *out, int out_len) 
00095 {
00096     int size1, size2;
00097     char temp[out_len];
00098 
00099     size1 = strlen(event_name);
00100     size2 = strlen(component_name);
00101 
00102 /* sanity checks */
00103     if ( size1 == 0 ) {
00104         return (PAPI_EBUG); /* hopefully event_name always has length?! */
00105     }   
00106 
00107     if ( size1 >= out_len )
00108         return (PAPI_ENOMEM);
00109 
00110 /* Guard against event_name == out */
00111     memcpy( temp, event_name, out_len );
00112 
00113 /* no component name to prefix */
00114     if ( size2 == 0 ) {
00115         sprintf(out, "%s%c", temp, '\0' );
00116         return (PAPI_OK);
00117     }
00118     
00119 /* Don't prefix 'cpu' component names for now */
00120     if ( strstr(component_name, "pe") ||
00121          strstr(component_name, "bgq") ||
00122          strstr(component_name, "bgp") ) {
00123         sprintf( out, "%s%c", temp, '\0'); 
00124         return (PAPI_OK);
00125     }
00126 
00127 /* strlen(component_name) + ::: + strlen(event_name) + NULL */
00128     if ( size1+size2+3+1 > out_len )
00129         return (PAPI_ENOMEM);
00130 
00131     sprintf( out, "%s:::%s%c" , component_name, temp, '\0');
00132     return (PAPI_OK);
00133 }
00134 
00145 char *_papi_hwi_strip_component_prefix(char *event_name)
00146 {
00147     char *start = NULL;
00148 /* We assume ::: is the seperator 
00149  * eg: 
00150  *      papi_component:::event_name 
00151  */
00152 
00153     start = strstr( event_name, ":::" );
00154     if ( start != NULL )
00155         start+= 3; /* return the actual start of event_name */
00156     else
00157         start = event_name;
00158 
00159     return (start);
00160 }
00161 
00162 static int
00163 _papi_hwi_find_native_event(int cidx, int event) {
00164 
00165   int i;
00166 
00167   for(i=0;i<num_native_events;i++) {
00168     if ((_papi_native_events[i].cidx==cidx) &&
00169     (_papi_native_events[i].component_event==event)) {
00170        return i|PAPI_NATIVE_MASK;
00171     }
00172   }
00173 
00174   return PAPI_ENOEVNT;
00175 
00176 }
00177 
00178 static int
00179 _papi_hwi_add_native_event(int event, int cidx) {
00180 
00181   int new_native_event;
00182 
00183   SUBDBG("Creating Event %x which is comp %d internal %d\n",
00184      num_native_events|PAPI_NATIVE_MASK,cidx,event);
00185   
00186   _papi_hwi_lock( INTERNAL_LOCK );
00187 
00188   if (num_native_events>=num_native_chunks*NATIVE_EVENT_CHUNKSIZE) {
00189      num_native_chunks++;
00190      _papi_native_events=realloc(_papi_native_events,
00191                  num_native_chunks*NATIVE_EVENT_CHUNKSIZE*
00192                  sizeof(struct native_event_info));
00193      if (_papi_native_events==NULL) {
00194         new_native_event=PAPI_ENOMEM;
00195     goto native_alloc_early_out;
00196      }
00197   }
00198 
00199   _papi_native_events[num_native_events].cidx=cidx;
00200   _papi_native_events[num_native_events].component_event=event;
00201   new_native_event=num_native_events|PAPI_NATIVE_MASK;
00202 
00203   num_native_events++;
00204 
00205 native_alloc_early_out:
00206 
00207   _papi_hwi_unlock( INTERNAL_LOCK );
00208 
00209   return new_native_event;
00210 }
00211 
00218 static int
00219 _papi_hwi_add_error( char *error )
00220 {
00221     SUBDBG("Adding a new Error message |%s|\n", error);
00222     _papi_hwi_lock(INTERNAL_LOCK);
00223 
00224     if (_papi_hwi_num_errors >= num_error_chunks*NATIVE_EVENT_CHUNKSIZE) {
00225         num_error_chunks++;
00226         _papi_errlist=realloc(_papi_errlist, 
00227                         num_error_chunks*NATIVE_EVENT_CHUNKSIZE*sizeof(char *));
00228         if (_papi_errlist==NULL) {
00229             _papi_hwi_num_errors = -2;
00230             goto bail;
00231         }
00232 
00233     }
00234 
00235     _papi_errlist[_papi_hwi_num_errors] = strdup( error );
00236     if ( _papi_errlist[_papi_hwi_num_errors] == NULL )
00237         _papi_hwi_num_errors = -2;
00238 
00239 bail:
00240     _papi_hwi_unlock(INTERNAL_LOCK);
00241 
00242     return _papi_hwi_num_errors++;
00243 }
00244 
00245 static void
00246 _papi_hwi_cleanup_errors()
00247 {
00248     int i; 
00249     
00250     if ( _papi_errlist == NULL || 
00251             _papi_hwi_num_errors == 0 )
00252         return; 
00253 
00254 
00255     _papi_hwi_lock( INTERNAL_LOCK );
00256     for (i=0; i < _papi_hwi_num_errors; i++ ) {
00257         free( _papi_errlist[i]);
00258         _papi_errlist[i] = NULL;
00259     } 
00260 
00261     free( _papi_errlist );
00262     _papi_errlist = NULL;
00263     _papi_hwi_num_errors = 0;
00264     num_error_chunks=0;
00265 
00266     _papi_hwi_unlock( INTERNAL_LOCK );
00267 }
00268 
00269 static int
00270 _papi_hwi_lookup_error( char *error ) 
00271 {
00272     int i;
00273 
00274     for (i=0; i<_papi_hwi_num_errors; i++) {
00275         if ( !strncasecmp( _papi_errlist[i], error, strlen( error ) ) )
00276             return i; 
00277         
00278     } 
00279 
00280     return (-1);
00281 }
00282 
00293 int _papi_hwi_publish_error( char *error )
00294 {
00295     int error_code = -1;
00296 
00297     if ( (error_code = _papi_hwi_lookup_error( error )) < 0 )
00298         error_code = _papi_hwi_add_error(error);
00299 
00300     return (-error_code); /* internally error_code is an index, externally, it should be <= 0 */
00301 }
00302 
00303 void
00304 _papi_hwi_init_errors(void) {
00305 /* we use add error to avoid the cost of lookups, we know the errors are not there yet */
00306     _papi_hwi_add_error("No error");
00307     _papi_hwi_add_error("Invalid argument");
00308     _papi_hwi_add_error("Insufficient memory");
00309     _papi_hwi_add_error("A System/C library call failed");
00310     _papi_hwi_add_error("Not supported by component");
00311     _papi_hwi_add_error("Access to the counters was lost or interrupted");
00312     _papi_hwi_add_error("Internal error, please send mail to the developers");
00313     _papi_hwi_add_error("Event does not exist");
00314     _papi_hwi_add_error("Event exists, but cannot be counted due to hardware resource limits");
00315     _papi_hwi_add_error("EventSet is currently not running");
00316     _papi_hwi_add_error("EventSet is currently counting");
00317     _papi_hwi_add_error("No such EventSet available");
00318     _papi_hwi_add_error("Event in argument is not a valid preset");
00319     _papi_hwi_add_error("Hardware does not support performance counters");
00320     _papi_hwi_add_error("Unknown error code");
00321     _papi_hwi_add_error("Permission level does not permit operation");
00322     _papi_hwi_add_error("PAPI hasn't been initialized yet");
00323     _papi_hwi_add_error("Component Index isn't set");
00324     _papi_hwi_add_error("Not supported");
00325     _papi_hwi_add_error("Not implemented");
00326     _papi_hwi_add_error("Buffer size exceeded");
00327     _papi_hwi_add_error("EventSet domain is not supported for the operation");
00328     _papi_hwi_add_error("Invalid or missing event attributes");
00329     _papi_hwi_add_error("Too many events or attributes");
00330     _papi_hwi_add_error("Bad combination of features");
00331 }
00332 
00333 int
00334 _papi_hwi_invalid_cmp( int cidx )
00335 {
00336   return ( cidx < 0 || cidx >= papi_num_components );
00337 }
00338 
00339 
00340 int 
00341 _papi_hwi_component_index( int event_code ) {
00342 
00343   int cidx;
00344   int event_index;
00345 
00346   SUBDBG("Trying to find component for native_event %x\n",event_code);
00347 
00348   /* currently assume presets are for component 0 only */
00349   if (event_code&PAPI_PRESET_MASK) {
00350      SUBDBG("Event %x is a PRESET, assigning component %d\n",
00351         event_code,0);
00352      return 0;
00353   }
00354 
00355   event_index=event_code&PAPI_NATIVE_AND_MASK;
00356 
00357   if ( (event_index < 0) || (event_index>=num_native_events)) {
00358      SUBDBG("Event index %x is out of range\n",event_index);
00359      return PAPI_ENOEVNT;
00360   }
00361 
00362   cidx=_papi_native_events[event_index].cidx;
00363 
00364   SUBDBG("Found event code %d from %d, %x\n",cidx,event_index,event_code);
00365 
00366   if ((cidx<0) || (cidx >= papi_num_components)) return PAPI_ENOCMP;
00367 
00368   return cidx;
00369 }
00370 
00371 /* Convert a component and internal event to a native_event */
00372 int 
00373 _papi_hwi_native_to_eventcode(int cidx, int event_code) {
00374 
00375   int result;
00376 
00377   SUBDBG("Looking for component %d event %d\n",cidx,event_code);
00378 
00379   result=_papi_hwi_find_native_event(cidx,event_code);
00380   if (result==PAPI_ENOEVNT) {
00381      /* Need to allocate */
00382      result=_papi_hwi_add_native_event(event_code,cidx);
00383   }
00384 
00385   return result;
00386 }
00387 
00388 /* Convert a native_event code to an internal event code */
00389 int
00390 _papi_hwi_eventcode_to_native(int event_code) {
00391 
00392   int result;
00393   int event_index;
00394 
00395   SUBDBG("Looking for event for native_event %x\n",event_code);
00396 
00397   event_index=event_code&PAPI_NATIVE_AND_MASK;
00398   if (event_index>=num_native_events) return PAPI_ENOEVNT;
00399 
00400   result=_papi_native_events[event_index].component_event;
00401   
00402   SUBDBG("Found result %x\n",result);
00403 
00404   return result;
00405 
00406 }
00407 
00408 
00409 /*********************/
00410 /* Utility functions */
00411 /*********************/
00412 
00413 void
00414 PAPIERROR( char *format, ... )
00415 {
00416     va_list args;
00417     if ( ( _papi_hwi_error_level != PAPI_QUIET ) ||
00418          ( getenv( "PAPI_VERBOSE" ) ) ) {
00419         va_start( args, format );
00420         fprintf( stderr, "PAPI Error: " );
00421         vfprintf( stderr, format, args );
00422         fprintf( stderr, ".\n" );
00423         va_end( args );
00424     }
00425 }
00426 
00427 static int
00428 default_debug_handler( int errorCode )
00429 {
00430     char str[PAPI_HUGE_STR_LEN];
00431 
00432     if ( errorCode == PAPI_OK )
00433         return ( errorCode );
00434     if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) {
00435         PAPIERROR( "%s %d,%s,Bug! Unknown error code", PAPI_ERROR_CODE_str,
00436                    errorCode, "" );
00437         return ( PAPI_EBUG );
00438     }
00439 
00440     switch ( _papi_hwi_error_level ) {
00441     case PAPI_VERB_ECONT:
00442     case PAPI_VERB_ESTOP:
00443         /* gcc 2.96 bug fix, do not change */
00444         /* fprintf(stderr,"%s %d: %s: %s\n",PAPI_ERROR_CODE_str,errorCode,_papi_hwi_err[-errorCode].name,_papi_hwi_err[-errorCode].descr); */
00445 
00446         sprintf( str, "%s %d,%s", PAPI_ERROR_CODE_str, errorCode,
00447                  _papi_errlist[-errorCode] );
00448         if ( errorCode == PAPI_ESYS )
00449             sprintf( str + strlen( str ), ": %s", strerror( errno ) );
00450 
00451         PAPIERROR( str );
00452 
00453         if ( _papi_hwi_error_level == PAPI_VERB_ESTOP )
00454             abort(  );       /* patch provided by will cohen of redhat */
00455         else
00456             return errorCode;
00457         break;
00458 
00459     case PAPI_QUIET:
00460     default:
00461         return errorCode;
00462     }
00463     return ( PAPI_EBUG );    /* Never get here */
00464 }
00465 
00466 static int
00467 allocate_eventset_map( DynamicArray_t * map )
00468 {
00469     /* Allocate and clear the Dynamic Array structure */
00470     if ( map->dataSlotArray != NULL )
00471         papi_free( map->dataSlotArray );
00472     memset( map, 0x00, sizeof ( DynamicArray_t ) );
00473 
00474     /* Allocate space for the EventSetInfo_t pointers */
00475 
00476     map->dataSlotArray =
00477         ( EventSetInfo_t ** ) papi_malloc( PAPI_INIT_SLOTS *
00478                                            sizeof ( EventSetInfo_t * ) );
00479     if ( map->dataSlotArray == NULL ) {
00480         return ( PAPI_ENOMEM );
00481     }
00482     memset( map->dataSlotArray, 0x00,
00483             PAPI_INIT_SLOTS * sizeof ( EventSetInfo_t * ) );
00484     map->totalSlots = PAPI_INIT_SLOTS;
00485     map->availSlots = PAPI_INIT_SLOTS;
00486     map->fullSlots = 0;
00487 
00488     return ( PAPI_OK );
00489 }
00490 
00491 static int
00492 expand_dynamic_array( DynamicArray_t * DA )
00493 {
00494     int number;
00495     EventSetInfo_t **n;
00496 
00497     /*realloc existing PAPI_EVENTSET_MAP.dataSlotArray */
00498 
00499     number = DA->totalSlots * 2;
00500     n = ( EventSetInfo_t ** ) papi_realloc( DA->dataSlotArray,
00501                                             ( size_t ) number *
00502                                             sizeof ( EventSetInfo_t * ) );
00503     if ( n == NULL )
00504         return ( PAPI_ENOMEM );
00505 
00506     /* Need to assign this value, what if realloc moved it? */
00507 
00508     DA->dataSlotArray = n;
00509 
00510     memset( DA->dataSlotArray + DA->totalSlots, 0x00,
00511             ( size_t ) DA->totalSlots * sizeof ( EventSetInfo_t * ) );
00512 
00513     DA->totalSlots = number;
00514     DA->availSlots = number - DA->fullSlots;
00515 
00516     return ( PAPI_OK );
00517 }
00518 
00519 static int
00520 EventInfoArrayLength( const EventSetInfo_t * ESI )
00521 {
00522    return ( _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs );
00523 }
00524 
00525 
00526 
00527 
00528 
00529 /*========================================================================*/
00530 /* This function allocates space for one EventSetInfo_t structure and for */
00531 /* all of the pointers in this structure.  If any malloc in this function */
00532 /* fails, all memory malloced to the point of failure is freed, and NULL  */
00533 /* is returned.  Upon success, a pointer to the EventSetInfo_t data       */
00534 /* structure is returned.                                                 */
00535 /*========================================================================*/
00536 
00537 
00538 static int
00539 create_EventSet( EventSetInfo_t ** here )
00540 {
00541    EventSetInfo_t *ESI;
00542 
00543    ESI = ( EventSetInfo_t * ) papi_calloc( 1, sizeof ( EventSetInfo_t ) );
00544    if ( ESI == NULL ) {
00545       return PAPI_ENOMEM;
00546    }
00547 
00548    *here = ESI;
00549 
00550    return PAPI_OK;
00551 }
00552 
00553 int
00554 _papi_hwi_assign_eventset( EventSetInfo_t *ESI, int cidx )
00555 {
00556    int retval;
00557    size_t max_counters;
00558    char *ptr;
00559    unsigned int i, j;
00560 
00561    /* If component doesn't exist... */
00562    if (_papi_hwi_invalid_cmp(cidx)) return PAPI_ECMP;
00563 
00564    /* Assigned at create time */
00565    ESI->domain.domain = _papi_hwd[cidx]->cmp_info.default_domain;
00566    ESI->granularity.granularity =
00567                              _papi_hwd[cidx]->cmp_info.default_granularity;
00568    ESI->CmpIdx = cidx;
00569 
00570    /* ??? */
00571    max_counters = ( size_t ) _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
00572 
00573    ESI->ctl_state = (hwd_control_state_t *) papi_calloc( 1, (size_t) 
00574                    _papi_hwd[cidx]->size.control_state );
00575    ESI->sw_stop = (long long *) papi_calloc( ( size_t ) max_counters,
00576                               sizeof ( long long ) );
00577    ESI->hw_start = ( long long * ) papi_calloc( ( size_t ) max_counters,
00578                                                       sizeof ( long long ) );
00579    ESI->EventInfoArray = ( EventInfo_t * ) papi_calloc( (size_t) max_counters,
00580                                                       sizeof ( EventInfo_t ) );
00581 
00582    /* allocate room for the native events and for the component-private */
00583    /* register structures */
00584    /* ugh is there a cleaner way to allocate this?  vmw */
00585    ESI->NativeInfoArray = ( NativeInfo_t * ) 
00586      papi_calloc( ( size_t ) max_counters, sizeof ( NativeInfo_t ));
00587 
00588    ESI->NativeBits = papi_calloc(( size_t ) max_counters,
00589                                  ( size_t ) _papi_hwd[cidx]->size.reg_value );
00590 
00591    /* NOTE: the next two malloc allocate blocks of memory that are later */
00592    /* parcelled into overflow and profile arrays                         */
00593    ESI->overflow.deadline = ( long long * )
00594         papi_malloc( ( sizeof ( long long ) +
00595                        sizeof ( int ) * 3 ) * ( size_t ) max_counters );
00596 
00597    ESI->profile.prof = ( PAPI_sprofil_t ** )
00598         papi_malloc( ( sizeof ( PAPI_sprofil_t * ) * ( size_t ) max_counters +
00599                        ( size_t ) max_counters * sizeof ( int ) * 4 ) );
00600 
00601    /* If any of these allocations failed, free things up and fail */
00602 
00603    if ( ( ESI->ctl_state == NULL ) ||
00604     ( ESI->sw_stop == NULL )   || 
00605         ( ESI->hw_start == NULL )  ||
00606     ( ESI->NativeInfoArray == NULL ) || 
00607     ( ESI->NativeBits == NULL ) || 
00608         ( ESI->EventInfoArray == NULL )  ||
00609     ( ESI->profile.prof == NULL ) || 
00610         ( ESI->overflow.deadline == NULL ) ) {
00611 
00612       if ( ESI->sw_stop ) papi_free( ESI->sw_stop );
00613       if ( ESI->hw_start ) papi_free( ESI->hw_start );
00614       if ( ESI->EventInfoArray ) papi_free( ESI->EventInfoArray );
00615       if ( ESI->NativeInfoArray ) papi_free( ESI->NativeInfoArray );
00616       if ( ESI->NativeBits ) papi_free( ESI->NativeBits );
00617       if ( ESI->ctl_state ) papi_free( ESI->ctl_state );
00618       if ( ESI->overflow.deadline ) papi_free( ESI->overflow.deadline );
00619       if ( ESI->profile.prof ) papi_free( ESI->profile.prof );
00620       papi_free( ESI );
00621       return PAPI_ENOMEM;
00622    }
00623 
00624 
00625    /* Carve up the overflow block into separate arrays */
00626    ptr = ( char * ) ESI->overflow.deadline;
00627    ptr += sizeof ( long long ) * max_counters;
00628    ESI->overflow.threshold = ( int * ) ptr;
00629    ptr += sizeof ( int ) * max_counters;
00630    ESI->overflow.EventIndex = ( int * ) ptr;
00631    ptr += sizeof ( int ) * max_counters;
00632    ESI->overflow.EventCode = ( int * ) ptr;
00633 
00634    /* Carve up the profile block into separate arrays */
00635    ptr = ( char * ) ESI->profile.prof +
00636         ( sizeof ( PAPI_sprofil_t * ) * max_counters );
00637    ESI->profile.count = ( int * ) ptr;
00638    ptr += sizeof ( int ) * max_counters;
00639    ESI->profile.threshold = ( int * ) ptr;
00640    ptr += sizeof ( int ) * max_counters;
00641    ESI->profile.EventIndex = ( int * ) ptr;
00642    ptr += sizeof ( int ) * max_counters;
00643    ESI->profile.EventCode = ( int * ) ptr;
00644 
00645    /* initialize_EventInfoArray */
00646 
00647    for ( i = 0; i < max_counters; i++ ) {
00648        ESI->EventInfoArray[i].event_code=( unsigned int ) PAPI_NULL;
00649        ESI->EventInfoArray[i].ops = NULL;
00650        ESI->EventInfoArray[i].derived=NOT_DERIVED;
00651        for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
00652        ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
00653        }
00654    }
00655 
00656    /* initialize_NativeInfoArray */
00657    for( i = 0; i < max_counters; i++ ) {
00658       ESI->NativeInfoArray[i].ni_event = -1;
00659       ESI->NativeInfoArray[i].ni_position = -1;
00660       ESI->NativeInfoArray[i].ni_owners = 0;
00661       ESI->NativeInfoArray[i].ni_bits = ((unsigned char*)ESI->NativeBits) + 
00662                                           (i*_papi_hwd[cidx]->size.reg_value);
00663    }
00664 
00665    ESI->NativeCount = 0;
00666 
00667    ESI->state = PAPI_STOPPED;
00668 
00669    /* these used to be init_config */
00670    retval = _papi_hwd[cidx]->init_control_state( ESI->ctl_state );  
00671    retval |= _papi_hwd[cidx]->set_domain( ESI->ctl_state, ESI->domain.domain);
00672 
00673    return retval;
00674 }
00675 
00676 /*========================================================================*/
00677 /* This function should free memory for one EventSetInfo_t structure.     */
00678 /* The argument list consists of a pointer to the EventSetInfo_t          */
00679 /* structure, *ESI.                                                       */
00680 /* The calling function should check  for ESI==NULL.                      */
00681 /*========================================================================*/
00682 
00683 void
00684 _papi_hwi_free_EventSet( EventSetInfo_t * ESI )
00685 {
00686 
00687     if ( ESI->EventInfoArray )
00688         papi_free( ESI->EventInfoArray );
00689     if ( ESI->NativeInfoArray )
00690         papi_free( ESI->NativeInfoArray );
00691     if ( ESI->NativeBits )
00692         papi_free( ESI->NativeBits );
00693     if ( ESI->overflow.deadline )
00694         papi_free( ESI->overflow.deadline );
00695     if ( ESI->profile.prof )
00696         papi_free( ESI->profile.prof );
00697     if ( ESI->ctl_state )
00698         papi_free( ESI->ctl_state );
00699     if ( ESI->sw_stop )
00700         papi_free( ESI->sw_stop );
00701     if ( ESI->hw_start )
00702         papi_free( ESI->hw_start );
00703     if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
00704         papi_free( ESI->multiplex.mpx_evset );
00705     if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
00706         _papi_hwi_shutdown_cpu( ESI->CpuInfo );
00707 
00708 #ifdef DEBUG
00709     memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
00710 #endif
00711     papi_free( ESI );
00712 
00713 }
00714 
00715 static int
00716 add_EventSet( EventSetInfo_t * ESI, ThreadInfo_t * master )
00717 {
00718     DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
00719     int i, errorCode;
00720 
00721     _papi_hwi_lock( INTERNAL_LOCK );
00722 
00723     if ( map->availSlots == 0 ) {
00724         errorCode = expand_dynamic_array( map );
00725         if ( errorCode < PAPI_OK ) {
00726             _papi_hwi_unlock( INTERNAL_LOCK );
00727             return ( errorCode );
00728         }
00729     }
00730 
00731     i = 0;
00732     for ( i = 0; i < map->totalSlots; i++ ) {
00733         if ( map->dataSlotArray[i] == NULL ) {
00734             ESI->master = master;
00735             ESI->EventSetIndex = i;
00736             map->fullSlots++;
00737             map->availSlots--;
00738             map->dataSlotArray[i] = ESI;
00739             _papi_hwi_unlock( INTERNAL_LOCK );
00740             return ( PAPI_OK );
00741         }
00742     }
00743 
00744     _papi_hwi_unlock( INTERNAL_LOCK );
00745     return ( PAPI_EBUG );
00746 }
00747 
00748 int
00749 _papi_hwi_create_eventset( int *EventSet, ThreadInfo_t * handle )
00750 {
00751     EventSetInfo_t *ESI;
00752     int retval;
00753 
00754     /* Is the EventSet already in existence? */
00755 
00756     if ( ( EventSet == NULL ) || ( handle == NULL ) )
00757         return PAPI_EINVAL;
00758 
00759     if ( *EventSet != PAPI_NULL )
00760         return PAPI_EINVAL;
00761 
00762     /* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
00763 
00764     retval = create_EventSet( &ESI );
00765     if ( retval != PAPI_OK )
00766         return retval;
00767 
00768     ESI->CmpIdx = -1;        /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
00769     ESI->state = PAPI_STOPPED;
00770 
00771     /* Add it to the global table */
00772 
00773     retval = add_EventSet( ESI, handle );
00774     if ( retval < PAPI_OK ) {
00775         _papi_hwi_free_EventSet( ESI );
00776         return retval ;
00777     }
00778 
00779     *EventSet = ESI->EventSetIndex;
00780 
00781     INTDBG( "(%p,%p): new EventSet in slot %d\n",
00782             ( void * ) EventSet, handle, *EventSet );
00783 
00784     return retval;
00785 }
00786 
00787 /* This function returns the index of the the next free slot
00788    in the EventInfoArray. If EventCode is already in the list,
00789    it returns PAPI_ECNFLCT. */
00790 
00791 static int
00792 get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
00793 {
00794     int k;
00795     int lowslot = PAPI_ECNFLCT;
00796     int limit = EventInfoArrayLength( ESI );
00797 
00798     /* Check for duplicate events and get the lowest empty slot */
00799 
00800     for ( k = 0; k < limit; k++ ) {
00801         if ( ESI->EventInfoArray[k].event_code == EventCode )
00802             return ( PAPI_ECNFLCT );
00803         /*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
00804         if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
00805             lowslot = k;
00806             break;
00807         }
00808     }
00809     return ( lowslot );
00810 }
00811 
00812 /* This function returns the index of the EventCode or error */
00813 /* Index to what? The index to everything stored EventCode in the */
00814 /* EventSet. */
00815 
00816 int
00817 _papi_hwi_lookup_EventCodeIndex( const EventSetInfo_t * ESI,
00818                  unsigned int EventCode )
00819 {
00820     int i;
00821     int limit = EventInfoArrayLength( ESI );
00822 
00823     for ( i = 0; i < limit; i++ ) {
00824        if ( ESI->EventInfoArray[i].event_code == EventCode ) {
00825           return i;
00826        }
00827     }
00828 
00829     return PAPI_EINVAL;
00830 }
00831 
00832 /* This function only removes empty EventSets */
00833 
00834 int
00835 _papi_hwi_remove_EventSet( EventSetInfo_t * ESI )
00836 {
00837     DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
00838     int i;
00839 
00840     i = ESI->EventSetIndex;
00841 
00842     _papi_hwi_lock( INTERNAL_LOCK );
00843 
00844     _papi_hwi_free_EventSet( ESI );
00845 
00846     /* do bookkeeping for PAPI_EVENTSET_MAP */
00847 
00848     map->dataSlotArray[i] = NULL;
00849     map->availSlots++;
00850     map->fullSlots--;
00851 
00852     _papi_hwi_unlock( INTERNAL_LOCK );
00853 
00854     return PAPI_OK;
00855 }
00856 
00857 
00858 /* this function checks if an event is already in an EventSet
00859      Success, return ESI->NativeInfoArray[] index
00860      Fail,    return PAPI_ENOEVNT;
00861 */
00862 static int
00863 event_already_in_eventset( EventSetInfo_t * ESI, int nevt )
00864 {
00865    int i;
00866 
00867    /* to find the native event from the native events list */
00868    for( i = 0; i < ESI->NativeCount; i++ ) {
00869       if ( _papi_hwi_eventcode_to_native(nevt) == 
00870                                         ESI->NativeInfoArray[i].ni_event ) {
00871      INTDBG( "found native event already mapped: 0x%x\n", nevt );
00872      return i;
00873       }
00874    }
00875    return PAPI_ENOEVNT;
00876 }
00877 
00878 /* This function goes through the events in an EventSet's EventInfoArray */
00879 /* And maps each event (whether native or part of a preset) to           */
00880 /* an event in the EventSets NativeInfoArray.                            */
00881 
00882 /* We need to do this every time a native event is added to or removed   */
00883 /* from an eventset.                                                     */
00884 
00885 /* It is also called after a update controlstate as the components are   */
00886 /* allowed to re-arrange the native events to fit hardware constraints.  */
00887 
00888 void
00889 _papi_hwi_map_events_to_native( EventSetInfo_t *ESI)
00890 {
00891 
00892     int i, event, k, n, preset_index = 0, nevt;
00893     int total_events = ESI->NumberOfEvents;
00894 
00895     APIDBG("Mapping %d events in EventSet %d\n",
00896        total_events,ESI->EventSetIndex);
00897    
00898     event = 0;
00899     for( i = 0; i < total_events; i++ ) {
00900 
00901        /* find the first event that isn't PAPI_NULL */
00902        /* Is this really necessary? --vmw           */
00903        while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
00904           event++;
00905        }
00906        
00907        /* If it's a preset */
00908        if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
00909       preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
00910 
00911       /* walk all sub-events in the preset */
00912       for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
00913          nevt = _papi_hwi_presets[preset_index].code[k];
00914          if ( nevt == PAPI_NULL ) {
00915         break;
00916          }
00917 
00918          APIDBG("Loking for subevent %x\n",nevt);
00919 
00920          /* Match each sub-event to something in the Native List */
00921          for( n = 0; n < ESI->NativeCount; n++ ) {
00922             if ( _papi_hwi_eventcode_to_native(nevt) == 
00923                                  ESI->NativeInfoArray[n].ni_event ) {
00924            APIDBG("Found event %x at position %d\n",
00925               nevt,
00926               ESI->NativeInfoArray[n].ni_position);
00927            ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
00928            break;
00929         }
00930          }
00931       }
00932        } 
00933        /* It's a native event */
00934        else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
00935       nevt = ( int ) ESI->EventInfoArray[event].event_code;
00936 
00937       /* Look for the event in the NativeInfoArray */
00938       for( n = 0; n < ESI->NativeCount; n++ ) {
00939          if ( _papi_hwi_eventcode_to_native(nevt) == 
00940                                   ESI->NativeInfoArray[n].ni_event ) {
00941         ESI->EventInfoArray[event].pos[0] = ESI->NativeInfoArray[n].ni_position;
00942         break;
00943          }
00944       }
00945        /* It's a user-defined event */
00946        } else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
00947           for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
00948           nevt = _papi_user_events[preset_index].events[k];
00949           if ( nevt == PAPI_NULL ) break;
00950 
00951           /* Match each sub-event to something in the Native List */
00952           for ( n = 0; n < ESI->NativeCount; n++ ) {
00953          if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[n].ni_event ) {
00954             ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
00955          }
00956           }
00957       }
00958        }
00959        event++;
00960     }
00961 }
00962 
00963 
00964 static int
00965 add_native_fail_clean( EventSetInfo_t *ESI, int nevt )
00966 {
00967    int i, max_counters;
00968    int cidx;
00969 
00970    cidx = _papi_hwi_component_index( nevt );
00971    if (cidx<0) return PAPI_ENOCMP;
00972 
00973    max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
00974 
00975    /* to find the native event from the native events list */
00976    for( i = 0; i < max_counters; i++ ) {
00977      if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[i].ni_event ) {
00978      ESI->NativeInfoArray[i].ni_owners--;
00979      /* to clean the entry in the nativeInfo array */
00980      if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
00981         ESI->NativeInfoArray[i].ni_event = -1;
00982         ESI->NativeInfoArray[i].ni_position = -1;
00983         ESI->NativeCount--;
00984      }
00985      INTDBG( "add_events fail, and remove added native events "
00986                  "of the event: 0x%x\n", nevt );
00987      return i;
00988       }
00989    }
00990    return -1;
00991 }
00992 
00993 /* since update_control_state trashes overflow settings, this puts things
00994    back into balance. */
00995 static int
00996 update_overflow( EventSetInfo_t * ESI )
00997 {
00998    int i, retval = PAPI_OK;
00999 
01000    if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
01001       for( i = 0; i < ESI->overflow.event_counter; i++ ) {
01002      retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
01003                             ESI->overflow.EventIndex[i],
01004                             ESI->overflow.threshold[i] );
01005      if ( retval != PAPI_OK ) {
01006         break;
01007      }
01008       }
01009    }
01010    return retval;
01011 }
01012 
01013 /* this function is called by _papi_hwi_add_event when adding native events 
01014    ESI:   event set to add the events to
01015    nevnt: pointer to array of native event table indexes to add
01016    size:  number of native events to add
01017    out:   ???
01018 
01019    return:  < 0 = error
01020               0 = no new events added
01021               1 = new events added
01022 */
01023 static int
01024 add_native_events( EventSetInfo_t *ESI, unsigned int *nevt, 
01025                    int size, EventInfo_t *out )
01026 {
01027    int nidx, i, j, added_events = 0;
01028    int retval, retval2;
01029    int max_counters;
01030    hwd_context_t *context;
01031 
01032    max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
01033 
01034    /* Walk through the list of native events, adding them */
01035    for( i = 0; i < size; i++ ) {
01036 
01037       /* Check to see if event is already in EventSet */
01038       nidx = event_already_in_eventset( ESI, nevt[i] );
01039 
01040       if ( nidx >= 0 ) {
01041      /* Event is already there.  Set position */
01042      out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
01043      ESI->NativeInfoArray[nidx].ni_owners++;
01044 
01045       } else {
01046 
01047      /* Event wasn't already there */
01048 
01049      if ( ESI->NativeCount == max_counters ) {
01050 
01051         /* No more room in counters! */
01052         for( j = 0; j < i; j++ ) {
01053            if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
01054           out->pos[j] = -1;
01055           continue;
01056            }
01057            INTDBG( "should not happen!\n" );
01058         }
01059         INTDBG( "counters are full!\n" );
01060         return PAPI_ECOUNT;
01061      }
01062      else {
01063             
01064         /* there is an empty slot for the native event; */
01065         /* initialize the native index for the new added event */
01066         INTDBG( "Adding 0x%x to ESI %p Component %d\n", 
01067             nevt[i], ESI, ESI->CmpIdx );
01068         ESI->NativeInfoArray[ESI->NativeCount].ni_event = 
01069               _papi_hwi_eventcode_to_native(nevt[i]);
01070 
01071         ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
01072         ESI->NativeCount++;
01073         added_events++;
01074      }
01075       }
01076    }
01077 
01078    /* if we added events we need to tell the component so it */
01079    /* can add them too.                                      */
01080    if ( added_events ) {
01081       /* get the context we should use for this event set */
01082       context = _papi_hwi_get_context( ESI, NULL );
01083        
01084       if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
01085 
01086      retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01087           ESI->NativeInfoArray,
01088           ESI->NativeCount,
01089           context);
01090      if ( retval != PAPI_OK ) {
01091 clean:
01092         for( i = 0; i < size; i++ ) {
01093            if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
01094           out->pos[i] = -1;
01095           continue;
01096            }
01097            INTDBG( "should not happen!\n" );
01098         }
01099         /* re-establish the control state after the previous error */
01100         retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state( 
01101                        ESI->ctl_state,
01102                ESI->NativeInfoArray,
01103                ESI->NativeCount,
01104                context);
01105         if ( retval2 != PAPI_OK ) {
01106            PAPIERROR("update_control_state failed to re-establish "
01107              "working events!" );
01108            return retval2;
01109         }
01110         return retval;
01111      }
01112      return 1; /* need remap */
01113       } else {
01114      retval = PAPI_EMISC;
01115      goto clean;
01116       }
01117    }
01118    return PAPI_OK;
01119 }
01120 
01121 
01122 int
01123 _papi_hwi_add_event( EventSetInfo_t * ESI, int EventCode )
01124 {
01125     int i, j, thisindex, remap, retval = PAPI_OK;
01126     int cidx;
01127 
01128     cidx=_papi_hwi_component_index( EventCode );
01129     if (cidx<0) return PAPI_ENOCMP;
01130 
01131     /* Sanity check that the new EventCode is from the same component */
01132     /* as previous events.                                            */
01133     
01134     if ( ESI->CmpIdx < 0 ) {
01135        if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx) != PAPI_OK )) {
01136           return retval;
01137        }
01138     } else {
01139        if ( ESI->CmpIdx != cidx ) {
01140       return PAPI_EINVAL;
01141        }
01142     }
01143 
01144     /* Make sure the event is not present and get the next free slot. */
01145     thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
01146     if ( thisindex < PAPI_OK ) {
01147        return thisindex;
01148     }
01149 
01150     APIDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
01151 
01152     /* If it is a software MPX EventSet, add it to the multiplex data structure */
01153     /* and this thread's multiplex list                                         */
01154 
01155     if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
01156 
01157        /* Handle preset case */
01158        if ( IS_PRESET(EventCode) ) {
01159       int count;
01160       int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
01161 
01162       /* Check if it's within the valid range */
01163       if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
01164          return PAPI_EINVAL;
01165       }
01166 
01167       /* count the number of native events in this preset */
01168       count = ( int ) _papi_hwi_presets[preset_index].count;
01169 
01170       /* Check if event exists */
01171       if ( !count ) {
01172          return PAPI_ENOEVNT;
01173       }
01174             
01175       /* check if the native events have been used as overflow events */
01176       /* this is not allowed                                          */
01177       if ( ESI->state & PAPI_OVERFLOWING ) {
01178          for( i = 0; i < count; i++ ) {
01179         for( j = 0; j < ESI->overflow.event_counter; j++ ) {
01180           if ( ESI->overflow.EventCode[j] ==(int)
01181             ( _papi_hwi_presets[preset_index].code[i] ) ) {
01182               return PAPI_ECNFLCT;
01183            }
01184         }
01185          }
01186       }
01187 
01188       /* Try to add the preset. */
01189 
01190       remap = add_native_events( ESI,
01191                      _papi_hwi_presets[preset_index].code,
01192                      count, &ESI->EventInfoArray[thisindex] );
01193       if ( remap < 0 ) {
01194          return PAPI_ECNFLCT;
01195       }
01196           else {
01197          /* Fill in the EventCode (machine independent) information */
01198          ESI->EventInfoArray[thisindex].event_code = 
01199                                   ( unsigned int ) EventCode;
01200          ESI->EventInfoArray[thisindex].derived =
01201                   _papi_hwi_presets[preset_index].derived_int;
01202          ESI->EventInfoArray[thisindex].ops =
01203                   _papi_hwi_presets[preset_index].postfix;
01204              ESI->NumberOfEvents++;
01205          _papi_hwi_map_events_to_native( ESI );
01206          
01207       }
01208        }
01209        /* Handle adding Native events */
01210        else if ( IS_NATIVE(EventCode) ) {
01211 
01212       /* Check if native event exists */
01213       if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
01214          return PAPI_ENOEVNT;
01215       }
01216             
01217       /* check if the native events have been used as overflow events */
01218       /* This is not allowed                                          */
01219       if ( ESI->state & PAPI_OVERFLOWING ) {
01220          for( j = 0; j < ESI->overflow.event_counter; j++ ) {
01221             if ( EventCode == ESI->overflow.EventCode[j] ) {
01222            return PAPI_ECNFLCT;
01223         }
01224          }
01225       }
01226 
01227       /* Try to add the native event. */
01228 
01229       remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
01230                      &ESI->EventInfoArray[thisindex] );
01231 
01232       if ( remap < 0 ) {
01233          return PAPI_ECNFLCT;
01234       } else {
01235 
01236          /* Fill in the EventCode (machine independent) information */
01237          ESI->EventInfoArray[thisindex].event_code = 
01238                                        ( unsigned int ) EventCode;
01239              ESI->NumberOfEvents++;
01240          _papi_hwi_map_events_to_native( ESI );
01241          
01242       }
01243        } else if ( IS_USER_DEFINED( EventCode ) ) {
01244          int count;
01245          int index = EventCode & PAPI_UE_AND_MASK;
01246 
01247          if ( index < 0 || index >= (int)_papi_user_events_count )
01248            return ( PAPI_EINVAL );
01249 
01250          count = ( int ) _papi_user_events[index].count;
01251 
01252          for ( i = 0; i < count; i++ ) {
01253            for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
01254              if ( ESI->overflow.EventCode[j] ==
01255                  _papi_user_events[index].events[i] ) {
01256                return ( PAPI_EBUG );
01257              }
01258            }
01259          }
01260 
01261          remap = add_native_events( ESI,
01262              (unsigned int*)_papi_user_events[index].events,
01263              count, &ESI->EventInfoArray[thisindex] );
01264 
01265          if ( remap < 0 ) {
01266            return PAPI_ECNFLCT;
01267          } else {
01268            ESI->EventInfoArray[thisindex].event_code       
01269                                          = (unsigned int) EventCode;
01270            ESI->EventInfoArray[thisindex].derived          
01271                                          = DERIVED_POSTFIX;
01272            ESI->EventInfoArray[thisindex].ops                      
01273                                          = _papi_user_events[index].operation;
01274                    ESI->NumberOfEvents++;
01275            _papi_hwi_map_events_to_native( ESI );
01276          }
01277        } else {
01278 
01279       /* not Native, Preset, or User events */
01280 
01281       return PAPI_EBUG;
01282        }
01283     }
01284     else {
01285         
01286        /* Multiplexing is special. See multiplex.c */
01287 
01288        retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
01289                    ESI->domain.domain, 
01290                    ESI->granularity.granularity );
01291 
01292 
01293        if ( retval < PAPI_OK ) {
01294       return retval;
01295        }
01296 
01297        /* Relevant (???) */
01298        ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;  
01299        ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
01300 
01301        ESI->NumberOfEvents++;
01302 
01303        /* event is in the EventInfoArray but not mapped to the NativeEvents */
01304        /* this causes issues if you try to set overflow on the event.       */
01305        /* in theory this wouldn't matter anyway.                            */
01306     }
01307 
01308     /* reinstate the overflows if any */
01309     retval=update_overflow( ESI );
01310 
01311     return retval;
01312 }
01313 
01314 static int
01315 remove_native_events( EventSetInfo_t *ESI, int *nevt, int size )
01316 {
01317    NativeInfo_t *native = ESI->NativeInfoArray;
01318    hwd_context_t *context;
01319    int i, j, zero = 0, retval;
01320 
01321    /* Remove the references to this event from the native events:
01322       for all the metrics in this event,
01323       compare to each native event in this event set,
01324       and decrement owners if they match  */
01325    for( i = 0; i < size; i++ ) {
01326       for( j = 0; j < ESI->NativeCount; j++ ) {
01327      if ( native[j].ni_event ==  _papi_hwi_eventcode_to_native(nevt[i]) ) {
01328         native[j].ni_owners--;
01329         if ( native[j].ni_owners == 0 ) {
01330            zero++;
01331         }
01332         break;
01333      }
01334       }
01335    }
01336 
01337    /* Remove any native events from the array if owners dropped to zero.
01338       The NativeInfoArray must be dense, with no empty slots, so if we
01339       remove an element, we must compact the list */
01340    for( i = 0; i < ESI->NativeCount; i++ ) {
01341 
01342       if ( native[i].ni_event == -1 ) continue;
01343 
01344       if ( native[i].ni_owners == 0 ) {
01345      int copy = 0;
01346      int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
01347      for( j = ESI->NativeCount - 1; j > i; j-- ) {
01348         if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
01349         else {
01350            /* copy j into i */
01351            native[i].ni_event = native[j].ni_event;
01352            native[i].ni_position = native[j].ni_position;
01353            native[i].ni_owners = native[j].ni_owners;
01354            /* copy opaque [j].ni_bits to [i].ni_bits */
01355            memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
01356            /* reset j to initialized state */
01357            native[j].ni_event = -1;
01358            native[j].ni_position = -1;
01359            native[j].ni_owners = 0;
01360            copy++;
01361            break;
01362         }
01363      }
01364 
01365      if ( copy == 0 ) {
01366         /* set this structure back to empty state */
01367         /* ni_owners is already 0 and contents of ni_bits doesn't matter */
01368         native[i].ni_event = -1;
01369         native[i].ni_position = -1;
01370      }
01371       }
01372    }
01373 
01374    /* to reset hwd_control_state values */
01375    ESI->NativeCount -= zero;
01376 
01377    /* If we removed any elements, 
01378       clear the now empty slots, reinitialize the index, and update the count.
01379       Then send the info down to the component to update the hwd control structure. */
01380     retval = PAPI_OK;
01381     if ( zero ) {
01382       /* get the context we should use for this event set */
01383       context = _papi_hwi_get_context( ESI, NULL );
01384         retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01385                                                           native, ESI->NativeCount, context);
01386         if ( retval == PAPI_OK )
01387             retval = update_overflow( ESI );
01388     }
01389     return ( retval );
01390 }
01391 
01392 int
01393 _papi_hwi_remove_event( EventSetInfo_t * ESI, int EventCode )
01394 {
01395     int j = 0, retval, thisindex;
01396     EventInfo_t *array;
01397 
01398     thisindex =
01399         _papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
01400     if ( thisindex < PAPI_OK )
01401         return ( thisindex );
01402 
01403     /* If it is a MPX EventSet, remove it from the multiplex data structure and
01404        this threads multiplex list */
01405 
01406     if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
01407         retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
01408         if ( retval < PAPI_OK )
01409             return ( retval );
01410     } else
01411         /* Remove the events hardware dependent stuff from the EventSet */
01412     {
01413         if ( IS_PRESET(EventCode) ) {
01414             int preset_index = EventCode & PAPI_PRESET_AND_MASK;
01415 
01416             /* Check if it's within the valid range */
01417             if ( ( preset_index < 0 ) ||
01418                  ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
01419                 return PAPI_EINVAL;
01420 
01421             /* Check if event exists */
01422             if ( !_papi_hwi_presets[preset_index].count )
01423                 return PAPI_ENOEVNT;
01424 
01425             /* Remove the preset event. */
01426             for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
01427                   j++ );
01428             retval = remove_native_events( ESI,
01429                                (int *)_papi_hwi_presets[preset_index].code, j );
01430             if ( retval != PAPI_OK )
01431                 return ( retval );
01432         } else if ( IS_NATIVE(EventCode) ) {
01433             /* Check if native event exists */
01434             if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
01435                  PAPI_OK )
01436                 return PAPI_ENOEVNT;
01437 
01438             /* Remove the native event. */
01439             retval = remove_native_events( ESI, &EventCode, 1 );
01440             if ( retval != PAPI_OK )
01441                 return ( retval );
01442         } else if ( IS_USER_DEFINED( EventCode ) ) {
01443           int index = EventCode & PAPI_UE_AND_MASK;
01444 
01445           if ( (index < 0) || (index >= (int)_papi_user_events_count) )
01446             return ( PAPI_EINVAL );
01447 
01448           for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
01449               _papi_user_events[index].events[j] != 0; j++ ) {
01450             retval = remove_native_events( ESI,
01451                 _papi_user_events[index].events, j);
01452 
01453             if ( retval != PAPI_OK )
01454               return ( retval );
01455           }
01456         } else
01457             return ( PAPI_ENOEVNT );
01458     }
01459     array = ESI->EventInfoArray;
01460 
01461     /* Compact the Event Info Array list if it's not the last event */
01462     /* clear the newly empty slot in the array */
01463     for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
01464         array[thisindex] = array[thisindex + 1];
01465 
01466 
01467     array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
01468     for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
01469         array[thisindex].pos[j] = PAPI_NULL;
01470     array[thisindex].ops = NULL;
01471     array[thisindex].derived = NOT_DERIVED;
01472     ESI->NumberOfEvents--;
01473 
01474     return ( PAPI_OK );
01475 }
01476 
01477 int
01478 _papi_hwi_read( hwd_context_t * context, EventSetInfo_t * ESI,
01479                 long long *values )
01480 {
01481     int retval;
01482     long long *dp = NULL;
01483     int i, index;
01484 
01485     retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state, 
01486                            &dp, ESI->state );
01487     if ( retval != PAPI_OK ) {
01488        return retval;
01489     }
01490 
01491     /* This routine distributes hardware counters to software counters in the
01492        order that they were added. Note that the higher level
01493        EventInfoArray[i] entries may not be contiguous because the user
01494        has the right to remove an event.
01495        But if we do compaction after remove event, this function can be 
01496        changed.  
01497      */
01498 
01499     for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
01500 
01501         index = ESI->EventInfoArray[i].pos[0];
01502 
01503         if ( index == -1 )
01504             continue;
01505 
01506         INTDBG( "Event index %d, position is 0x%x\n", i, index );
01507 
01508         /* If this is not a derived event */
01509 
01510         if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
01511             values[i] = dp[index];
01512             INTDBG( "value: 0x%llx\n", values[i] );
01513         } else {             /* If this is a derived event */
01514             values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
01515 #ifdef DEBUG
01516             if ( values[i] < ( long long ) 0 ) {
01517                 INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
01518             }
01519             INTDBG( "derived value: 0x%llx \n", values[i] );
01520 #endif
01521         }
01522     }
01523 
01524     return PAPI_OK;
01525 }
01526 
01527 int
01528 _papi_hwi_cleanup_eventset( EventSetInfo_t * ESI )
01529 {
01530    int i, j, num_cntrs, retval;
01531    hwd_context_t *context;
01532    int EventCode;
01533    NativeInfo_t *native;
01534 
01535    num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
01536 
01537    for(i=0;i<num_cntrs;i++) {
01538 
01539       EventCode=ESI->EventInfoArray[i].event_code;     
01540 
01541       /* skip if event not there */
01542       if ( EventCode == PAPI_NULL ) continue;
01543 
01544       /* If it is a MPX EventSet, remove it from the multiplex */
01545       /* data structure and this thread's multiplex list */
01546 
01547       if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
01548      retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
01549      if ( retval < PAPI_OK )
01550         return retval;
01551       } else {
01552 
01553       native = ESI->NativeInfoArray;
01554 
01555       /* clear out ESI->NativeInfoArray */
01556       /* do we really need to do this, seeing as we free() it later? */
01557 
01558       for( j = 0; j < ESI->NativeCount; j++ ) {
01559          native[j].ni_event = -1;
01560          native[j].ni_position = -1;
01561          native[j].ni_owners = 0;
01562          /* native[j].ni_bits?? */
01563       }
01564       }
01565 
01566       /* do we really need to do this, seeing as we free() it later? */
01567       ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
01568       for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
01569       ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
01570       }
01571       ESI->EventInfoArray[i].ops = NULL;
01572       ESI->EventInfoArray[i].derived = NOT_DERIVED;
01573    }
01574 
01575    context = _papi_hwi_get_context( ESI, NULL );
01576    /* calling with count of 0 equals a close? */
01577    retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01578                    NULL, 0, context);
01579    if (retval!=PAPI_OK) {
01580      return retval;
01581    }
01582 
01583    ESI->CmpIdx = -1;
01584    ESI->NumberOfEvents = 0;
01585    ESI->NativeCount = 0;
01586 
01587    if ( ESI->ctl_state )
01588       papi_free( ESI->ctl_state );
01589 
01590    if ( ESI->sw_stop )
01591       papi_free( ESI->sw_stop );
01592 
01593    if ( ESI->hw_start )
01594       papi_free( ESI->hw_start );
01595     
01596    if ( ESI->EventInfoArray )
01597       papi_free( ESI->EventInfoArray );
01598     
01599    if ( ESI->NativeInfoArray ) 
01600       papi_free( ESI->NativeInfoArray );
01601 
01602    if ( ESI->NativeBits ) 
01603       papi_free( ESI->NativeBits );
01604     
01605    if ( ESI->overflow.deadline )
01606       papi_free( ESI->overflow.deadline );
01607     
01608    if ( ESI->profile.prof )
01609       papi_free( ESI->profile.prof );
01610 
01611    ESI->ctl_state = NULL;
01612    ESI->sw_stop = NULL;
01613    ESI->hw_start = NULL;
01614    ESI->EventInfoArray = NULL;
01615    ESI->NativeInfoArray = NULL;
01616    ESI->NativeBits = NULL;
01617 
01618    memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
01619    memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
01620    memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
01621    memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
01622    memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
01623    memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
01624    memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
01625    memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
01626 
01627    ESI->CpuInfo = NULL;
01628 
01629    return PAPI_OK;
01630 }
01631 
01632 int
01633 _papi_hwi_convert_eventset_to_multiplex( _papi_int_multiplex_t * mpx )
01634 {
01635     int retval, i, j = 0, *mpxlist = NULL;
01636     EventSetInfo_t *ESI = mpx->ESI;
01637     int flags = mpx->flags;
01638 
01639     /* If there are any events in the EventSet, 
01640        convert them to multiplex events */
01641 
01642     if ( ESI->NumberOfEvents ) {
01643 
01644         mpxlist =
01645             ( int * ) papi_malloc( sizeof ( int ) *
01646                                    ( size_t ) ESI->NumberOfEvents );
01647         if ( mpxlist == NULL )
01648             return ( PAPI_ENOMEM );
01649 
01650         /* Build the args to MPX_add_events(). */
01651 
01652         /* Remember the EventInfoArray can be sparse
01653            and the data can be non-contiguous */
01654 
01655         for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
01656             if ( ESI->EventInfoArray[i].event_code !=
01657                  ( unsigned int ) PAPI_NULL )
01658                 mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
01659 
01660         /* Resize the EventInfo_t array */
01661 
01662         if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
01663              ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
01664                ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
01665             retval =
01666                 MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
01667                                 ESI->domain.domain,
01668                                 ESI->granularity.granularity );
01669             if ( retval != PAPI_OK ) {
01670                 papi_free( mpxlist );
01671                 return ( retval );
01672             }
01673         }
01674 
01675         papi_free( mpxlist );
01676     }
01677 
01678     /* Update the state before initialization! */
01679 
01680     ESI->state |= PAPI_MULTIPLEXING;
01681     if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
01682          ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
01683         ESI->multiplex.flags = PAPI_MULTIPLEX_FORCE_SW;
01684     ESI->multiplex.ns = ( int ) mpx->ns;
01685 
01686     return ( PAPI_OK );
01687 }
01688 
01689 #include "components_config.h"
01690 
01691 int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
01692 
01693 /*
01694  * Routine that initializes all available components.
01695  * A component is available if a pointer to its info vector
01696  * appears in the NULL terminated_papi_hwd table.
01697  */
01698 int
01699 _papi_hwi_init_global( void )
01700 {
01701         int retval, i = 0;
01702 
01703     retval = _papi_hwi_innoculate_os_vector( &_papi_os_vector );
01704     if ( retval != PAPI_OK ) {
01705        return retval;
01706     }
01707 
01708     while ( _papi_hwd[i] ) {
01709 
01710        retval = _papi_hwi_innoculate_vector( _papi_hwd[i] );
01711        if ( retval != PAPI_OK ) {
01712           return retval;
01713        }
01714 
01715        /* We can be disabled by user before init */
01716        if (!_papi_hwd[i]->cmp_info.disabled) {
01717           retval = _papi_hwd[i]->init_component( i );
01718           _papi_hwd[i]->cmp_info.disabled=retval;
01719 
01720           /* Do some sanity checking */
01721           if (retval==PAPI_OK) {
01722         if (_papi_hwd[i]->cmp_info.num_cntrs >
01723             _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
01724           fprintf(stderr,"Warning!  num_cntrs is more than num_mpx_cntrs\n");
01725         }
01726 
01727           }
01728        }
01729 
01730        i++;
01731     }
01732     return PAPI_OK;
01733 }
01734 
01735 /* Machine info struct initialization using defaults */
01736 /* See _papi_mdi definition in papi_internal.h       */
01737 
01738 int
01739 _papi_hwi_init_global_internal( void )
01740 {
01741 
01742     int retval;
01743 
01744     memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
01745 
01746     memset( _papi_hwi_using_signal,0x0,sizeof( _papi_hwi_using_signal ));
01747 
01748     /* Global struct to maintain EventSet mapping */
01749     retval = allocate_eventset_map( &_papi_hwi_system_info.global_eventset_map );
01750     if ( retval != PAPI_OK ) {
01751         return retval;
01752     }
01753 
01754     _papi_hwi_system_info.pid = 0;  /* Process identifier */
01755 
01756     /* PAPI_hw_info_t struct */
01757     memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
01758 
01759     return PAPI_OK;
01760 }
01761 
01762 void
01763 _papi_hwi_shutdown_global_internal( void )
01764 {
01765     _papi_hwi_cleanup_all_presets(  );
01766 
01767     _papi_hwi_cleanup_errors( );
01768 
01769     _papi_hwi_lock( INTERNAL_LOCK );
01770 
01771     papi_free(  _papi_hwi_system_info.global_eventset_map.dataSlotArray );
01772     memset(  &_papi_hwi_system_info.global_eventset_map, 
01773          0x00, sizeof ( DynamicArray_t ) );
01774 
01775     _papi_hwi_unlock( INTERNAL_LOCK );
01776 
01777     if ( _papi_hwi_system_info.shlib_info.map ) {
01778         papi_free( _papi_hwi_system_info.shlib_info.map );
01779     }
01780     memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
01781 
01782 }
01783 
01784 
01785 
01786 void
01787 _papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
01788                          void *context )
01789 {
01790     /* This function is not used and shouldn't be called. */
01791     ( void ) EventSet;       /*unused */
01792     ( void ) address;        /*unused */
01793     ( void ) overflow_vector;   /*unused */
01794     ( void ) context;        /*unused */
01795     return;
01796 }
01797 
01798 static long long
01799 handle_derived_add( int *position, long long *from )
01800 {
01801     int pos, i;
01802     long long retval = 0;
01803 
01804     i = 0;
01805     while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
01806         pos = position[i++];
01807         if ( pos == PAPI_NULL )
01808             break;
01809         INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
01810         retval += from[pos];
01811     }
01812     return ( retval );
01813 }
01814 
01815 static long long
01816 handle_derived_subtract( int *position, long long *from )
01817 {
01818     int pos, i;
01819     long long retval = from[position[0]];
01820 
01821     i = 1;
01822     while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
01823         pos = position[i++];
01824         if ( pos == PAPI_NULL )
01825             break;
01826         INTDBG( "Compound event, subtracting pos=%d  %lld from %lld\n", pos,
01827                 from[pos], retval );
01828         retval -= from[pos];
01829     }
01830     return ( retval );
01831 }
01832 
01833 static long long
01834 units_per_second( long long units, long long cycles )
01835 {
01836    return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
01837               (long long) 1000000 ) / cycles );
01838 }
01839 
01840 static long long
01841 handle_derived_ps( int *position, long long *from )
01842 {
01843     return ( units_per_second( from[position[1]], from[position[0]] ) );
01844 }
01845 static long long
01846 handle_derived_add_ps( int *position, long long *from )
01847 {
01848     long long tmp = handle_derived_add( position + 1, from );
01849     return ( units_per_second( tmp, from[position[0]] ) );
01850 }
01851 
01852 /* this function implement postfix calculation, it reads in a string where I use:
01853       |      as delimiter
01854       N2     indicate No. 2 native event in the derived preset
01855       +, -, *, /, %  as operator
01856       #      as MHZ(million hz) got from  _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
01857 
01858   Haihang (you@cs.utk.edu)
01859 */ 
01860 static long long
01861 _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
01862 {
01863     char *point = evi->ops, operand[16];
01864     double stack[PAPI_EVENTS_IN_DERIVED_EVENT];
01865     int i, top = 0;
01866 
01867     memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
01868 
01869     while ( *point != '\0' ) {
01870         if ( *point == 'N' ) {  /* to get count for each native event */
01871             i = 0;
01872             point++;
01873             do {
01874                 operand[i] = *point;
01875                 point++;
01876                 i++;
01877             } while ( *point != '|' );
01878             operand[i] = '\0';
01879             stack[top] = ( double ) hw_counter[evi->pos[atoi( operand )]];
01880             top++;
01881             point++;
01882         } else if ( *point == '#' ) {   /* to get mhz, ignore the rest char's */
01883             stack[top] = _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000000.0;
01884             top++;
01885             do {
01886                 point++;
01887             } while ( *point != '|' );
01888             point++;
01889         } else if ( isdigit( *point ) ) {   /* to get integer, I suppose only integer will be used, 
01890                                                no error check here, please only use integer */
01891             i = 0;
01892             do {
01893                 operand[i] = *point;
01894                 point++;
01895                 i++;
01896             } while ( *point != '|' );
01897             operand[i] = '\0';
01898             stack[top] = atoi( operand );
01899             top++;
01900             point++;
01901         } else if ( *point == '+' ) {   /* + calculation */
01902             stack[top - 2] += stack[top - 1];
01903             top--;
01904             do {
01905                 point++;
01906             } while ( *point != '|' );
01907             point++;
01908         } else if ( *point == '-' ) {   /* - calculation */
01909             stack[top - 2] -= stack[top - 1];
01910             top--;
01911             do {
01912                 point++;
01913             } while ( *point != '|' );
01914             point++;
01915         } else if ( *point == '*' ) {   /* * calculation */
01916             stack[top - 2] *= stack[top - 1];
01917             top--;
01918             do {
01919                 point++;
01920             } while ( *point != '|' );
01921             point++;
01922         } else if ( *point == '/' ) {   /* / calculation */
01923             stack[top - 2] /= stack[top - 1];
01924             top--;
01925             do {
01926                 point++;
01927             } while ( *point != '|' );
01928             point++;
01929         } else {             /* do nothing */
01930             do {
01931                 point++;
01932             } while ( *point != '|' );
01933             point++;
01934         }
01935     }
01936     return ( long long ) stack[0];
01937 }
01938 
01939 static long long
01940 handle_derived( EventInfo_t * evi, long long *from )
01941 {
01942     switch ( evi->derived ) {
01943     case DERIVED_ADD:
01944         return ( handle_derived_add( evi->pos, from ) );
01945     case DERIVED_ADD_PS:
01946         return ( handle_derived_add_ps( evi->pos, from ) );
01947     case DERIVED_SUB:
01948         return ( handle_derived_subtract( evi->pos, from ) );
01949     case DERIVED_PS:
01950         return ( handle_derived_ps( evi->pos, from ) );
01951     case DERIVED_POSTFIX:
01952         return ( _papi_hwi_postfix_calc( evi, from ) );
01953     case DERIVED_CMPD:       /* This type has existed for a long time, but was never implemented.
01954                                 Probably because its a no-op. However, if it's in a header, it
01955                                 should be supported. As I found out when I implemented it in 
01956                                 Pentium 4 for testing...dkt */
01957         return ( from[evi->pos[0]] );
01958     default:
01959         PAPIERROR( "BUG! Unknown derived command %d, returning 0",
01960                    evi->derived );
01961         return ( ( long long ) 0 );
01962     }
01963 }
01964 
01965 
01966 /* table matching derived types to derived strings.                             
01967    used by get_info, encode_event, xml translator                               
01968 */
01969 static const hwi_describe_t _papi_hwi_derived[] = {
01970   {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
01971   {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
01972   {DERIVED_PS, "DERIVED_PS",
01973    "Divide by the cycle counter and convert to seconds"},
01974   {DERIVED_ADD_PS, "DERIVED_ADD_PS",
01975    "Add 2 counters then divide by the cycle counter and xl8 to secs."},
01976   {DERIVED_CMPD, "DERIVED_CMPD",
01977    "Event lives in first counter but takes 2 or more codes"},
01978   {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
01979   {DERIVED_POSTFIX, "DERIVED_POSTFIX",
01980    "Process counters based on specified postfix string"},
01981   {-1, NULL, NULL}
01982 };
01983 
01984 /* _papi_hwi_derived_type:
01985    Helper routine to extract a derived type from a derived string
01986    returns type value if found, otherwise returns -1
01987 */
01988 int
01989 _papi_hwi_derived_type( char *tmp, int *code )
01990 {
01991   int i = 0;
01992   while ( _papi_hwi_derived[i].name != NULL ) {
01993     if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
01994       *code = _papi_hwi_derived[i].value;
01995       return PAPI_OK;
01996     }
01997     i++;
01998   }
01999   INTDBG( "Invalid derived string %s\n", tmp );
02000   return PAPI_EINVAL;
02001 }
02002 
02003 
02004 /* _papi_hwi_derived_string:
02005    Helper routine to extract a derived string from a derived type  
02006    copies derived type string into derived if found,
02007    otherwise returns PAPI_EINVAL
02008 */
02009 static int
02010 _papi_hwi_derived_string( int type, char *derived, int len )
02011 {
02012   int j;
02013 
02014   for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
02015     if ( _papi_hwi_derived[j].value == type ) {
02016       strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
02017            len );
02018       return PAPI_OK;
02019     }
02020   }
02021   INTDBG( "Invalid derived type %d\n", type );
02022   return PAPI_EINVAL;
02023 }
02024 
02025 
02026 /* _papi_hwi_get_preset_event_info:
02027    Assumes EventCode contains a valid preset code.
02028    But defensive programming says check for NULL pointers.
02029    Returns a filled in PAPI_event_info_t structure containing
02030    descriptive strings and values for the specified preset event.
02031 */
02032 int
02033 _papi_hwi_get_preset_event_info( int EventCode, PAPI_event_info_t * info )
02034 {
02035     int i = EventCode & PAPI_PRESET_AND_MASK;
02036     unsigned int j;
02037 
02038     if ( _papi_hwi_presets[i].symbol ) {    /* if the event is in the preset table */
02039        /* set whole structure to 0 */
02040        memset( info, 0, sizeof ( PAPI_event_info_t ) );
02041 
02042        info->event_code = ( unsigned int ) EventCode;
02043        strncpy( info->symbol, _papi_hwi_presets[i].symbol,
02044             sizeof(info->symbol));
02045 
02046        if ( _papi_hwi_presets[i].short_descr != NULL )
02047           strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
02048                           sizeof ( info->short_descr ) );
02049 
02050        if ( _papi_hwi_presets[i].long_descr != NULL )
02051           strncpy( info->long_descr,  _papi_hwi_presets[i].long_descr,
02052                           sizeof ( info->long_descr ) );
02053 
02054        info->event_type = _papi_hwi_presets[i].event_type;
02055        info->count = _papi_hwi_presets[i].count;
02056 
02057        _papi_hwi_derived_string( _papi_hwi_presets[i].derived_int,
02058                      info->derived,  sizeof ( info->derived ) );
02059 
02060        if ( _papi_hwi_presets[i].postfix != NULL )
02061           strncpy( info->postfix, _papi_hwi_presets[i].postfix,
02062                           sizeof ( info->postfix ) );
02063 
02064        for(j=0;j < info->count; j++) {
02065           info->code[j]=_papi_hwi_presets[i].code[j];
02066           strncpy(info->name[j], _papi_hwi_presets[i].name[j],
02067               sizeof(info->name[j]));
02068        }
02069 
02070        if ( _papi_hwi_presets[i].note != NULL ) {
02071           strncpy( info->note, _papi_hwi_presets[i].note,
02072                           sizeof ( info->note ) );
02073        }
02074 
02075        return PAPI_OK;
02076     } else {
02077        return PAPI_ENOEVNT;
02078     }
02079 }
02080 
02081 
02082 /* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
02083    Used to enumerate the entire array, e.g. for native_avail.c */
02084 int
02085 _papi_hwi_query_native_event( unsigned int EventCode )
02086 {
02087    char name[PAPI_HUGE_STR_LEN];      /* probably overkill, */
02088                                       /* but should always be big enough */
02089    int cidx;
02090 
02091    cidx = _papi_hwi_component_index( EventCode );
02092    if (cidx<0) return PAPI_ENOCMP;
02093 
02094    return ( _papi_hwd[cidx]->ntv_code_to_name( 
02095                     _papi_hwi_eventcode_to_native(EventCode), 
02096                     name, sizeof(name)));
02097 }
02098 
02099 /* Converts an ASCII name into a native event code usable by other routines
02100    Returns code = 0 and PAPI_OK if name not found.
02101    This allows for sparse native event arrays */
02102 int
02103 _papi_hwi_native_name_to_code( char *in, int *out )
02104 {
02105     int retval = PAPI_ENOEVNT;
02106     char name[PAPI_HUGE_STR_LEN];      /* make sure it's big enough */
02107     unsigned int i;
02108     int cidx;
02109 
02110     SUBDBG("checking all %d components\n",papi_num_components);
02111     in = _papi_hwi_strip_component_prefix(in);
02112 
02113     
02114     for(cidx=0; cidx < papi_num_components; cidx++) {
02115 
02116        if (_papi_hwd[cidx]->cmp_info.disabled) continue;
02117 
02118        /* first check each component for name_to_code */
02119        retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
02120        *out = _papi_hwi_native_to_eventcode(cidx,*out);
02121 
02122        /* If not implemented, work around */
02123        if ( retval==PAPI_ECMP) {
02124           i = 0;
02125       _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
02126       
02127       //      _papi_hwi_lock( INTERNAL_LOCK );
02128 
02129       do {
02130          retval = _papi_hwd[cidx]->ntv_code_to_name(
02131                       i, 
02132                       name, sizeof(name));
02133              /* printf("%x\nname =|%s|\ninput=|%s|\n", i, name, in); */
02134          if ( retval == PAPI_OK && in != NULL) {
02135         if ( strcasecmp( name, in ) == 0 ) {
02136            *out = _papi_hwi_native_to_eventcode(cidx,i);
02137            break;
02138         } else {
02139            retval = PAPI_ENOEVNT;
02140         }
02141          } else {
02142           *out = 0;
02143           retval = PAPI_ENOEVNT;
02144           break;
02145          }
02146       } while ( ( _papi_hwd[cidx]->ntv_enum_events( &i, 
02147                             PAPI_ENUM_EVENTS ) ==
02148                       PAPI_OK ) );
02149 
02150       //      _papi_hwi_unlock( INTERNAL_LOCK );
02151        }
02152 
02153        if ( retval == PAPI_OK ) return retval;
02154     }
02155 
02156     return retval;
02157 }
02158 
02159 /* Returns event name based on native event code. 
02160    Returns NULL if name not found */
02161 int
02162 _papi_hwi_native_code_to_name( unsigned int EventCode, 
02163                    char *hwi_name, int len )
02164 {
02165   int cidx;
02166   int retval; 
02167 
02168   cidx = _papi_hwi_component_index( EventCode );
02169   if (cidx<0) return PAPI_ENOEVNT;
02170 
02171   if ( EventCode & PAPI_NATIVE_MASK ) {
02172     if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
02173                         _papi_hwi_eventcode_to_native(EventCode), 
02174                         hwi_name, len) ) == PAPI_OK ) {
02175         return 
02176             _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name, 
02177                                              hwi_name, hwi_name, len);
02178     } else {
02179         return (retval);
02180     }
02181   }
02182   return PAPI_ENOEVNT;
02183 }
02184 
02185 
02186 
02187 /* The native event equivalent of PAPI_get_event_info */
02188 int
02189 _papi_hwi_get_native_event_info( unsigned int EventCode,
02190                  PAPI_event_info_t *info )
02191 {
02192     int retval;
02193     int cidx;
02194 
02195     cidx = _papi_hwi_component_index( EventCode );
02196     if (cidx<0) return PAPI_ENOCMP;
02197 
02198     if ( EventCode & PAPI_NATIVE_MASK ) {
02199 
02200        /* clear the event info */
02201        memset( info, 0, sizeof ( PAPI_event_info_t ) );
02202        info->event_code = ( unsigned int ) EventCode;
02203 
02204        retval = _papi_hwd[cidx]->ntv_code_to_info( 
02205                   _papi_hwi_eventcode_to_native(EventCode), info);
02206 
02207        /* If component error, it's missing the ntv_code_to_info vector */
02208        /* so we'll have to fake it.                                    */
02209        if ( retval == PAPI_ECMP ) {
02210 
02211 
02212       SUBDBG("missing NTV_CODE_TO_INFO, faking\n");
02213       /* Fill in the info structure */
02214 
02215       if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
02216                     _papi_hwi_eventcode_to_native(EventCode), 
02217                     info->symbol,
02218                     sizeof(info->symbol)) ) == PAPI_OK ) {
02219 
02220       } else {
02221          SUBDBG("failed ntv_code_to_name\n");
02222          return retval;
02223       }
02224 
02225       retval = _papi_hwd[cidx]->ntv_code_to_descr( 
02226                      _papi_hwi_eventcode_to_native(EventCode), 
02227                                      info->long_descr,
02228                      sizeof ( info->long_descr));
02229       if (retval!=PAPI_OK) {
02230          SUBDBG("Failed ntv_code_to_descr()\n");
02231       }
02232 
02233        }
02234        retval = _papi_hwi_prefix_component_name( 
02235                         _papi_hwd[cidx]->cmp_info.short_name, 
02236                         info->symbol,
02237                         info->symbol, 
02238                         sizeof(info->symbol) );
02239 
02240        return retval;
02241     }
02242 
02243     return PAPI_ENOEVNT;
02244 }
02245 
02246 EventSetInfo_t *
02247 _papi_hwi_lookup_EventSet( int eventset )
02248 {
02249     const DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
02250     EventSetInfo_t *set;
02251 
02252     if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
02253         return ( NULL );
02254 
02255     set = map->dataSlotArray[eventset];
02256 #ifdef DEBUG
02257     if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
02258          ( set->master->tid != _papi_hwi_thread_id_fn(  ) ) )
02259         return ( NULL );
02260 #endif
02261 
02262     return ( set );
02263 }
02264 
02265 int
02266 _papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
02267 {
02268    /* Are we multiplexing at all */
02269    if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
02270       return 0;
02271    }
02272 
02273    /* Does the component support kernel multiplexing */
02274    if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
02275       /* Have we forced software multiplexing */
02276       if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
02277      return 1;
02278       }
02279       /* Nope, using hardware multiplexing */
02280       return 0;
02281    } 
02282 
02283    /* We are multiplexing but the component does not support hardware */
02284 
02285    return 1;
02286 
02287 }
02288 
02289 hwd_context_t *
02290 _papi_hwi_get_context( EventSetInfo_t * ESI, int *is_dirty )
02291 {
02292     INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
02293     int dirty_ctx;
02294     hwd_context_t *ctx=NULL;
02295 
02296     /* assume for now the control state is clean (last updated by this ESI) */
02297     dirty_ctx = 0;
02298     
02299     /* get a context pointer based on if we are counting for a thread or for a cpu */
02300     if (ESI->state & PAPI_CPU_ATTACHED) {
02301         /* use cpu context */
02302         ctx = ESI->CpuInfo->context[ESI->CmpIdx];
02303 
02304         /* if the user wants to know if the control state was last set by the same event set, tell him */
02305         if (is_dirty != NULL) {
02306             if (ESI->CpuInfo->from_esi != ESI) {
02307                 dirty_ctx = 1;
02308             }
02309             *is_dirty = dirty_ctx;
02310         }
02311         ESI->CpuInfo->from_esi = ESI;
02312        
02313     } else {
02314 
02315         /* use thread context */
02316         ctx = ESI->master->context[ESI->CmpIdx];
02317 
02318         /* if the user wants to know if the control state was last set by the same event set, tell him */
02319         if (is_dirty != NULL) {
02320             if (ESI->master->from_esi != ESI) {
02321                 dirty_ctx = 1;
02322             }
02323             *is_dirty = dirty_ctx;
02324         }
02325         ESI->master->from_esi = ESI;
02326 
02327     }
02328     return( ctx );
02329 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines