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