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