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