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