PAPI  5.1.0.2
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     _papi_hwi_cleanup_eventset( ESI );
00687 
00688 #ifdef DEBUG
00689     memset( ESI, 0x00, sizeof ( EventSetInfo_t ) );
00690 #endif
00691     papi_free( ESI );
00692 
00693 }
00694 
00695 static int
00696 add_EventSet( EventSetInfo_t * ESI, ThreadInfo_t * master )
00697 {
00698     DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
00699     int i, errorCode;
00700 
00701     _papi_hwi_lock( INTERNAL_LOCK );
00702 
00703     if ( map->availSlots == 0 ) {
00704         errorCode = expand_dynamic_array( map );
00705         if ( errorCode < PAPI_OK ) {
00706             _papi_hwi_unlock( INTERNAL_LOCK );
00707             return ( errorCode );
00708         }
00709     }
00710 
00711     i = 0;
00712     for ( i = 0; i < map->totalSlots; i++ ) {
00713         if ( map->dataSlotArray[i] == NULL ) {
00714             ESI->master = master;
00715             ESI->EventSetIndex = i;
00716             map->fullSlots++;
00717             map->availSlots--;
00718             map->dataSlotArray[i] = ESI;
00719             _papi_hwi_unlock( INTERNAL_LOCK );
00720             return ( PAPI_OK );
00721         }
00722     }
00723 
00724     _papi_hwi_unlock( INTERNAL_LOCK );
00725     return ( PAPI_EBUG );
00726 }
00727 
00728 int
00729 _papi_hwi_create_eventset( int *EventSet, ThreadInfo_t * handle )
00730 {
00731     EventSetInfo_t *ESI;
00732     int retval;
00733 
00734     /* Is the EventSet already in existence? */
00735 
00736     if ( ( EventSet == NULL ) || ( handle == NULL ) )
00737         return PAPI_EINVAL;
00738 
00739     if ( *EventSet != PAPI_NULL )
00740         return PAPI_EINVAL;
00741 
00742     /* Well, then allocate a new one. Use n to keep track of a NEW EventSet */
00743 
00744     retval = create_EventSet( &ESI );
00745     if ( retval != PAPI_OK )
00746         return retval;
00747 
00748     ESI->CmpIdx = -1;        /* when eventset is created, it is not decided yet which component it belongs to, until first event is added */
00749     ESI->state = PAPI_STOPPED;
00750 
00751     /* Add it to the global table */
00752 
00753     retval = add_EventSet( ESI, handle );
00754     if ( retval < PAPI_OK ) {
00755         _papi_hwi_free_EventSet( ESI );
00756         return retval ;
00757     }
00758 
00759     *EventSet = ESI->EventSetIndex;
00760 
00761     INTDBG( "(%p,%p): new EventSet in slot %d\n",
00762             ( void * ) EventSet, handle, *EventSet );
00763 
00764     return retval;
00765 }
00766 
00767 /* This function returns the index of the the next free slot
00768    in the EventInfoArray. If EventCode is already in the list,
00769    it returns PAPI_ECNFLCT. */
00770 
00771 static int
00772 get_free_EventCodeIndex( const EventSetInfo_t * ESI, unsigned int EventCode )
00773 {
00774     int k;
00775     int lowslot = PAPI_ECNFLCT;
00776     int limit = EventInfoArrayLength( ESI );
00777 
00778     /* Check for duplicate events and get the lowest empty slot */
00779 
00780     for ( k = 0; k < limit; k++ ) {
00781         if ( ESI->EventInfoArray[k].event_code == EventCode )
00782             return ( PAPI_ECNFLCT );
00783         /*if ((ESI->EventInfoArray[k].event_code == PAPI_NULL) && (lowslot == PAPI_ECNFLCT)) */
00784         if ( ESI->EventInfoArray[k].event_code == ( unsigned int ) PAPI_NULL ) {
00785             lowslot = k;
00786             break;
00787         }
00788     }
00789     return ( lowslot );
00790 }
00791 
00792 /* This function returns the index of the EventCode or error */
00793 /* Index to what? The index to everything stored EventCode in the */
00794 /* EventSet. */
00795 
00796 int
00797 _papi_hwi_lookup_EventCodeIndex( const EventSetInfo_t * ESI,
00798                  unsigned int EventCode )
00799 {
00800     int i;
00801     int limit = EventInfoArrayLength( ESI );
00802 
00803     for ( i = 0; i < limit; i++ ) {
00804        if ( ESI->EventInfoArray[i].event_code == EventCode ) {
00805           return i;
00806        }
00807     }
00808 
00809     return PAPI_EINVAL;
00810 }
00811 
00812 /* This function only removes empty EventSets */
00813 
00814 int
00815 _papi_hwi_remove_EventSet( EventSetInfo_t * ESI )
00816 {
00817     DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
00818     int i;
00819 
00820     i = ESI->EventSetIndex;
00821 
00822     _papi_hwi_lock( INTERNAL_LOCK );
00823 
00824     _papi_hwi_free_EventSet( ESI );
00825 
00826     /* do bookkeeping for PAPI_EVENTSET_MAP */
00827 
00828     map->dataSlotArray[i] = NULL;
00829     map->availSlots++;
00830     map->fullSlots--;
00831 
00832     _papi_hwi_unlock( INTERNAL_LOCK );
00833 
00834     return PAPI_OK;
00835 }
00836 
00837 
00838 /* this function checks if an event is already in an EventSet
00839      Success, return ESI->NativeInfoArray[] index
00840      Fail,    return PAPI_ENOEVNT;
00841 */
00842 static int
00843 event_already_in_eventset( EventSetInfo_t * ESI, int nevt )
00844 {
00845    int i;
00846 
00847    /* to find the native event from the native events list */
00848    for( i = 0; i < ESI->NativeCount; i++ ) {
00849       if ( _papi_hwi_eventcode_to_native(nevt) == 
00850                                         ESI->NativeInfoArray[i].ni_event ) {
00851      INTDBG( "found native event already mapped: 0x%x\n", nevt );
00852      return i;
00853       }
00854    }
00855    return PAPI_ENOEVNT;
00856 }
00857 
00858 /* This function goes through the events in an EventSet's EventInfoArray */
00859 /* And maps each event (whether native or part of a preset) to           */
00860 /* an event in the EventSets NativeInfoArray.                            */
00861 
00862 /* We need to do this every time a native event is added to or removed   */
00863 /* from an eventset.                                                     */
00864 
00865 /* It is also called after a update controlstate as the components are   */
00866 /* allowed to re-arrange the native events to fit hardware constraints.  */
00867 
00868 void
00869 _papi_hwi_map_events_to_native( EventSetInfo_t *ESI)
00870 {
00871 
00872     int i, event, k, n, preset_index = 0, nevt;
00873     int total_events = ESI->NumberOfEvents;
00874 
00875     APIDBG("Mapping %d events in EventSet %d\n",
00876        total_events,ESI->EventSetIndex);
00877    
00878     event = 0;
00879     for( i = 0; i < total_events; i++ ) {
00880 
00881        /* find the first event that isn't PAPI_NULL */
00882        /* Is this really necessary? --vmw           */
00883        while ( ESI->EventInfoArray[event].event_code == ( unsigned int ) PAPI_NULL ) {
00884           event++;
00885        }
00886        
00887        /* If it's a preset */
00888        if ( IS_PRESET(ESI->EventInfoArray[event].event_code) ) {
00889       preset_index = ( int ) ESI->EventInfoArray[event].event_code & PAPI_PRESET_AND_MASK;
00890 
00891       /* walk all sub-events in the preset */
00892       for( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
00893          nevt = _papi_hwi_presets[preset_index].code[k];
00894          if ( nevt == PAPI_NULL ) {
00895         break;
00896          }
00897 
00898          APIDBG("Loking for subevent %x\n",nevt);
00899 
00900          /* Match each sub-event to something in the Native List */
00901          for( n = 0; n < ESI->NativeCount; n++ ) {
00902             if ( _papi_hwi_eventcode_to_native(nevt) == 
00903                                  ESI->NativeInfoArray[n].ni_event ) {
00904            APIDBG("Found event %x at position %d\n",
00905               nevt,
00906               ESI->NativeInfoArray[n].ni_position);
00907            ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
00908            break;
00909         }
00910          }
00911       }
00912        } 
00913        /* It's a native event */
00914        else if( IS_NATIVE(ESI->EventInfoArray[event].event_code) ) {
00915       nevt = ( int ) ESI->EventInfoArray[event].event_code;
00916 
00917       /* Look for the event in the NativeInfoArray */
00918       for( n = 0; n < ESI->NativeCount; n++ ) {
00919          if ( _papi_hwi_eventcode_to_native(nevt) == 
00920                                   ESI->NativeInfoArray[n].ni_event ) {
00921         ESI->EventInfoArray[event].pos[0] = ESI->NativeInfoArray[n].ni_position;
00922         break;
00923          }
00924       }
00925        /* It's a user-defined event */
00926        } else if ( IS_USER_DEFINED(ESI->EventInfoArray[event].event_code) ) {
00927           for ( k = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT; k++ ) {
00928           nevt = _papi_user_events[preset_index].events[k];
00929           if ( nevt == PAPI_NULL ) break;
00930 
00931           /* Match each sub-event to something in the Native List */
00932           for ( n = 0; n < ESI->NativeCount; n++ ) {
00933          if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[n].ni_event ) {
00934             ESI->EventInfoArray[event].pos[k] = ESI->NativeInfoArray[n].ni_position;
00935          }
00936           }
00937       }
00938        }
00939        event++;
00940     }
00941 }
00942 
00943 
00944 static int
00945 add_native_fail_clean( EventSetInfo_t *ESI, int nevt )
00946 {
00947    int i, max_counters;
00948    int cidx;
00949 
00950    cidx = _papi_hwi_component_index( nevt );
00951    if (cidx<0) return PAPI_ENOCMP;
00952 
00953    max_counters = _papi_hwd[cidx]->cmp_info.num_mpx_cntrs;
00954 
00955    /* to find the native event from the native events list */
00956    for( i = 0; i < max_counters; i++ ) {
00957      if ( _papi_hwi_eventcode_to_native(nevt) == ESI->NativeInfoArray[i].ni_event ) {
00958      ESI->NativeInfoArray[i].ni_owners--;
00959      /* to clean the entry in the nativeInfo array */
00960      if ( ESI->NativeInfoArray[i].ni_owners == 0 ) {
00961         ESI->NativeInfoArray[i].ni_event = -1;
00962         ESI->NativeInfoArray[i].ni_position = -1;
00963         ESI->NativeCount--;
00964      }
00965      INTDBG( "add_events fail, and remove added native events "
00966                  "of the event: 0x%x\n", nevt );
00967      return i;
00968       }
00969    }
00970    return -1;
00971 }
00972 
00973 /* since update_control_state trashes overflow settings, this puts things
00974    back into balance. */
00975 static int
00976 update_overflow( EventSetInfo_t * ESI )
00977 {
00978    int i, retval = PAPI_OK;
00979 
00980    if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
00981       for( i = 0; i < ESI->overflow.event_counter; i++ ) {
00982      retval = _papi_hwd[ESI->CmpIdx]->set_overflow( ESI,
00983                             ESI->overflow.EventIndex[i],
00984                             ESI->overflow.threshold[i] );
00985      if ( retval != PAPI_OK ) {
00986         break;
00987      }
00988       }
00989    }
00990    return retval;
00991 }
00992 
00993 /* this function is called by _papi_hwi_add_event when adding native events 
00994    ESI:   event set to add the events to
00995    nevnt: pointer to array of native event table indexes to add
00996    size:  number of native events to add
00997    out:   ???
00998 
00999    return:  < 0 = error
01000               0 = no new events added
01001               1 = new events added
01002 */
01003 static int
01004 add_native_events( EventSetInfo_t *ESI, unsigned int *nevt, 
01005                    int size, EventInfo_t *out )
01006 {
01007    int nidx, i, j, added_events = 0;
01008    int retval, retval2;
01009    int max_counters;
01010    hwd_context_t *context;
01011 
01012    max_counters = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
01013 
01014    /* Walk through the list of native events, adding them */
01015    for( i = 0; i < size; i++ ) {
01016 
01017       /* Check to see if event is already in EventSet */
01018       nidx = event_already_in_eventset( ESI, nevt[i] );
01019 
01020       if ( nidx >= 0 ) {
01021      /* Event is already there.  Set position */
01022      out->pos[i] = ESI->NativeInfoArray[nidx].ni_position;
01023      ESI->NativeInfoArray[nidx].ni_owners++;
01024 
01025       } else {
01026 
01027      /* Event wasn't already there */
01028 
01029      if ( ESI->NativeCount == max_counters ) {
01030 
01031         /* No more room in counters! */
01032         for( j = 0; j < i; j++ ) {
01033            if ( ( nidx = add_native_fail_clean( ESI, nevt[j] ) ) >= 0 ) {
01034           out->pos[j] = -1;
01035           continue;
01036            }
01037            INTDBG( "should not happen!\n" );
01038         }
01039         INTDBG( "counters are full!\n" );
01040         return PAPI_ECOUNT;
01041      }
01042      else {
01043             
01044         /* there is an empty slot for the native event; */
01045         /* initialize the native index for the new added event */
01046         INTDBG( "Adding 0x%x to ESI %p Component %d\n", 
01047             nevt[i], ESI, ESI->CmpIdx );
01048         ESI->NativeInfoArray[ESI->NativeCount].ni_event = 
01049               _papi_hwi_eventcode_to_native(nevt[i]);
01050 
01051         ESI->NativeInfoArray[ESI->NativeCount].ni_owners = 1;
01052         ESI->NativeCount++;
01053         added_events++;
01054      }
01055       }
01056    }
01057 
01058    /* if we added events we need to tell the component so it */
01059    /* can add them too.                                      */
01060    if ( added_events ) {
01061       /* get the context we should use for this event set */
01062       context = _papi_hwi_get_context( ESI, NULL );
01063        
01064       if ( _papi_hwd[ESI->CmpIdx]->allocate_registers( ESI ) == PAPI_OK ) {
01065 
01066      retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01067           ESI->NativeInfoArray,
01068           ESI->NativeCount,
01069           context);
01070      if ( retval != PAPI_OK ) {
01071 clean:
01072         for( i = 0; i < size; i++ ) {
01073            if ( ( nidx = add_native_fail_clean( ESI, nevt[i] ) ) >= 0 ) {
01074           out->pos[i] = -1;
01075           continue;
01076            }
01077            INTDBG( "should not happen!\n" );
01078         }
01079         /* re-establish the control state after the previous error */
01080         retval2 = _papi_hwd[ESI->CmpIdx]->update_control_state( 
01081                        ESI->ctl_state,
01082                ESI->NativeInfoArray,
01083                ESI->NativeCount,
01084                context);
01085         if ( retval2 != PAPI_OK ) {
01086            PAPIERROR("update_control_state failed to re-establish "
01087              "working events!" );
01088            return retval2;
01089         }
01090         return retval;
01091      }
01092      return 1; /* need remap */
01093       } else {
01094      retval = PAPI_EMISC;
01095      goto clean;
01096       }
01097    }
01098    return PAPI_OK;
01099 }
01100 
01101 
01102 int
01103 _papi_hwi_add_event( EventSetInfo_t * ESI, int EventCode )
01104 {
01105     int i, j, thisindex, remap, retval = PAPI_OK;
01106     int cidx;
01107 
01108     cidx=_papi_hwi_component_index( EventCode );
01109     if (cidx<0) return PAPI_ENOCMP;
01110 
01111     /* Sanity check that the new EventCode is from the same component */
01112     /* as previous events.                                            */
01113     
01114     if ( ESI->CmpIdx < 0 ) {
01115        if ( ( retval = _papi_hwi_assign_eventset( ESI, cidx) != PAPI_OK )) {
01116           return retval;
01117        }
01118     } else {
01119        if ( ESI->CmpIdx != cidx ) {
01120       return PAPI_EINVAL;
01121        }
01122     }
01123 
01124     /* Make sure the event is not present and get the next free slot. */
01125     thisindex = get_free_EventCodeIndex( ESI, ( unsigned int ) EventCode );
01126     if ( thisindex < PAPI_OK ) {
01127        return thisindex;
01128     }
01129 
01130     APIDBG("Adding event to slot %d of EventSet %d\n",thisindex,ESI->EventSetIndex);
01131 
01132     /* If it is a software MPX EventSet, add it to the multiplex data structure */
01133     /* and this thread's multiplex list                                         */
01134 
01135     if ( !_papi_hwi_is_sw_multiplex( ESI ) ) {
01136 
01137        /* Handle preset case */
01138        if ( IS_PRESET(EventCode) ) {
01139       int count;
01140       int preset_index = EventCode & ( int ) PAPI_PRESET_AND_MASK;
01141 
01142       /* Check if it's within the valid range */
01143       if ( ( preset_index < 0 ) || ( preset_index >= PAPI_MAX_PRESET_EVENTS ) ) {
01144          return PAPI_EINVAL;
01145       }
01146 
01147       /* count the number of native events in this preset */
01148       count = ( int ) _papi_hwi_presets[preset_index].count;
01149 
01150       /* Check if event exists */
01151       if ( !count ) {
01152          return PAPI_ENOEVNT;
01153       }
01154             
01155       /* check if the native events have been used as overflow events */
01156       /* this is not allowed                                          */
01157       if ( ESI->state & PAPI_OVERFLOWING ) {
01158          for( i = 0; i < count; i++ ) {
01159         for( j = 0; j < ESI->overflow.event_counter; j++ ) {
01160           if ( ESI->overflow.EventCode[j] ==(int)
01161             ( _papi_hwi_presets[preset_index].code[i] ) ) {
01162               return PAPI_ECNFLCT;
01163            }
01164         }
01165          }
01166       }
01167 
01168       /* Try to add the preset. */
01169 
01170       remap = add_native_events( ESI,
01171                      _papi_hwi_presets[preset_index].code,
01172                      count, &ESI->EventInfoArray[thisindex] );
01173       if ( remap < 0 ) {
01174          return remap;
01175       }
01176           else {
01177          /* Fill in the EventCode (machine independent) information */
01178          ESI->EventInfoArray[thisindex].event_code = 
01179                                   ( unsigned int ) EventCode;
01180          ESI->EventInfoArray[thisindex].derived =
01181                   _papi_hwi_presets[preset_index].derived_int;
01182          ESI->EventInfoArray[thisindex].ops =
01183                   _papi_hwi_presets[preset_index].postfix;
01184              ESI->NumberOfEvents++;
01185          _papi_hwi_map_events_to_native( ESI );
01186          
01187       }
01188        }
01189        /* Handle adding Native events */
01190        else if ( IS_NATIVE(EventCode) ) {
01191 
01192       /* Check if native event exists */
01193       if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) != PAPI_OK ) {
01194          return PAPI_ENOEVNT;
01195       }
01196             
01197       /* check if the native events have been used as overflow events */
01198       /* This is not allowed                                          */
01199       if ( ESI->state & PAPI_OVERFLOWING ) {
01200          for( j = 0; j < ESI->overflow.event_counter; j++ ) {
01201             if ( EventCode == ESI->overflow.EventCode[j] ) {
01202            return PAPI_ECNFLCT;
01203         }
01204          }
01205       }
01206 
01207       /* Try to add the native event. */
01208 
01209       remap = add_native_events( ESI, (unsigned int *)&EventCode, 1,
01210                      &ESI->EventInfoArray[thisindex] );
01211 
01212       if ( remap < 0 ) {
01213          return remap;
01214       } else {
01215 
01216          /* Fill in the EventCode (machine independent) information */
01217          ESI->EventInfoArray[thisindex].event_code = 
01218                                        ( unsigned int ) EventCode;
01219              ESI->NumberOfEvents++;
01220          _papi_hwi_map_events_to_native( ESI );
01221          
01222       }
01223        } else if ( IS_USER_DEFINED( EventCode ) ) {
01224          int count;
01225          int index = EventCode & PAPI_UE_AND_MASK;
01226 
01227          if ( index < 0 || index >= (int)_papi_user_events_count )
01228            return ( PAPI_EINVAL );
01229 
01230          count = ( int ) _papi_user_events[index].count;
01231 
01232          for ( i = 0; i < count; i++ ) {
01233            for ( j = 0; j < ESI->overflow.event_counter; j++ ) {
01234              if ( ESI->overflow.EventCode[j] ==
01235                  _papi_user_events[index].events[i] ) {
01236                return ( PAPI_EBUG );
01237              }
01238            }
01239          }
01240 
01241          remap = add_native_events( ESI,
01242              (unsigned int*)_papi_user_events[index].events,
01243              count, &ESI->EventInfoArray[thisindex] );
01244 
01245          if ( remap < 0 ) {
01246            return remap;
01247          } else {
01248            ESI->EventInfoArray[thisindex].event_code       
01249                                          = (unsigned int) EventCode;
01250            ESI->EventInfoArray[thisindex].derived          
01251                                          = DERIVED_POSTFIX;
01252            ESI->EventInfoArray[thisindex].ops                      
01253                                          = _papi_user_events[index].operation;
01254                    ESI->NumberOfEvents++;
01255            _papi_hwi_map_events_to_native( ESI );
01256          }
01257        } else {
01258 
01259       /* not Native, Preset, or User events */
01260 
01261       return PAPI_EBUG;
01262        }
01263     }
01264     else {
01265         
01266        /* Multiplexing is special. See multiplex.c */
01267 
01268        retval = mpx_add_event( &ESI->multiplex.mpx_evset, EventCode,
01269                    ESI->domain.domain, 
01270                    ESI->granularity.granularity );
01271 
01272 
01273        if ( retval < PAPI_OK ) {
01274       return retval;
01275        }
01276 
01277        /* Relevant (???) */
01278        ESI->EventInfoArray[thisindex].event_code = ( unsigned int ) EventCode;  
01279        ESI->EventInfoArray[thisindex].derived = NOT_DERIVED;
01280 
01281        ESI->NumberOfEvents++;
01282 
01283        /* event is in the EventInfoArray but not mapped to the NativeEvents */
01284        /* this causes issues if you try to set overflow on the event.       */
01285        /* in theory this wouldn't matter anyway.                            */
01286     }
01287 
01288     /* reinstate the overflows if any */
01289     retval=update_overflow( ESI );
01290 
01291     return retval;
01292 }
01293 
01294 static int
01295 remove_native_events( EventSetInfo_t *ESI, int *nevt, int size )
01296 {
01297    NativeInfo_t *native = ESI->NativeInfoArray;
01298    hwd_context_t *context;
01299    int i, j, zero = 0, retval;
01300 
01301    /* Remove the references to this event from the native events:
01302       for all the metrics in this event,
01303       compare to each native event in this event set,
01304       and decrement owners if they match  */
01305    for( i = 0; i < size; i++ ) {
01306       for( j = 0; j < ESI->NativeCount; j++ ) {
01307      if ( native[j].ni_event ==  _papi_hwi_eventcode_to_native(nevt[i]) ) {
01308         native[j].ni_owners--;
01309         if ( native[j].ni_owners == 0 ) {
01310            zero++;
01311         }
01312         break;
01313      }
01314       }
01315    }
01316 
01317    /* Remove any native events from the array if owners dropped to zero.
01318       The NativeInfoArray must be dense, with no empty slots, so if we
01319       remove an element, we must compact the list */
01320    for( i = 0; i < ESI->NativeCount; i++ ) {
01321 
01322       if ( native[i].ni_event == -1 ) continue;
01323 
01324       if ( native[i].ni_owners == 0 ) {
01325      int copy = 0;
01326      int sz = _papi_hwd[ESI->CmpIdx]->size.reg_value;
01327      for( j = ESI->NativeCount - 1; j > i; j-- ) {
01328         if ( native[j].ni_event == -1 || native[j].ni_owners == 0 ) continue;
01329         else {
01330            /* copy j into i */
01331            native[i].ni_event = native[j].ni_event;
01332            native[i].ni_position = native[j].ni_position;
01333            native[i].ni_owners = native[j].ni_owners;
01334            /* copy opaque [j].ni_bits to [i].ni_bits */
01335            memcpy( native[i].ni_bits, native[j].ni_bits, ( size_t ) sz );
01336            /* reset j to initialized state */
01337            native[j].ni_event = -1;
01338            native[j].ni_position = -1;
01339            native[j].ni_owners = 0;
01340            copy++;
01341            break;
01342         }
01343      }
01344 
01345      if ( copy == 0 ) {
01346         /* set this structure back to empty state */
01347         /* ni_owners is already 0 and contents of ni_bits doesn't matter */
01348         native[i].ni_event = -1;
01349         native[i].ni_position = -1;
01350      }
01351       }
01352    }
01353 
01354    /* to reset hwd_control_state values */
01355    ESI->NativeCount -= zero;
01356 
01357    /* If we removed any elements, 
01358       clear the now empty slots, reinitialize the index, and update the count.
01359       Then send the info down to the component to update the hwd control structure. */
01360     retval = PAPI_OK;
01361     if ( zero ) {
01362       /* get the context we should use for this event set */
01363       context = _papi_hwi_get_context( ESI, NULL );
01364         retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01365                                                           native, ESI->NativeCount, context);
01366         if ( retval == PAPI_OK )
01367             retval = update_overflow( ESI );
01368     }
01369     return ( retval );
01370 }
01371 
01372 int
01373 _papi_hwi_remove_event( EventSetInfo_t * ESI, int EventCode )
01374 {
01375     int j = 0, retval, thisindex;
01376     EventInfo_t *array;
01377 
01378     thisindex =
01379         _papi_hwi_lookup_EventCodeIndex( ESI, ( unsigned int ) EventCode );
01380     if ( thisindex < PAPI_OK )
01381         return ( thisindex );
01382 
01383     /* If it is a MPX EventSet, remove it from the multiplex data structure and
01384        this threads multiplex list */
01385 
01386     if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
01387         retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
01388         if ( retval < PAPI_OK )
01389             return ( retval );
01390     } else
01391         /* Remove the events hardware dependent stuff from the EventSet */
01392     {
01393         if ( IS_PRESET(EventCode) ) {
01394             int preset_index = EventCode & PAPI_PRESET_AND_MASK;
01395 
01396             /* Check if it's within the valid range */
01397             if ( ( preset_index < 0 ) ||
01398                  ( preset_index >= PAPI_MAX_PRESET_EVENTS ) )
01399                 return PAPI_EINVAL;
01400 
01401             /* Check if event exists */
01402             if ( !_papi_hwi_presets[preset_index].count )
01403                 return PAPI_ENOEVNT;
01404 
01405             /* Remove the preset event. */
01406             for ( j = 0; _papi_hwi_presets[preset_index].code[j] != (unsigned int)PAPI_NULL;
01407                   j++ );
01408             retval = remove_native_events( ESI,
01409                                (int *)_papi_hwi_presets[preset_index].code, j );
01410             if ( retval != PAPI_OK )
01411                 return ( retval );
01412         } else if ( IS_NATIVE(EventCode) ) {
01413             /* Check if native event exists */
01414             if ( _papi_hwi_query_native_event( ( unsigned int ) EventCode ) !=
01415                  PAPI_OK )
01416                 return PAPI_ENOEVNT;
01417 
01418             /* Remove the native event. */
01419             retval = remove_native_events( ESI, &EventCode, 1 );
01420             if ( retval != PAPI_OK )
01421                 return ( retval );
01422         } else if ( IS_USER_DEFINED( EventCode ) ) {
01423           int index = EventCode & PAPI_UE_AND_MASK;
01424 
01425           if ( (index < 0) || (index >= (int)_papi_user_events_count) )
01426             return ( PAPI_EINVAL );
01427 
01428           for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT &&
01429               _papi_user_events[index].events[j] != 0; j++ ) {
01430             retval = remove_native_events( ESI,
01431                 _papi_user_events[index].events, j);
01432 
01433             if ( retval != PAPI_OK )
01434               return ( retval );
01435           }
01436         } else
01437             return ( PAPI_ENOEVNT );
01438     }
01439     array = ESI->EventInfoArray;
01440 
01441     /* Compact the Event Info Array list if it's not the last event */
01442     /* clear the newly empty slot in the array */
01443     for ( ; thisindex < ESI->NumberOfEvents - 1; thisindex++ )
01444         array[thisindex] = array[thisindex + 1];
01445 
01446 
01447     array[thisindex].event_code = ( unsigned int ) PAPI_NULL;
01448     for ( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ )
01449         array[thisindex].pos[j] = PAPI_NULL;
01450     array[thisindex].ops = NULL;
01451     array[thisindex].derived = NOT_DERIVED;
01452     ESI->NumberOfEvents--;
01453 
01454     return ( PAPI_OK );
01455 }
01456 
01457 int
01458 _papi_hwi_read( hwd_context_t * context, EventSetInfo_t * ESI,
01459                 long long *values )
01460 {
01461     int retval;
01462     long long *dp = NULL;
01463     int i, index;
01464 
01465     retval = _papi_hwd[ESI->CmpIdx]->read( context, ESI->ctl_state, 
01466                            &dp, ESI->state );
01467     if ( retval != PAPI_OK ) {
01468        return retval;
01469     }
01470 
01471     /* This routine distributes hardware counters to software counters in the
01472        order that they were added. Note that the higher level
01473        EventInfoArray[i] entries may not be contiguous because the user
01474        has the right to remove an event.
01475        But if we do compaction after remove event, this function can be 
01476        changed.  
01477      */
01478 
01479     for ( i = 0; i != ESI->NumberOfEvents; i++ ) {
01480 
01481         index = ESI->EventInfoArray[i].pos[0];
01482 
01483         if ( index == -1 )
01484             continue;
01485 
01486         INTDBG( "Event index %d, position is 0x%x\n", i, index );
01487 
01488         /* If this is not a derived event */
01489 
01490         if ( ESI->EventInfoArray[i].derived == NOT_DERIVED ) {
01491             values[i] = dp[index];
01492             INTDBG( "value: 0x%llx\n", values[i] );
01493         } else {             /* If this is a derived event */
01494             values[i] = handle_derived( &ESI->EventInfoArray[i], dp );
01495 #ifdef DEBUG
01496             if ( values[i] < ( long long ) 0 ) {
01497                 INTDBG( "Derived Event is negative!!: %lld\n", values[i] );
01498             }
01499             INTDBG( "derived value: 0x%llx \n", values[i] );
01500 #endif
01501         }
01502     }
01503 
01504     return PAPI_OK;
01505 }
01506 
01507 int
01508 _papi_hwi_cleanup_eventset( EventSetInfo_t * ESI )
01509 {
01510    int i, j, num_cntrs, retval;
01511    hwd_context_t *context;
01512    int EventCode;
01513    NativeInfo_t *native;
01514    if ( !_papi_hwi_invalid_cmp( ESI->CmpIdx ) ) {
01515    num_cntrs = _papi_hwd[ESI->CmpIdx]->cmp_info.num_mpx_cntrs;
01516 
01517    for(i=0;i<num_cntrs;i++) {
01518 
01519       EventCode=ESI->EventInfoArray[i].event_code;     
01520 
01521       /* skip if event not there */
01522       if ( EventCode == PAPI_NULL ) continue;
01523 
01524       /* If it is a MPX EventSet, remove it from the multiplex */
01525       /* data structure and this thread's multiplex list */
01526 
01527       if ( _papi_hwi_is_sw_multiplex( ESI ) ) {
01528      retval = mpx_remove_event( &ESI->multiplex.mpx_evset, EventCode );
01529      if ( retval < PAPI_OK )
01530         return retval;
01531       } else {
01532 
01533       native = ESI->NativeInfoArray;
01534 
01535       /* clear out ESI->NativeInfoArray */
01536       /* do we really need to do this, seeing as we free() it later? */
01537 
01538       for( j = 0; j < ESI->NativeCount; j++ ) {
01539          native[j].ni_event = -1;
01540          native[j].ni_position = -1;
01541          native[j].ni_owners = 0;
01542          /* native[j].ni_bits?? */
01543       }
01544       }
01545 
01546       /* do we really need to do this, seeing as we free() it later? */
01547       ESI->EventInfoArray[i].event_code= ( unsigned int ) PAPI_NULL;
01548       for( j = 0; j < PAPI_EVENTS_IN_DERIVED_EVENT; j++ ) {
01549       ESI->EventInfoArray[i].pos[j] = PAPI_NULL;
01550       }
01551       ESI->EventInfoArray[i].ops = NULL;
01552       ESI->EventInfoArray[i].derived = NOT_DERIVED;
01553    }
01554 
01555    context = _papi_hwi_get_context( ESI, NULL );
01556    /* calling with count of 0 equals a close? */
01557    retval = _papi_hwd[ESI->CmpIdx]->update_control_state( ESI->ctl_state,
01558                    NULL, 0, context);
01559    if (retval!=PAPI_OK) {
01560      return retval;
01561    }
01562    }
01563 
01564    ESI->CmpIdx = -1;
01565    ESI->NumberOfEvents = 0;
01566    ESI->NativeCount = 0;
01567 
01568    if ( ( ESI->state & PAPI_MULTIPLEXING ) && ESI->multiplex.mpx_evset )
01569            papi_free( ESI->multiplex.mpx_evset );
01570 
01571    if ( ( ESI->state & PAPI_CPU_ATTACH ) && ESI->CpuInfo )
01572            _papi_hwi_shutdown_cpu( ESI->CpuInfo );
01573 
01574    if ( ESI->ctl_state )
01575       papi_free( ESI->ctl_state );
01576 
01577    if ( ESI->sw_stop )
01578       papi_free( ESI->sw_stop );
01579 
01580    if ( ESI->hw_start )
01581       papi_free( ESI->hw_start );
01582     
01583    if ( ESI->EventInfoArray )
01584       papi_free( ESI->EventInfoArray );
01585     
01586    if ( ESI->NativeInfoArray ) 
01587       papi_free( ESI->NativeInfoArray );
01588 
01589    if ( ESI->NativeBits ) 
01590       papi_free( ESI->NativeBits );
01591     
01592    if ( ESI->overflow.deadline )
01593       papi_free( ESI->overflow.deadline );
01594     
01595    if ( ESI->profile.prof )
01596       papi_free( ESI->profile.prof );
01597 
01598    ESI->ctl_state = NULL;
01599    ESI->sw_stop = NULL;
01600    ESI->hw_start = NULL;
01601    ESI->EventInfoArray = NULL;
01602    ESI->NativeInfoArray = NULL;
01603    ESI->NativeBits = NULL;
01604 
01605    memset( &ESI->domain, 0x0, sizeof(EventSetDomainInfo_t) );
01606    memset( &ESI->granularity, 0x0, sizeof(EventSetGranularityInfo_t) );
01607    memset( &ESI->overflow, 0x0, sizeof(EventSetOverflowInfo_t) );
01608    memset( &ESI->multiplex, 0x0, sizeof(EventSetMultiplexInfo_t) );
01609    memset( &ESI->attach, 0x0, sizeof(EventSetAttachInfo_t) );
01610    memset( &ESI->cpu, 0x0, sizeof(EventSetCpuInfo_t) );
01611    memset( &ESI->profile, 0x0, sizeof(EventSetProfileInfo_t) );
01612    memset( &ESI->inherit, 0x0, sizeof(EventSetInheritInfo_t) );
01613 
01614    ESI->CpuInfo = NULL;
01615 
01616    return PAPI_OK;
01617 }
01618 
01619 int
01620 _papi_hwi_convert_eventset_to_multiplex( _papi_int_multiplex_t * mpx )
01621 {
01622     int retval, i, j = 0, *mpxlist = NULL;
01623     EventSetInfo_t *ESI = mpx->ESI;
01624     int flags = mpx->flags;
01625 
01626     /* If there are any events in the EventSet, 
01627        convert them to multiplex events */
01628 
01629     if ( ESI->NumberOfEvents ) {
01630 
01631         mpxlist =
01632             ( int * ) papi_malloc( sizeof ( int ) *
01633                                    ( size_t ) ESI->NumberOfEvents );
01634         if ( mpxlist == NULL )
01635             return ( PAPI_ENOMEM );
01636 
01637         /* Build the args to MPX_add_events(). */
01638 
01639         /* Remember the EventInfoArray can be sparse
01640            and the data can be non-contiguous */
01641 
01642         for ( i = 0; i < EventInfoArrayLength( ESI ); i++ )
01643             if ( ESI->EventInfoArray[i].event_code !=
01644                  ( unsigned int ) PAPI_NULL )
01645                 mpxlist[j++] = ( int ) ESI->EventInfoArray[i].event_code;
01646 
01647         /* Resize the EventInfo_t array */
01648 
01649         if ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex == 0 ) ||
01650              ( ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) &&
01651                ( flags & PAPI_MULTIPLEX_FORCE_SW ) ) ) {
01652             retval =
01653                 MPX_add_events( &ESI->multiplex.mpx_evset, mpxlist, j,
01654                                 ESI->domain.domain,
01655                                 ESI->granularity.granularity );
01656             if ( retval != PAPI_OK ) {
01657                 papi_free( mpxlist );
01658                 return ( retval );
01659             }
01660         }
01661 
01662         papi_free( mpxlist );
01663     }
01664 
01665     /* Update the state before initialization! */
01666 
01667     ESI->state |= PAPI_MULTIPLEXING;
01668     if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex &&
01669          ( flags & PAPI_MULTIPLEX_FORCE_SW ) )
01670         ESI->multiplex.flags = PAPI_MULTIPLEX_FORCE_SW;
01671     ESI->multiplex.ns = ( int ) mpx->ns;
01672 
01673     return ( PAPI_OK );
01674 }
01675 
01676 #include "components_config.h"
01677 
01678 int papi_num_components = ( sizeof ( _papi_hwd ) / sizeof ( *_papi_hwd ) ) - 1;
01679 
01680 /*
01681  * Routine that initializes all available components.
01682  * A component is available if a pointer to its info vector
01683  * appears in the NULL terminated_papi_hwd table.
01684  */
01685 int
01686 _papi_hwi_init_global( void )
01687 {
01688         int retval, i = 0;
01689 
01690     retval = _papi_hwi_innoculate_os_vector( &_papi_os_vector );
01691     if ( retval != PAPI_OK ) {
01692        return retval;
01693     }
01694 
01695     while ( _papi_hwd[i] ) {
01696 
01697        retval = _papi_hwi_innoculate_vector( _papi_hwd[i] );
01698        if ( retval != PAPI_OK ) {
01699           return retval;
01700        }
01701 
01702        /* We can be disabled by user before init */
01703        if (!_papi_hwd[i]->cmp_info.disabled) {
01704           retval = _papi_hwd[i]->init_component( i );
01705           _papi_hwd[i]->cmp_info.disabled=retval;
01706 
01707           /* Do some sanity checking */
01708           if (retval==PAPI_OK) {
01709         if (_papi_hwd[i]->cmp_info.num_cntrs >
01710             _papi_hwd[i]->cmp_info.num_mpx_cntrs) {
01711           fprintf(stderr,"Warning!  num_cntrs is more than num_mpx_cntrs\n");
01712         }
01713 
01714           }
01715        }
01716 
01717        i++;
01718     }
01719     return PAPI_OK;
01720 }
01721 
01722 /* Machine info struct initialization using defaults */
01723 /* See _papi_mdi definition in papi_internal.h       */
01724 
01725 int
01726 _papi_hwi_init_global_internal( void )
01727 {
01728 
01729     int retval;
01730 
01731     memset(&_papi_hwi_system_info,0x0,sizeof( _papi_hwi_system_info ));
01732 
01733     memset( _papi_hwi_using_signal,0x0,sizeof( _papi_hwi_using_signal ));
01734 
01735     /* Global struct to maintain EventSet mapping */
01736     retval = allocate_eventset_map( &_papi_hwi_system_info.global_eventset_map );
01737     if ( retval != PAPI_OK ) {
01738         return retval;
01739     }
01740 
01741     _papi_hwi_system_info.pid = 0;  /* Process identifier */
01742 
01743     /* PAPI_hw_info_t struct */
01744     memset(&(_papi_hwi_system_info.hw_info),0x0,sizeof(PAPI_hw_info_t));
01745 
01746     return PAPI_OK;
01747 }
01748 
01749 void
01750 _papi_hwi_shutdown_global_internal( void )
01751 {
01752     _papi_hwi_cleanup_all_presets(  );
01753 
01754     _papi_hwi_cleanup_errors( );
01755 
01756     _papi_hwi_lock( INTERNAL_LOCK );
01757 
01758     papi_free(  _papi_hwi_system_info.global_eventset_map.dataSlotArray );
01759     memset(  &_papi_hwi_system_info.global_eventset_map, 
01760          0x00, sizeof ( DynamicArray_t ) );
01761 
01762     _papi_hwi_unlock( INTERNAL_LOCK );
01763 
01764     if ( _papi_hwi_system_info.shlib_info.map ) {
01765         papi_free( _papi_hwi_system_info.shlib_info.map );
01766     }
01767     memset( &_papi_hwi_system_info, 0x0, sizeof ( _papi_hwi_system_info ) );
01768 
01769 }
01770 
01771 
01772 
01773 void
01774 _papi_hwi_dummy_handler( int EventSet, void *address, long long overflow_vector,
01775                          void *context )
01776 {
01777     /* This function is not used and shouldn't be called. */
01778     ( void ) EventSet;       /*unused */
01779     ( void ) address;        /*unused */
01780     ( void ) overflow_vector;   /*unused */
01781     ( void ) context;        /*unused */
01782     return;
01783 }
01784 
01785 static long long
01786 handle_derived_add( int *position, long long *from )
01787 {
01788     int pos, i;
01789     long long retval = 0;
01790 
01791     i = 0;
01792     while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
01793         pos = position[i++];
01794         if ( pos == PAPI_NULL )
01795             break;
01796         INTDBG( "Compound event, adding %lld to %lld\n", from[pos], retval );
01797         retval += from[pos];
01798     }
01799     return ( retval );
01800 }
01801 
01802 static long long
01803 handle_derived_subtract( int *position, long long *from )
01804 {
01805     int pos, i;
01806     long long retval = from[position[0]];
01807 
01808     i = 1;
01809     while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
01810         pos = position[i++];
01811         if ( pos == PAPI_NULL )
01812             break;
01813         INTDBG( "Compound event, subtracting pos=%d  %lld from %lld\n", pos,
01814                 from[pos], retval );
01815         retval -= from[pos];
01816     }
01817     return ( retval );
01818 }
01819 
01820 static long long
01821 units_per_second( long long units, long long cycles )
01822 {
01823    return ( ( units * (long long) _papi_hwi_system_info.hw_info.cpu_max_mhz *
01824               (long long) 1000000 ) / cycles );
01825 }
01826 
01827 static long long
01828 handle_derived_ps( int *position, long long *from )
01829 {
01830     return ( units_per_second( from[position[1]], from[position[0]] ) );
01831 }
01832 static long long
01833 handle_derived_add_ps( int *position, long long *from )
01834 {
01835     long long tmp = handle_derived_add( position + 1, from );
01836     return ( units_per_second( tmp, from[position[0]] ) );
01837 }
01838 
01839 /* this function implement postfix calculation, it reads in a string where I use:
01840       |      as delimiter
01841       N2     indicate No. 2 native event in the derived preset
01842       +, -, *, /, %  as operator
01843       #      as MHZ(million hz) got from  _papi_hwi_system_info.hw_info.cpu_max_mhz*1000000.0
01844 
01845   Haihang (you@cs.utk.edu)
01846 */ 
01847 static long long
01848 _papi_hwi_postfix_calc( EventInfo_t * evi, long long *hw_counter )
01849 {
01850     char *point = evi->ops, operand[16];
01851     double stack[PAPI_EVENTS_IN_DERIVED_EVENT];
01852     int i, top = 0;
01853 
01854     memset(&stack,0,PAPI_EVENTS_IN_DERIVED_EVENT*sizeof(double));
01855 
01856     while ( *point != '\0' ) {
01857         if ( *point == 'N' ) {  /* to get count for each native event */
01858             i = 0;
01859             point++;
01860             do {
01861                 operand[i] = *point;
01862                 point++;
01863                 i++;
01864             } while ( *point != '|' );
01865             operand[i] = '\0';
01866             stack[top] = ( double ) hw_counter[evi->pos[atoi( operand )]];
01867             top++;
01868             point++;
01869         } else if ( *point == '#' ) {   /* to get mhz, ignore the rest char's */
01870             stack[top] = _papi_hwi_system_info.hw_info.cpu_max_mhz * 1000000.0;
01871             top++;
01872             do {
01873                 point++;
01874             } while ( *point != '|' );
01875             point++;
01876         } else if ( isdigit( *point ) ) {   /* to get integer, I suppose only integer will be used, 
01877                                                no error check here, please only use integer */
01878             i = 0;
01879             do {
01880                 operand[i] = *point;
01881                 point++;
01882                 i++;
01883             } while ( *point != '|' );
01884             operand[i] = '\0';
01885             stack[top] = atoi( operand );
01886             top++;
01887             point++;
01888         } else if ( *point == '+' ) {   /* + calculation */
01889             stack[top - 2] += stack[top - 1];
01890             top--;
01891             do {
01892                 point++;
01893             } while ( *point != '|' );
01894             point++;
01895         } else if ( *point == '-' ) {   /* - calculation */
01896             stack[top - 2] -= stack[top - 1];
01897             top--;
01898             do {
01899                 point++;
01900             } while ( *point != '|' );
01901             point++;
01902         } else if ( *point == '*' ) {   /* * calculation */
01903             stack[top - 2] *= stack[top - 1];
01904             top--;
01905             do {
01906                 point++;
01907             } while ( *point != '|' );
01908             point++;
01909         } else if ( *point == '/' ) {   /* / calculation */
01910             stack[top - 2] /= stack[top - 1];
01911             top--;
01912             do {
01913                 point++;
01914             } while ( *point != '|' );
01915             point++;
01916         } else {             /* do nothing */
01917             do {
01918                 point++;
01919             } while ( *point != '|' );
01920             point++;
01921         }
01922     }
01923     return ( long long ) stack[0];
01924 }
01925 
01926 static long long
01927 handle_derived( EventInfo_t * evi, long long *from )
01928 {
01929     switch ( evi->derived ) {
01930     case DERIVED_ADD:
01931         return ( handle_derived_add( evi->pos, from ) );
01932     case DERIVED_ADD_PS:
01933         return ( handle_derived_add_ps( evi->pos, from ) );
01934     case DERIVED_SUB:
01935         return ( handle_derived_subtract( evi->pos, from ) );
01936     case DERIVED_PS:
01937         return ( handle_derived_ps( evi->pos, from ) );
01938     case DERIVED_POSTFIX:
01939         return ( _papi_hwi_postfix_calc( evi, from ) );
01940     case DERIVED_CMPD:       /* This type has existed for a long time, but was never implemented.
01941                                 Probably because its a no-op. However, if it's in a header, it
01942                                 should be supported. As I found out when I implemented it in 
01943                                 Pentium 4 for testing...dkt */
01944         return ( from[evi->pos[0]] );
01945     default:
01946         PAPIERROR( "BUG! Unknown derived command %d, returning 0",
01947                    evi->derived );
01948         return ( ( long long ) 0 );
01949     }
01950 }
01951 
01952 
01953 /* table matching derived types to derived strings.                             
01954    used by get_info, encode_event, xml translator                               
01955 */
01956 static const hwi_describe_t _papi_hwi_derived[] = {
01957   {NOT_DERIVED, "NOT_DERIVED", "Do nothing"},
01958   {DERIVED_ADD, "DERIVED_ADD", "Add counters"},
01959   {DERIVED_PS, "DERIVED_PS",
01960    "Divide by the cycle counter and convert to seconds"},
01961   {DERIVED_ADD_PS, "DERIVED_ADD_PS",
01962    "Add 2 counters then divide by the cycle counter and xl8 to secs."},
01963   {DERIVED_CMPD, "DERIVED_CMPD",
01964    "Event lives in first counter but takes 2 or more codes"},
01965   {DERIVED_SUB, "DERIVED_SUB", "Sub all counters from first counter"},
01966   {DERIVED_POSTFIX, "DERIVED_POSTFIX",
01967    "Process counters based on specified postfix string"},
01968   {-1, NULL, NULL}
01969 };
01970 
01971 /* _papi_hwi_derived_type:
01972    Helper routine to extract a derived type from a derived string
01973    returns type value if found, otherwise returns -1
01974 */
01975 int
01976 _papi_hwi_derived_type( char *tmp, int *code )
01977 {
01978   int i = 0;
01979   while ( _papi_hwi_derived[i].name != NULL ) {
01980     if ( strcasecmp( tmp, _papi_hwi_derived[i].name ) == 0 ) {
01981       *code = _papi_hwi_derived[i].value;
01982       return PAPI_OK;
01983     }
01984     i++;
01985   }
01986   INTDBG( "Invalid derived string %s\n", tmp );
01987   return PAPI_EINVAL;
01988 }
01989 
01990 
01991 /* _papi_hwi_derived_string:
01992    Helper routine to extract a derived string from a derived type  
01993    copies derived type string into derived if found,
01994    otherwise returns PAPI_EINVAL
01995 */
01996 static int
01997 _papi_hwi_derived_string( int type, char *derived, int len )
01998 {
01999   int j;
02000 
02001   for ( j = 0; _papi_hwi_derived[j].value != -1; j++ ) {
02002     if ( _papi_hwi_derived[j].value == type ) {
02003       strncpy( derived, _papi_hwi_derived[j].name, ( size_t )\
02004            len );
02005       return PAPI_OK;
02006     }
02007   }
02008   INTDBG( "Invalid derived type %d\n", type );
02009   return PAPI_EINVAL;
02010 }
02011 
02012 
02013 /* _papi_hwi_get_preset_event_info:
02014    Assumes EventCode contains a valid preset code.
02015    But defensive programming says check for NULL pointers.
02016    Returns a filled in PAPI_event_info_t structure containing
02017    descriptive strings and values for the specified preset event.
02018 */
02019 int
02020 _papi_hwi_get_preset_event_info( int EventCode, PAPI_event_info_t * info )
02021 {
02022     int i = EventCode & PAPI_PRESET_AND_MASK;
02023     unsigned int j;
02024 
02025     if ( _papi_hwi_presets[i].symbol ) {    /* if the event is in the preset table */
02026        /* set whole structure to 0 */
02027        memset( info, 0, sizeof ( PAPI_event_info_t ) );
02028 
02029        info->event_code = ( unsigned int ) EventCode;
02030        strncpy( info->symbol, _papi_hwi_presets[i].symbol,
02031             sizeof(info->symbol));
02032 
02033        if ( _papi_hwi_presets[i].short_descr != NULL )
02034           strncpy( info->short_descr, _papi_hwi_presets[i].short_descr,
02035                           sizeof ( info->short_descr ) );
02036 
02037        if ( _papi_hwi_presets[i].long_descr != NULL )
02038           strncpy( info->long_descr,  _papi_hwi_presets[i].long_descr,
02039                           sizeof ( info->long_descr ) );
02040 
02041        info->event_type = _papi_hwi_presets[i].event_type;
02042        info->count = _papi_hwi_presets[i].count;
02043 
02044        _papi_hwi_derived_string( _papi_hwi_presets[i].derived_int,
02045                      info->derived,  sizeof ( info->derived ) );
02046 
02047        if ( _papi_hwi_presets[i].postfix != NULL )
02048           strncpy( info->postfix, _papi_hwi_presets[i].postfix,
02049                           sizeof ( info->postfix ) );
02050 
02051        for(j=0;j < info->count; j++) {
02052           info->code[j]=_papi_hwi_presets[i].code[j];
02053           strncpy(info->name[j], _papi_hwi_presets[i].name[j],
02054               sizeof(info->name[j]));
02055        }
02056 
02057        if ( _papi_hwi_presets[i].note != NULL ) {
02058           strncpy( info->note, _papi_hwi_presets[i].note,
02059                           sizeof ( info->note ) );
02060        }
02061 
02062        return PAPI_OK;
02063     } else {
02064        return PAPI_ENOEVNT;
02065     }
02066 }
02067 
02068 
02069 /* Returns PAPI_OK if native EventCode found, or PAPI_ENOEVNT if not;
02070    Used to enumerate the entire array, e.g. for native_avail.c */
02071 int
02072 _papi_hwi_query_native_event( unsigned int EventCode )
02073 {
02074    char name[PAPI_HUGE_STR_LEN];      /* probably overkill, */
02075                                       /* but should always be big enough */
02076    int cidx;
02077 
02078    cidx = _papi_hwi_component_index( EventCode );
02079    if (cidx<0) return PAPI_ENOCMP;
02080 
02081    return ( _papi_hwd[cidx]->ntv_code_to_name( 
02082                     _papi_hwi_eventcode_to_native(EventCode), 
02083                     name, sizeof(name)));
02084 }
02085 
02086 /* Converts an ASCII name into a native event code usable by other routines
02087    Returns code = 0 and PAPI_OK if name not found.
02088    This allows for sparse native event arrays */
02089 int
02090 _papi_hwi_native_name_to_code( char *in, int *out )
02091 {
02092     int retval = PAPI_ENOEVNT;
02093     char name[PAPI_HUGE_STR_LEN];      /* make sure it's big enough */
02094     unsigned int i;
02095     int cidx;
02096 
02097     SUBDBG("checking all %d components\n",papi_num_components);
02098     in = _papi_hwi_strip_component_prefix(in);
02099 
02100     
02101     for(cidx=0; cidx < papi_num_components; cidx++) {
02102 
02103        if (_papi_hwd[cidx]->cmp_info.disabled) continue;
02104 
02105        /* first check each component for name_to_code */
02106        retval = _papi_hwd[cidx]->ntv_name_to_code( in, ( unsigned * ) out );
02107        *out = _papi_hwi_native_to_eventcode(cidx,*out);
02108 
02109        /* If not implemented, work around */
02110        if ( retval==PAPI_ECMP) {
02111           i = 0;
02112       _papi_hwd[cidx]->ntv_enum_events( &i, PAPI_ENUM_FIRST );
02113       
02114       //      _papi_hwi_lock( INTERNAL_LOCK );
02115 
02116       do {
02117          retval = _papi_hwd[cidx]->ntv_code_to_name(
02118                       i, 
02119                       name, sizeof(name));
02120              /* printf("%x\nname =|%s|\ninput=|%s|\n", i, name, in); */
02121          if ( retval == PAPI_OK && in != NULL) {
02122         if ( strcasecmp( name, in ) == 0 ) {
02123            *out = _papi_hwi_native_to_eventcode(cidx,i);
02124            break;
02125         } else {
02126            retval = PAPI_ENOEVNT;
02127         }
02128          } else {
02129           *out = 0;
02130           retval = PAPI_ENOEVNT;
02131           break;
02132          }
02133       } while ( ( _papi_hwd[cidx]->ntv_enum_events( &i, 
02134                             PAPI_ENUM_EVENTS ) ==
02135                       PAPI_OK ) );
02136 
02137       //      _papi_hwi_unlock( INTERNAL_LOCK );
02138        }
02139 
02140        if ( retval == PAPI_OK ) return retval;
02141     }
02142 
02143     return retval;
02144 }
02145 
02146 /* Returns event name based on native event code. 
02147    Returns NULL if name not found */
02148 int
02149 _papi_hwi_native_code_to_name( unsigned int EventCode, 
02150                    char *hwi_name, int len )
02151 {
02152   int cidx;
02153   int retval; 
02154 
02155   cidx = _papi_hwi_component_index( EventCode );
02156   if (cidx<0) return PAPI_ENOEVNT;
02157 
02158   if ( EventCode & PAPI_NATIVE_MASK ) {
02159     if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
02160                         _papi_hwi_eventcode_to_native(EventCode), 
02161                         hwi_name, len) ) == PAPI_OK ) {
02162         return 
02163             _papi_hwi_prefix_component_name( _papi_hwd[cidx]->cmp_info.short_name, 
02164                                              hwi_name, hwi_name, len);
02165     } else {
02166         return (retval);
02167     }
02168   }
02169   return PAPI_ENOEVNT;
02170 }
02171 
02172 
02173 
02174 /* The native event equivalent of PAPI_get_event_info */
02175 int
02176 _papi_hwi_get_native_event_info( unsigned int EventCode,
02177                  PAPI_event_info_t *info )
02178 {
02179     int retval;
02180     int cidx;
02181 
02182     cidx = _papi_hwi_component_index( EventCode );
02183     if (cidx<0) return PAPI_ENOCMP;
02184 
02185     if ( EventCode & PAPI_NATIVE_MASK ) {
02186 
02187        /* clear the event info */
02188        memset( info, 0, sizeof ( PAPI_event_info_t ) );
02189        info->event_code = ( unsigned int ) EventCode;
02190 
02191        retval = _papi_hwd[cidx]->ntv_code_to_info( 
02192                   _papi_hwi_eventcode_to_native(EventCode), info);
02193 
02194        /* If component error, it's missing the ntv_code_to_info vector */
02195        /* so we'll have to fake it.                                    */
02196        if ( retval == PAPI_ECMP ) {
02197 
02198 
02199       SUBDBG("missing NTV_CODE_TO_INFO, faking\n");
02200       /* Fill in the info structure */
02201 
02202       if ( (retval = _papi_hwd[cidx]->ntv_code_to_name( 
02203                     _papi_hwi_eventcode_to_native(EventCode), 
02204                     info->symbol,
02205                     sizeof(info->symbol)) ) == PAPI_OK ) {
02206 
02207       } else {
02208          SUBDBG("failed ntv_code_to_name\n");
02209          return retval;
02210       }
02211 
02212       retval = _papi_hwd[cidx]->ntv_code_to_descr( 
02213                      _papi_hwi_eventcode_to_native(EventCode), 
02214                                      info->long_descr,
02215                      sizeof ( info->long_descr));
02216       if (retval!=PAPI_OK) {
02217          SUBDBG("Failed ntv_code_to_descr()\n");
02218       }
02219 
02220        }
02221        retval = _papi_hwi_prefix_component_name( 
02222                         _papi_hwd[cidx]->cmp_info.short_name, 
02223                         info->symbol,
02224                         info->symbol, 
02225                         sizeof(info->symbol) );
02226 
02227        return retval;
02228     }
02229 
02230     return PAPI_ENOEVNT;
02231 }
02232 
02233 EventSetInfo_t *
02234 _papi_hwi_lookup_EventSet( int eventset )
02235 {
02236     const DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map;
02237     EventSetInfo_t *set;
02238 
02239     if ( ( eventset < 0 ) || ( eventset > map->totalSlots ) )
02240         return ( NULL );
02241 
02242     set = map->dataSlotArray[eventset];
02243 #ifdef DEBUG
02244     if ( ( ISLEVEL( DEBUG_THREADS ) ) && ( _papi_hwi_thread_id_fn ) &&
02245          ( set->master->tid != _papi_hwi_thread_id_fn(  ) ) )
02246         return ( NULL );
02247 #endif
02248 
02249     return ( set );
02250 }
02251 
02252 int
02253 _papi_hwi_is_sw_multiplex(EventSetInfo_t *ESI)
02254 {
02255    /* Are we multiplexing at all */
02256    if ( ( ESI->state & PAPI_MULTIPLEXING ) == 0 ) {
02257       return 0;
02258    }
02259 
02260    /* Does the component support kernel multiplexing */
02261    if ( _papi_hwd[ESI->CmpIdx]->cmp_info.kernel_multiplex ) {
02262       /* Have we forced software multiplexing */
02263       if ( ESI->multiplex.flags == PAPI_MULTIPLEX_FORCE_SW ) {
02264      return 1;
02265       }
02266       /* Nope, using hardware multiplexing */
02267       return 0;
02268    } 
02269 
02270    /* We are multiplexing but the component does not support hardware */
02271 
02272    return 1;
02273 
02274 }
02275 
02276 hwd_context_t *
02277 _papi_hwi_get_context( EventSetInfo_t * ESI, int *is_dirty )
02278 {
02279     INTDBG("Entry: ESI: %p, is_dirty: %p\n", ESI, is_dirty);
02280     int dirty_ctx;
02281     hwd_context_t *ctx=NULL;
02282 
02283     /* assume for now the control state is clean (last updated by this ESI) */
02284     dirty_ctx = 0;
02285     
02286     /* get a context pointer based on if we are counting for a thread or for a cpu */
02287     if (ESI->state & PAPI_CPU_ATTACHED) {
02288         /* use cpu context */
02289         ctx = ESI->CpuInfo->context[ESI->CmpIdx];
02290 
02291         /* if the user wants to know if the control state was last set by the same event set, tell him */
02292         if (is_dirty != NULL) {
02293             if (ESI->CpuInfo->from_esi != ESI) {
02294                 dirty_ctx = 1;
02295             }
02296             *is_dirty = dirty_ctx;
02297         }
02298         ESI->CpuInfo->from_esi = ESI;
02299        
02300     } else {
02301 
02302         /* use thread context */
02303         ctx = ESI->master->context[ESI->CmpIdx];
02304 
02305         /* if the user wants to know if the control state was last set by the same event set, tell him */
02306         if (is_dirty != NULL) {
02307             if (ESI->master->from_esi != ESI) {
02308                 dirty_ctx = 1;
02309             }
02310             *is_dirty = dirty_ctx;
02311         }
02312         ESI->master->from_esi = ESI;
02313 
02314     }
02315     return( ctx );
02316 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines