|
PAPI
5.3.0.0
|
00001 /****************************/ 00002 /* THIS IS OPEN SOURCE CODE */ 00003 /****************************/ 00004 00024 #include <stdio.h> 00025 #include <string.h> 00026 #include <stdlib.h> 00027 #include <unistd.h> 00028 00029 #include "papi.h" 00030 #include "papi_internal.h" 00031 #include "papi_vector.h" 00032 #include "papi_memory.h" 00033 00034 #include "papi_user_events.h" 00035 00036 #include "cpus.h" 00037 #include "extras.h" 00038 #include "sw_multiplex.h" 00039 #include "papi_hl.h" 00040 00041 /*******************************/ 00042 /* BEGIN EXTERNAL DECLARATIONS */ 00043 /*******************************/ 00044 00045 00046 #ifdef DEBUG 00047 #define papi_return(a) do { \ 00048 int b = a; \ 00049 if (b != PAPI_OK) {\ 00050 _papi_hwi_errno = b;\ 00051 } \ 00052 return((_papi_hwi_debug_handler ? _papi_hwi_debug_handler(b) : b)); \ 00053 } while (0) 00054 #else 00055 #define papi_return(a) do { \ 00056 int b = a; \ 00057 if (b != PAPI_OK) {\ 00058 _papi_hwi_errno = b;\ 00059 } \ 00060 return(b);\ 00061 } while(0) 00062 #endif 00063 00064 00065 /* 00066 #ifdef DEBUG 00067 #define papi_return(a) return((_papi_hwi_debug_handler ? _papi_hwi_debug_handler(a) : a)) 00068 #else 00069 #define papi_return(a) return(a) 00070 #endif 00071 */ 00072 00073 #ifdef DEBUG 00074 int _papi_hwi_debug; 00075 #endif 00076 00077 00078 static int init_retval = DEADBEEF; 00079 00080 inline_static int 00081 valid_component( int cidx ) 00082 { 00083 if ( _papi_hwi_invalid_cmp( cidx ) ) 00084 return ( PAPI_ENOCMP ); 00085 return ( cidx ); 00086 } 00087 00088 inline_static int 00089 valid_ESI_component( EventSetInfo_t * ESI ) 00090 { 00091 return ( valid_component( ESI->CmpIdx ) ); 00092 } 00093 00117 int 00118 PAPI_thread_init( unsigned long int ( *id_fn ) ( void ) ) 00119 { 00120 /* Thread support not implemented on Alpha/OSF because the OSF pfm 00121 * counter device driver does not support per-thread counters. 00122 * When this is updated, we can remove this if statement 00123 */ 00124 if ( init_level == PAPI_NOT_INITED ) 00125 papi_return( PAPI_ENOINIT ); 00126 00127 if ( ( init_level & PAPI_THREAD_LEVEL_INITED ) ) 00128 papi_return( PAPI_OK ); 00129 00130 init_level |= PAPI_THREAD_LEVEL_INITED; 00131 papi_return( _papi_hwi_set_thread_id_fn( id_fn ) ); 00132 } 00133 00156 unsigned long 00157 PAPI_thread_id( void ) 00158 { 00159 if ( _papi_hwi_thread_id_fn != NULL ) 00160 return ( ( *_papi_hwi_thread_id_fn ) ( ) ); 00161 else 00162 #ifdef DEBUG 00163 if ( _papi_hwi_debug_handler ) 00164 return ( unsigned long ) _papi_hwi_debug_handler( PAPI_EMISC ); 00165 #endif 00166 return ( unsigned long ) PAPI_EMISC; 00167 } 00168 00169 /* Thread Functions */ 00170 00171 /* 00172 * Notify PAPI that a thread has 'appeared' 00173 * We lookup the thread, if it does not exist we create it 00174 */ 00175 00202 int 00203 PAPI_register_thread( void ) 00204 { 00205 ThreadInfo_t *thread; 00206 00207 if ( init_level == PAPI_NOT_INITED ) 00208 papi_return( PAPI_ENOINIT ); 00209 papi_return( _papi_hwi_lookup_or_create_thread( &thread, 0 ) ); 00210 } 00211 00212 /* 00213 * Notify PAPI that a thread has 'disappeared' 00214 * We lookup the thread, if it does not exist we return an error 00215 */ 00238 int 00239 PAPI_unregister_thread( void ) 00240 { 00241 ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 ); 00242 00243 if ( thread ) 00244 papi_return( _papi_hwi_shutdown_thread( thread, 0 ) ); 00245 00246 papi_return( PAPI_EMISC ); 00247 } 00248 00280 int 00281 PAPI_list_threads( PAPI_thread_id_t *tids, int *number ) 00282 { 00283 PAPI_all_thr_spec_t tmp; 00284 int retval; 00285 00286 /* If tids == NULL, then just count the threads, don't gather a list. */ 00287 /* If tids != NULL, then we need the length of the tids array in num. */ 00288 00289 if ( ( number == NULL ) || ( tids && ( *number <= 0 ) ) ) 00290 papi_return( PAPI_EINVAL ); 00291 00292 memset( &tmp, 0x0, sizeof ( tmp ) ); 00293 00294 /* data == NULL, since we don't want the thread specific pointers. */ 00295 /* tids may be NULL, if the user doesn't want the thread IDs. */ 00296 00297 tmp.num = *number; 00298 tmp.id = tids; 00299 tmp.data = NULL; 00300 00301 retval = _papi_hwi_gather_all_thrspec_data( 0, &tmp ); 00302 if ( retval == PAPI_OK ) 00303 *number = tmp.num; 00304 00305 papi_return( retval ); 00306 } 00307 00356 int 00357 PAPI_get_thr_specific( int tag, void **ptr ) 00358 { 00359 ThreadInfo_t *thread; 00360 int doall = 0, retval = PAPI_OK; 00361 00362 if ( init_level == PAPI_NOT_INITED ) 00363 papi_return( PAPI_ENOINIT ); 00364 if ( tag & PAPI_TLS_ALL_THREADS ) { 00365 tag = tag ^ PAPI_TLS_ALL_THREADS; 00366 doall = 1; 00367 } 00368 if ( ( tag < 0 ) || ( tag > PAPI_TLS_NUM ) ) 00369 papi_return( PAPI_EINVAL ); 00370 00371 if ( doall ) 00372 papi_return( _papi_hwi_gather_all_thrspec_data 00373 ( tag, ( PAPI_all_thr_spec_t * ) ptr ) ); 00374 00375 retval = _papi_hwi_lookup_or_create_thread( &thread, 0 ); 00376 if ( retval == PAPI_OK ) 00377 *ptr = thread->thread_storage[tag]; 00378 else 00379 papi_return( retval ); 00380 00381 return ( PAPI_OK ); 00382 } 00383 00432 int 00433 PAPI_set_thr_specific( int tag, void *ptr ) 00434 { 00435 ThreadInfo_t *thread; 00436 int retval = PAPI_OK; 00437 00438 if ( init_level == PAPI_NOT_INITED ) 00439 papi_return( PAPI_ENOINIT ); 00440 if ( ( tag < 0 ) || ( tag > PAPI_NUM_TLS ) ) 00441 papi_return( PAPI_EINVAL ); 00442 00443 retval = _papi_hwi_lookup_or_create_thread( &thread, 0 ); 00444 if ( retval == PAPI_OK ) { 00445 _papi_hwi_lock( THREADS_LOCK ); 00446 thread->thread_storage[tag] = ptr; 00447 _papi_hwi_unlock( THREADS_LOCK ); 00448 } 00449 else 00450 return ( retval ); 00451 00452 return ( PAPI_OK ); 00453 } 00454 00455 00494 int 00495 PAPI_library_init( int version ) 00496 { 00497 char *filename; 00498 int tmp = 0, tmpel; 00499 00500 /* This is a poor attempt at a lock. 00501 For 3.1 this should be replaced with a 00502 true UNIX semaphore. We cannot use PAPI 00503 locks here because they are not initialized yet */ 00504 static int _in_papi_library_init_cnt = 0; 00505 #ifdef DEBUG 00506 char *var; 00507 #endif 00508 _papi_hwi_init_errors(); 00509 00510 if ( version != PAPI_VER_CURRENT ) 00511 papi_return( PAPI_EINVAL ); 00512 00513 ++_in_papi_library_init_cnt; 00514 while ( _in_papi_library_init_cnt > 1 ) { 00515 PAPIERROR( "Multiple callers of PAPI_library_init" ); 00516 sleep( 1 ); 00517 } 00518 00519 /* This checks to see if we have forked or called init more than once. 00520 If we have forked, then we continue to init. If we have not forked, 00521 we check to see the status of initialization. */ 00522 00523 APIDBG( "Initializing library: current PID %d, old PID %d\n", 00524 getpid( ), _papi_hwi_system_info.pid ); 00525 00526 if ( _papi_hwi_system_info.pid == getpid( ) ) { 00527 /* If the magic environment variable PAPI_ALLOW_STOLEN is set, 00528 we call shutdown if PAPI has been initialized. This allows 00529 tools that use LD_PRELOAD to run on applications that use PAPI. 00530 In this circumstance, PAPI_ALLOW_STOLEN will be set to 'stolen' 00531 so the tool can check for this case. */ 00532 00533 if ( getenv( "PAPI_ALLOW_STOLEN" ) ) { 00534 char buf[PAPI_HUGE_STR_LEN]; 00535 if ( init_level != PAPI_NOT_INITED ) 00536 PAPI_shutdown( ); 00537 sprintf( buf, "%s=%s", "PAPI_ALLOW_STOLEN", "stolen" ); 00538 putenv( buf ); 00539 } 00540 00541 /* If the library has been successfully initialized *OR* 00542 the library attempted initialization but failed. */ 00543 00544 else if ( ( init_level != PAPI_NOT_INITED ) || 00545 ( init_retval != DEADBEEF ) ) { 00546 _in_papi_library_init_cnt--; 00547 if ( init_retval < PAPI_OK ) 00548 papi_return( init_retval ); 00549 else 00550 return ( init_retval ); 00551 } 00552 00553 APIDBG( "system_info was initialized, but init did not succeed\n" ); 00554 } 00555 #ifdef DEBUG 00556 var = ( char * ) getenv( "PAPI_DEBUG" ); 00557 _papi_hwi_debug = 0; 00558 00559 if ( var != NULL ) { 00560 if ( strlen( var ) != 0 ) { 00561 if ( strstr( var, "SUBSTRATE" ) ) 00562 _papi_hwi_debug |= DEBUG_SUBSTRATE; 00563 if ( strstr( var, "API" ) ) 00564 _papi_hwi_debug |= DEBUG_API; 00565 if ( strstr( var, "INTERNAL" ) ) 00566 _papi_hwi_debug |= DEBUG_INTERNAL; 00567 if ( strstr( var, "THREADS" ) ) 00568 _papi_hwi_debug |= DEBUG_THREADS; 00569 if ( strstr( var, "MULTIPLEX" ) ) 00570 _papi_hwi_debug |= DEBUG_MULTIPLEX; 00571 if ( strstr( var, "OVERFLOW" ) ) 00572 _papi_hwi_debug |= DEBUG_OVERFLOW; 00573 if ( strstr( var, "PROFILE" ) ) 00574 _papi_hwi_debug |= DEBUG_PROFILE; 00575 if ( strstr( var, "MEMORY" ) ) 00576 _papi_hwi_debug |= DEBUG_MEMORY; 00577 if ( strstr( var, "LEAK" ) ) 00578 _papi_hwi_debug |= DEBUG_LEAK; 00579 if ( strstr( var, "ALL" ) ) 00580 _papi_hwi_debug |= DEBUG_ALL; 00581 } 00582 00583 if ( _papi_hwi_debug == 0 ) 00584 _papi_hwi_debug |= DEBUG_API; 00585 } 00586 #endif 00587 00588 /* Be verbose for now */ 00589 00590 tmpel = _papi_hwi_error_level; 00591 _papi_hwi_error_level = PAPI_VERB_ECONT; 00592 00593 /* Initialize internal globals */ 00594 if ( _papi_hwi_init_global_internal( ) != PAPI_OK ) { 00595 _in_papi_library_init_cnt--; 00596 _papi_hwi_error_level = tmpel; 00597 papi_return( PAPI_EINVAL ); 00598 } 00599 00600 /* Initialize OS */ 00601 tmp = _papi_hwi_init_os(); 00602 if ( tmp ) { 00603 init_retval = tmp; 00604 _papi_hwi_shutdown_global_internal( ); 00605 _in_papi_library_init_cnt--; 00606 _papi_hwi_error_level = tmpel; 00607 papi_return( init_retval ); 00608 } 00609 00610 /* Initialize component globals */ 00611 00612 tmp = _papi_hwi_init_global( ); 00613 if ( tmp ) { 00614 init_retval = tmp; 00615 _papi_hwi_shutdown_global_internal( ); 00616 _in_papi_library_init_cnt--; 00617 _papi_hwi_error_level = tmpel; 00618 papi_return( init_retval ); 00619 } 00620 00621 /* Initialize thread globals, including the main threads */ 00622 00623 tmp = _papi_hwi_init_global_threads( ); 00624 if ( tmp ) { 00625 int i; 00626 init_retval = tmp; 00627 _papi_hwi_shutdown_global_internal( ); 00628 for ( i = 0; i < papi_num_components; i++ ) { 00629 if (!_papi_hwd[i]->cmp_info.disabled) { 00630 _papi_hwd[i]->shutdown_component( ); 00631 } 00632 } 00633 _in_papi_library_init_cnt--; 00634 _papi_hwi_error_level = tmpel; 00635 papi_return( init_retval ); 00636 } 00637 00638 init_level = PAPI_LOW_LEVEL_INITED; 00639 _in_papi_library_init_cnt--; 00640 _papi_hwi_error_level = tmpel; 00641 00642 #ifdef STATIC_USER_EVENTS 00643 _papi_user_defined_events_setup(NULL); 00644 #endif 00645 00646 if ( (filename = getenv( "PAPI_USER_EVENTS_FILE" )) != NULL ) { 00647 _papi_user_defined_events_setup(filename); 00648 } 00649 00650 return ( init_retval = PAPI_VER_CURRENT ); 00651 } 00652 00694 int 00695 PAPI_query_event( int EventCode ) 00696 { 00697 if ( IS_PRESET(EventCode) ) { 00698 EventCode &= PAPI_PRESET_AND_MASK; 00699 if ( EventCode >= PAPI_MAX_PRESET_EVENTS ) 00700 papi_return( PAPI_ENOTPRESET ); 00701 00702 if ( _papi_hwi_presets[EventCode].count ) 00703 papi_return (PAPI_OK); 00704 else 00705 return PAPI_ENOEVNT; 00706 } 00707 00708 if ( IS_NATIVE(EventCode) ) { 00709 papi_return( _papi_hwi_query_native_event 00710 ( ( unsigned int ) EventCode ) ); 00711 } 00712 00713 if ( IS_USER_DEFINED(EventCode) ) { 00714 EventCode &= PAPI_UE_AND_MASK; 00715 if ( EventCode < 0 || EventCode > (int)_papi_user_events_count) 00716 return ( PAPI_EINVAL ); 00717 00718 papi_return( PAPI_OK ); 00719 } 00720 00721 papi_return( PAPI_ENOEVNT ); 00722 } 00723 00762 int 00763 PAPI_query_named_event( char *EventName ) 00764 { 00765 int ret, code; 00766 00767 ret = PAPI_event_name_to_code( EventName, &code ); 00768 if ( ret == PAPI_OK ) ret = PAPI_query_event( code ); 00769 papi_return( ret); 00770 } 00771 00772 00802 const PAPI_component_info_t * 00803 PAPI_get_component_info( int cidx ) 00804 { 00805 if ( _papi_hwi_invalid_cmp( cidx ) ) 00806 return ( NULL ); 00807 else 00808 return ( &( _papi_hwd[cidx]->cmp_info ) ); 00809 } 00810 00811 /* PAPI_get_event_info: 00812 tests input EventCode and returns a filled in PAPI_event_info_t 00813 structure containing descriptive strings and values for the 00814 specified event. Handles both preset and native events by 00815 calling either _papi_hwi_get_event_info or 00816 _papi_hwi_get_native_event_info. 00817 */ 00840 int 00841 PAPI_get_event_info( int EventCode, PAPI_event_info_t *info ) 00842 { 00843 int i; 00844 00845 if ( info == NULL ) 00846 papi_return( PAPI_EINVAL ); 00847 00848 if ( IS_PRESET(EventCode) ) { 00849 i = EventCode & PAPI_PRESET_AND_MASK; 00850 if ( i >= PAPI_MAX_PRESET_EVENTS ) 00851 papi_return( PAPI_ENOTPRESET ); 00852 papi_return( _papi_hwi_get_preset_event_info( EventCode, info ) ); 00853 } 00854 00855 if ( IS_NATIVE(EventCode) ) { 00856 papi_return( _papi_hwi_get_native_event_info 00857 ( ( unsigned int ) EventCode, info ) ); 00858 } 00859 00860 if ( IS_USER_DEFINED(EventCode) ) { 00861 papi_return( PAPI_OK ); 00862 } 00863 papi_return( PAPI_ENOTPRESET ); 00864 } 00865 00866 00919 int 00920 PAPI_event_code_to_name( int EventCode, char *out ) 00921 { 00922 if ( out == NULL ) 00923 papi_return( PAPI_EINVAL ); 00924 00925 if ( IS_PRESET(EventCode) ) { 00926 EventCode &= PAPI_PRESET_AND_MASK; 00927 if ( ( EventCode >= PAPI_MAX_PRESET_EVENTS ) 00928 || ( _papi_hwi_presets[EventCode].symbol == NULL ) ) 00929 papi_return( PAPI_ENOTPRESET ); 00930 00931 strncpy( out, _papi_hwi_presets[EventCode].symbol, 00932 PAPI_MAX_STR_LEN ); 00933 papi_return( PAPI_OK ); 00934 } 00935 00936 if ( IS_NATIVE(EventCode) ) { 00937 return ( _papi_hwi_native_code_to_name 00938 ( ( unsigned int ) EventCode, out, PAPI_MAX_STR_LEN ) ); 00939 } 00940 00941 if ( IS_USER_DEFINED(EventCode) ) { 00942 EventCode &= PAPI_UE_AND_MASK; 00943 00944 if ( EventCode < 0 || EventCode > (int)_papi_user_events_count ) 00945 papi_return( PAPI_EINVAL ); 00946 00947 strncpy( out, _papi_user_events[EventCode].symbol, 00948 PAPI_MIN_STR_LEN); 00949 papi_return( PAPI_OK ); 00950 } 00951 00952 papi_return( PAPI_ENOEVNT ); 00953 } 00954 01002 int 01003 PAPI_event_name_to_code( char *in, int *out ) 01004 { 01005 APIDBG("Entry: in: %p, name: %s, out: %p\n", in, in, out); 01006 int i; 01007 01008 if ( ( in == NULL ) || ( out == NULL ) ) 01009 papi_return( PAPI_EINVAL ); 01010 01011 if ( init_level == PAPI_NOT_INITED ) 01012 papi_return( PAPI_ENOINIT ); 01013 01014 /* All presets start with "PAPI_" so no need to */ 01015 /* do an exhaustive search if that's not there */ 01016 if (strncmp(in, "PAPI_", 5) == 0) { 01017 for(i = 0; i < PAPI_MAX_PRESET_EVENTS; i++ ) { 01018 if ( ( _papi_hwi_presets[i].symbol ) 01019 && ( strcasecmp( _papi_hwi_presets[i].symbol, in ) == 0) ) { 01020 *out = ( int ) ( i | PAPI_PRESET_MASK ); 01021 papi_return( PAPI_OK ); 01022 } 01023 } 01024 } 01025 01026 for ( i=0; i < (int)_papi_user_events_count; i++ ) { 01027 if ( strcasecmp( _papi_user_events[i].symbol, in ) == 0 ) { 01028 *out = (int) ( i | PAPI_UE_MASK ); 01029 papi_return( PAPI_OK ); 01030 } 01031 } 01032 01033 papi_return( _papi_hwi_native_name_to_code( in, out ) ); 01034 } 01035 01036 /* Updates EventCode to next valid value, or returns error; 01037 modifier can specify {all / available} for presets, or other values for native tables 01038 and may be platform specific (Major groups / all mask bits; P / M / E chip, etc) */ 01039 01142 int 01143 PAPI_enum_event( int *EventCode, int modifier ) 01144 { 01145 int i = *EventCode; 01146 int retval; 01147 int cidx; 01148 int event_code; 01149 01150 cidx = _papi_hwi_component_index( *EventCode ); 01151 if (cidx < 0) return PAPI_ENOCMP; 01152 01153 /* Do we handle presets in componets other than CPU? */ 01154 /* if (( IS_PRESET(i) ) && cidx > 0 )) return PAPI_ENOCMP; */ 01155 01156 if ( IS_PRESET(i) ) { 01157 if ( modifier == PAPI_ENUM_FIRST ) { 01158 *EventCode = ( int ) PAPI_PRESET_MASK; 01159 return ( PAPI_OK ); 01160 } 01161 i &= PAPI_PRESET_AND_MASK; 01162 while ( ++i < PAPI_MAX_PRESET_EVENTS ) { 01163 if ( _papi_hwi_presets[i].symbol == NULL ) 01164 return ( PAPI_ENOEVNT ); /* NULL pointer terminates list */ 01165 if ( modifier & PAPI_PRESET_ENUM_AVAIL ) { 01166 if ( _papi_hwi_presets[i].count == 0 ) 01167 continue; 01168 } 01169 *EventCode = ( int ) ( i | PAPI_PRESET_MASK ); 01170 return ( PAPI_OK ); 01171 } 01172 } else if ( IS_NATIVE(i) ) { 01173 /* Should check against num native events here */ 01174 01175 event_code=_papi_hwi_eventcode_to_native((int)*EventCode); 01176 retval = _papi_hwd[cidx]->ntv_enum_events((unsigned int *)&event_code, modifier ); 01177 01178 /* re-apply Component ID to the returned Event */ 01179 *EventCode = _papi_hwi_native_to_eventcode(cidx,event_code); 01180 01181 return retval; 01182 } else if ( IS_USER_DEFINED(i) ) { 01183 if ( modifier == PAPI_ENUM_FIRST ) { 01184 *EventCode = (int) 0x0; 01185 return ( PAPI_OK ); 01186 } 01187 01188 i &= PAPI_UE_AND_MASK; 01189 ++i; 01190 01191 if ( (int)_papi_user_events_count <= i ) 01192 *EventCode = i; 01193 return ( PAPI_OK ); 01194 } 01195 01196 papi_return( PAPI_EINVAL ); 01197 } 01198 01199 01304 int 01305 PAPI_enum_cmp_event( int *EventCode, int modifier, int cidx ) 01306 { 01307 int i = *EventCode; 01308 int retval; 01309 int event_code; 01310 01311 if ( _papi_hwi_invalid_cmp(cidx) || ( (IS_PRESET(i)) && cidx > 0 ) ) { 01312 return PAPI_ENOCMP; 01313 } 01314 01315 if (_papi_hwd[cidx]->cmp_info.disabled) { 01316 return PAPI_ENOCMP; 01317 } 01318 01319 if ( IS_PRESET(i) ) { 01320 if ( modifier == PAPI_ENUM_FIRST ) { 01321 *EventCode = ( int ) PAPI_PRESET_MASK; 01322 return PAPI_OK; 01323 } 01324 i &= PAPI_PRESET_AND_MASK; 01325 while ( ++i < PAPI_MAX_PRESET_EVENTS ) { 01326 if ( _papi_hwi_presets[i].symbol == NULL ) 01327 return ( PAPI_ENOEVNT ); /* NULL pointer terminates list */ 01328 if ( modifier & PAPI_PRESET_ENUM_AVAIL ) { 01329 if ( _papi_hwi_presets[i].count == 0 ) 01330 continue; 01331 } 01332 *EventCode = ( int ) ( i | PAPI_PRESET_MASK ); 01333 return PAPI_OK; 01334 } 01335 } else if ( IS_NATIVE(i) ) { 01336 01337 /* Should we check against num native events here? */ 01338 event_code=_papi_hwi_eventcode_to_native(*EventCode); 01339 retval = _papi_hwd[cidx]->ntv_enum_events((unsigned int *)&event_code, modifier ); 01340 01341 if (retval!=PAPI_OK) { 01342 SUBDBG("VMW: retval=%d\n",retval); 01343 return PAPI_EINVAL; 01344 } 01345 01346 /* re-apply Component ID to the returned Event */ 01347 *EventCode = _papi_hwi_native_to_eventcode(cidx,event_code); 01348 01349 return retval; 01350 } 01351 01352 papi_return( PAPI_EINVAL ); 01353 } 01354 01398 int 01399 PAPI_create_eventset( int *EventSet ) 01400 { 01401 APIDBG("Entry: EventSet: %p\n", EventSet); 01402 ThreadInfo_t *master; 01403 int retval; 01404 01405 if ( init_level == PAPI_NOT_INITED ) 01406 papi_return( PAPI_ENOINIT ); 01407 retval = _papi_hwi_lookup_or_create_thread( &master, 0 ); 01408 if ( retval ) 01409 papi_return( retval ); 01410 01411 papi_return( _papi_hwi_create_eventset( EventSet, master ) ); 01412 } 01413 01459 int 01460 PAPI_assign_eventset_component( int EventSet, int cidx ) 01461 { 01462 EventSetInfo_t *ESI; 01463 int retval; 01464 01465 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01466 if ( ESI == NULL ) 01467 papi_return( PAPI_ENOEVST ); 01468 01469 /* validate cidx */ 01470 retval = valid_component( cidx ); 01471 if ( retval < 0 ) 01472 papi_return( retval ); 01473 01474 /* cowardly refuse to reassign eventsets */ 01475 if ( ESI->CmpIdx >= 0 ) 01476 return PAPI_EINVAL; 01477 01478 return ( _papi_hwi_assign_eventset( ESI, cidx ) ); 01479 } 01480 01502 int 01503 PAPI_get_eventset_component( int EventSet) 01504 { 01505 EventSetInfo_t *ESI; 01506 int retval; 01507 01508 /* validate eventset */ 01509 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01510 if ( ESI == NULL ) 01511 papi_return( PAPI_ENOEVST ); 01512 01513 /* check if a component has been assigned */ 01514 if ( ESI->CmpIdx < 0 ) 01515 papi_return( PAPI_ENOCMP ); 01516 01517 /* validate CmpIdx */ 01518 retval = valid_component( ESI->CmpIdx ); 01519 if ( retval < 0 ) 01520 papi_return( retval ); 01521 01522 /* return the index */ 01523 return ( ESI->CmpIdx ); 01524 } 01525 01526 01596 int 01597 PAPI_add_event( int EventSet, int EventCode ) 01598 { 01599 APIDBG("Entry: EventSet: %d, EventCode: %#x\n", EventSet, EventCode); 01600 EventSetInfo_t *ESI; 01601 01602 /* Is the EventSet already in existence? */ 01603 01604 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01605 if ( ESI == NULL ) 01606 papi_return( PAPI_ENOEVST ); 01607 01608 /* Check argument for validity */ 01609 01610 if ( ( ( EventCode & PAPI_PRESET_MASK ) == 0 ) && 01611 ( EventCode & PAPI_NATIVE_MASK ) == 0 ) 01612 papi_return( PAPI_EINVAL ); 01613 01614 /* Of course, it must be stopped in order to modify it. */ 01615 01616 if ( ESI->state & PAPI_RUNNING ) 01617 papi_return( PAPI_EISRUN ); 01618 01619 /* Now do the magic. */ 01620 01621 papi_return( _papi_hwi_add_event( ESI, EventCode ) ); 01622 } 01623 01691 int 01692 PAPI_remove_event( int EventSet, int EventCode ) 01693 { 01694 EventSetInfo_t *ESI; 01695 int i,retval; 01696 01697 /* check for pre-existing ESI */ 01698 01699 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01700 if ( ESI == NULL ) 01701 papi_return( PAPI_ENOEVST ); 01702 01703 /* Check argument for validity */ 01704 01705 if ( ( !IS_PRESET(EventCode) ) && 01706 ( !IS_NATIVE(EventCode) ) && 01707 ( !IS_USER_DEFINED(EventCode) )) 01708 papi_return( PAPI_EINVAL ); 01709 01710 /* Of course, it must be stopped in order to modify it. */ 01711 01712 if ( !( ESI->state & PAPI_STOPPED ) ) 01713 papi_return( PAPI_EISRUN ); 01714 01715 /* if the state is PAPI_OVERFLOWING, you must first call 01716 PAPI_overflow with threshold=0 to remove the overflow flag */ 01717 01718 /* Turn off the event that is overflowing */ 01719 if ( ESI->state & PAPI_OVERFLOWING ) { 01720 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 01721 if ( ESI->overflow.EventCode[i] == EventCode ) { 01722 retval = PAPI_overflow( EventSet, EventCode, 0, 0, 01723 ESI->overflow.handler ); 01724 if (retval!=PAPI_OK) return retval; 01725 break; 01726 } 01727 } 01728 } 01729 01730 /* force the user to call PAPI_profil to clear the PAPI_PROFILING flag */ 01731 if ( ESI->state & PAPI_PROFILING ) { 01732 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 01733 if ( ESI->profile.EventCode[i] == EventCode ) { 01734 PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, 0 ); 01735 break; 01736 } 01737 } 01738 } 01739 01740 /* Now do the magic. */ 01741 01742 papi_return( _papi_hwi_remove_event( ESI, EventCode ) ); 01743 } 01744 01808 int 01809 PAPI_add_named_event( int EventSet, char *EventName ) 01810 { 01811 int ret, code; 01812 01813 ret = PAPI_event_name_to_code( EventName, &code ); 01814 if ( ret == PAPI_OK ) ret = PAPI_add_event( EventSet, code ); 01815 papi_return( ret ); 01816 } 01817 01885 int 01886 PAPI_remove_named_event( int EventSet, char *EventName ) 01887 { 01888 int ret, code; 01889 01890 ret = PAPI_event_name_to_code( EventName, &code ); 01891 if ( ret == PAPI_OK ) ret = PAPI_remove_event( EventSet, code ); 01892 papi_return( ret ); 01893 } 01894 01936 int 01937 PAPI_destroy_eventset( int *EventSet ) 01938 { 01939 EventSetInfo_t *ESI; 01940 01941 APIDBG("Destroying Eventset %d\n",*EventSet); 01942 01943 /* check for pre-existing ESI */ 01944 01945 if ( EventSet == NULL ) 01946 papi_return( PAPI_EINVAL ); 01947 01948 ESI = _papi_hwi_lookup_EventSet( *EventSet ); 01949 if ( ESI == NULL ) 01950 papi_return( PAPI_ENOEVST ); 01951 01952 if ( !( ESI->state & PAPI_STOPPED ) ) 01953 papi_return( PAPI_EISRUN ); 01954 01955 if ( ESI->NumberOfEvents ) 01956 papi_return( PAPI_EINVAL ); 01957 01958 _papi_hwi_remove_EventSet( ESI ); 01959 *EventSet = PAPI_NULL; 01960 01961 return PAPI_OK; 01962 } 01963 01964 /* simply checks for valid EventSet, calls component start() call */ 02018 int 02019 PAPI_start( int EventSet ) 02020 { 02021 02022 int is_dirty=0; 02023 int retval; 02024 EventSetInfo_t *ESI; 02025 ThreadInfo_t *thread = NULL; 02026 CpuInfo_t *cpu = NULL; 02027 hwd_context_t *context; 02028 int cidx; 02029 02030 APIDBG("Entry: EventSet: %d\n", EventSet); 02031 02032 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02033 if ( ESI == NULL ) { 02034 papi_return( PAPI_ENOEVST ); 02035 } 02036 02037 APIDBG("EventSet: %p\n", ESI); 02038 02039 cidx = valid_ESI_component( ESI ); 02040 if ( cidx < 0 ) { 02041 papi_return( cidx ); 02042 } 02043 02044 /* only one event set per thread can be running at any time, */ 02045 /* so if another event set is running, the user must stop that */ 02046 /* event set explicitly */ 02047 02048 /* We used to check and not let multiple events be attached */ 02049 /* to the same CPU, but this was unnecessary? */ 02050 02051 thread = ESI->master; 02052 cpu = ESI->CpuInfo; 02053 02054 if ( thread->running_eventset[cidx] ) { 02055 APIDBG("Thread Running already (Only one active Eventset per component)\n"); 02056 papi_return( PAPI_EISRUN ); 02057 } 02058 02059 /* Check that there are added events */ 02060 if ( ESI->NumberOfEvents < 1 ) { 02061 papi_return( PAPI_EINVAL ); 02062 } 02063 02064 /* If multiplexing is enabled for this eventset, 02065 call John May's code. */ 02066 02067 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02068 retval = MPX_start( ESI->multiplex.mpx_evset ); 02069 if ( retval != PAPI_OK ) { 02070 papi_return( retval ); 02071 } 02072 02073 /* Update the state of this EventSet */ 02074 ESI->state ^= PAPI_STOPPED; 02075 ESI->state |= PAPI_RUNNING; 02076 02077 return PAPI_OK; 02078 } 02079 02080 /* get the context we should use for this event set */ 02081 context = _papi_hwi_get_context( ESI, &is_dirty ); 02082 if (is_dirty) { 02083 /* we need to reset the context state because it was last used */ 02084 /* for some other event set and does not contain the information */ 02085 /* for our events. */ 02086 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( 02087 ESI->ctl_state, 02088 ESI->NativeInfoArray, 02089 ESI->NativeCount, 02090 context); 02091 if ( retval != PAPI_OK ) { 02092 papi_return( retval ); 02093 } 02094 02095 /* now that the context contains this event sets information, */ 02096 /* make sure the position array in the EventInfoArray is correct */ 02097 02098 /* We have to do this because ->update_control_state() can */ 02099 /* in theory re-order the native events out from under us. */ 02100 _papi_hwi_map_events_to_native( ESI ); 02101 02102 } 02103 02104 /* If overflowing is enabled, turn it on */ 02105 if ( ( ESI->state & PAPI_OVERFLOWING ) && 02106 !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02107 retval = _papi_hwi_start_signal( _papi_os_info.itimer_sig, 02108 NEED_CONTEXT, cidx ); 02109 if ( retval != PAPI_OK ) { 02110 papi_return( retval ); 02111 } 02112 02113 /* Update the state of this EventSet and thread */ 02114 /* before to avoid races */ 02115 ESI->state ^= PAPI_STOPPED; 02116 ESI->state |= PAPI_RUNNING; 02117 /* can not be attached to thread or cpu if overflowing */ 02118 thread->running_eventset[cidx] = ESI; 02119 02120 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02121 if ( retval != PAPI_OK ) { 02122 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02123 ESI->state ^= PAPI_RUNNING; 02124 ESI->state |= PAPI_STOPPED; 02125 thread->running_eventset[cidx] = NULL; 02126 papi_return( retval ); 02127 } 02128 02129 retval = _papi_hwi_start_timer( _papi_os_info.itimer_num, 02130 _papi_os_info.itimer_sig, 02131 _papi_os_info.itimer_ns ); 02132 if ( retval != PAPI_OK ) { 02133 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02134 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02135 ESI->state ^= PAPI_RUNNING; 02136 ESI->state |= PAPI_STOPPED; 02137 thread->running_eventset[cidx] = NULL; 02138 papi_return( retval ); 02139 } 02140 } else { 02141 /* Update the state of this EventSet and thread before */ 02142 /* to avoid races */ 02143 ESI->state ^= PAPI_STOPPED; 02144 ESI->state |= PAPI_RUNNING; 02145 02146 /* if not attached to cpu or another process */ 02147 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02148 if ( !( ESI->state & PAPI_ATTACHED ) ) { 02149 thread->running_eventset[cidx] = ESI; 02150 } 02151 } else { 02152 cpu->running_eventset[cidx] = ESI; 02153 } 02154 02155 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02156 if ( retval != PAPI_OK ) { 02157 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02158 ESI->state ^= PAPI_RUNNING; 02159 ESI->state |= PAPI_STOPPED; 02160 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02161 if ( !( ESI->state & PAPI_ATTACHED ) ) 02162 thread->running_eventset[cidx] = NULL; 02163 } else { 02164 cpu->running_eventset[cidx] = NULL; 02165 } 02166 papi_return( retval ); 02167 } 02168 } 02169 02170 return retval; 02171 } 02172 02173 /* checks for valid EventSet, calls component stop() function. */ 02224 int 02225 PAPI_stop( int EventSet, long long *values ) 02226 { 02227 APIDBG("Entry: EventSet: %d, values: %p\n", EventSet, values); 02228 EventSetInfo_t *ESI; 02229 hwd_context_t *context; 02230 int cidx, retval; 02231 02232 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02233 if ( ESI == NULL ) 02234 papi_return( PAPI_ENOEVST ); 02235 02236 cidx = valid_ESI_component( ESI ); 02237 if ( cidx < 0 ) 02238 papi_return( cidx ); 02239 02240 if ( !( ESI->state & PAPI_RUNNING ) ) 02241 papi_return( PAPI_ENOTRUN ); 02242 02243 /* If multiplexing is enabled for this eventset, turn if off */ 02244 02245 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02246 retval = MPX_stop( ESI->multiplex.mpx_evset, values ); 02247 if ( retval != PAPI_OK ) 02248 papi_return( retval ); 02249 02250 /* Update the state of this EventSet */ 02251 02252 ESI->state ^= PAPI_RUNNING; 02253 ESI->state |= PAPI_STOPPED; 02254 02255 return ( PAPI_OK ); 02256 } 02257 02258 /* get the context we should use for this event set */ 02259 context = _papi_hwi_get_context( ESI, NULL ); 02260 /* Read the current counter values into the EventSet */ 02261 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02262 if ( retval != PAPI_OK ) 02263 papi_return( retval ); 02264 02265 /* Remove the control bits from the active counter config. */ 02266 retval = _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02267 if ( retval != PAPI_OK ) 02268 papi_return( retval ); 02269 if ( values ) 02270 memcpy( values, ESI->sw_stop, 02271 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02272 02273 /* If kernel profiling is in use, flush and process the kernel buffer */ 02274 02275 if ( ESI->state & PAPI_PROFILING ) { 02276 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 02277 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02278 retval = _papi_hwd[cidx]->stop_profiling( ESI->master, ESI ); 02279 if ( retval < PAPI_OK ) 02280 papi_return( retval ); 02281 } 02282 } 02283 02284 /* If overflowing is enabled, turn it off */ 02285 02286 if ( ESI->state & PAPI_OVERFLOWING ) { 02287 if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02288 retval = _papi_hwi_stop_timer( _papi_os_info.itimer_num, 02289 _papi_os_info.itimer_sig ); 02290 if ( retval != PAPI_OK ) 02291 papi_return( retval ); 02292 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02293 } 02294 } 02295 02296 /* Update the state of this EventSet */ 02297 02298 ESI->state ^= PAPI_RUNNING; 02299 ESI->state |= PAPI_STOPPED; 02300 02301 /* Update the running event set for this thread */ 02302 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02303 if ( !( ESI->state & PAPI_ATTACHED )) 02304 ESI->master->running_eventset[cidx] = NULL; 02305 } else { 02306 ESI->CpuInfo->running_eventset[cidx] = NULL; 02307 } 02308 02309 #if defined(DEBUG) 02310 if ( _papi_hwi_debug & DEBUG_API ) { 02311 int i; 02312 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02313 APIDBG( "PAPI_stop ESI->sw_stop[%d]:\t%llu\n", i, ESI->sw_stop[i] ); 02314 } 02315 } 02316 #endif 02317 02318 return ( PAPI_OK ); 02319 } 02320 02369 int 02370 PAPI_reset( int EventSet ) 02371 { 02372 int retval = PAPI_OK; 02373 EventSetInfo_t *ESI; 02374 hwd_context_t *context; 02375 int cidx; 02376 02377 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02378 if ( ESI == NULL ) 02379 papi_return( PAPI_ENOEVST ); 02380 02381 cidx = valid_ESI_component( ESI ); 02382 if ( cidx < 0 ) 02383 papi_return( cidx ); 02384 02385 if ( ESI->state & PAPI_RUNNING ) { 02386 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02387 retval = MPX_reset( ESI->multiplex.mpx_evset ); 02388 } else { 02389 /* If we're not the only one running, then just 02390 read the current values into the ESI->start 02391 array. This holds the starting value for counters 02392 that are shared. */ 02393 /* get the context we should use for this event set */ 02394 context = _papi_hwi_get_context( ESI, NULL ); 02395 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02396 } 02397 } else { 02398 #ifdef __bgp__ 02399 // For BG/P, we always want to reset the 'real' hardware counters. The counters 02400 // can be controlled via multiple interfaces, and we need to ensure that the values 02401 // are truly zero... 02402 /* get the context we should use for this event set */ 02403 context = _papi_hwi_get_context( ESI, NULL ); 02404 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02405 #endif 02406 memset( ESI->sw_stop, 0x00, 02407 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02408 } 02409 02410 APIDBG( "PAPI_reset returns %d\n", retval ); 02411 papi_return( retval ); 02412 } 02413 02468 int 02469 PAPI_read( int EventSet, long long *values ) 02470 { 02471 EventSetInfo_t *ESI; 02472 hwd_context_t *context; 02473 int cidx, retval = PAPI_OK; 02474 02475 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02476 if ( ESI == NULL ) 02477 papi_return( PAPI_ENOEVST ); 02478 02479 cidx = valid_ESI_component( ESI ); 02480 if ( cidx < 0 ) 02481 papi_return( cidx ); 02482 02483 if ( values == NULL ) 02484 papi_return( PAPI_EINVAL ); 02485 02486 if ( ESI->state & PAPI_RUNNING ) { 02487 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02488 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02489 } else { 02490 /* get the context we should use for this event set */ 02491 context = _papi_hwi_get_context( ESI, NULL ); 02492 retval = _papi_hwi_read( context, ESI, values ); 02493 } 02494 if ( retval != PAPI_OK ) 02495 papi_return( retval ); 02496 } else { 02497 memcpy( values, ESI->sw_stop, 02498 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02499 } 02500 02501 #if defined(DEBUG) 02502 if ( ISLEVEL( DEBUG_API ) ) { 02503 int i; 02504 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02505 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02506 } 02507 } 02508 #endif 02509 02510 APIDBG( "PAPI_read returns %d\n", retval ); 02511 return ( PAPI_OK ); 02512 } 02513 02556 int 02557 PAPI_read_ts( int EventSet, long long *values, long long *cycles ) 02558 { 02559 EventSetInfo_t *ESI; 02560 hwd_context_t *context; 02561 int cidx, retval = PAPI_OK; 02562 02563 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02564 if ( ESI == NULL ) 02565 papi_return( PAPI_ENOEVST ); 02566 02567 cidx = valid_ESI_component( ESI ); 02568 if ( cidx < 0 ) 02569 papi_return( cidx ); 02570 02571 if ( values == NULL ) 02572 papi_return( PAPI_EINVAL ); 02573 02574 if ( ESI->state & PAPI_RUNNING ) { 02575 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02576 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02577 } else { 02578 /* get the context we should use for this event set */ 02579 context = _papi_hwi_get_context( ESI, NULL ); 02580 retval = _papi_hwi_read( context, ESI, values ); 02581 } 02582 if ( retval != PAPI_OK ) 02583 papi_return( retval ); 02584 } else { 02585 memcpy( values, ESI->sw_stop, 02586 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02587 } 02588 02589 *cycles = _papi_os_vector.get_real_cycles( ); 02590 02591 #if defined(DEBUG) 02592 if ( ISLEVEL( DEBUG_API ) ) { 02593 int i; 02594 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02595 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02596 } 02597 } 02598 #endif 02599 02600 APIDBG( "PAPI_read_ts returns %d\n", retval ); 02601 return PAPI_OK; 02602 } 02603 02652 int 02653 PAPI_accum( int EventSet, long long *values ) 02654 { 02655 EventSetInfo_t *ESI; 02656 hwd_context_t *context; 02657 int i, cidx, retval; 02658 long long a, b, c; 02659 02660 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02661 if ( ESI == NULL ) 02662 papi_return( PAPI_ENOEVST ); 02663 02664 cidx = valid_ESI_component( ESI ); 02665 if ( cidx < 0 ) 02666 papi_return( cidx ); 02667 02668 if ( values == NULL ) 02669 papi_return( PAPI_EINVAL ); 02670 02671 if ( ESI->state & PAPI_RUNNING ) { 02672 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02673 retval = MPX_read( ESI->multiplex.mpx_evset, ESI->sw_stop, 0 ); 02674 } else { 02675 /* get the context we should use for this event set */ 02676 context = _papi_hwi_get_context( ESI, NULL ); 02677 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02678 } 02679 if ( retval != PAPI_OK ) 02680 papi_return( retval ); 02681 } 02682 02683 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02684 a = ESI->sw_stop[i]; 02685 b = values[i]; 02686 c = a + b; 02687 values[i] = c; 02688 } 02689 02690 papi_return( PAPI_reset( EventSet ) ); 02691 } 02692 02719 int 02720 PAPI_write( int EventSet, long long *values ) 02721 { 02722 int cidx, retval = PAPI_OK; 02723 EventSetInfo_t *ESI; 02724 hwd_context_t *context; 02725 02726 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02727 if ( ESI == NULL ) 02728 papi_return( PAPI_ENOEVST ); 02729 02730 cidx = valid_ESI_component( ESI ); 02731 if ( cidx < 0 ) 02732 papi_return( cidx ); 02733 02734 if ( values == NULL ) 02735 papi_return( PAPI_EINVAL ); 02736 02737 if ( ESI->state & PAPI_RUNNING ) { 02738 /* get the context we should use for this event set */ 02739 context = _papi_hwi_get_context( ESI, NULL ); 02740 retval = _papi_hwd[cidx]->write( context, ESI->ctl_state, values ); 02741 if ( retval != PAPI_OK ) 02742 return ( retval ); 02743 } 02744 02745 memcpy( ESI->hw_start, values, 02746 ( size_t ) _papi_hwd[cidx]->cmp_info.num_cntrs * 02747 sizeof ( long long ) ); 02748 02749 return ( retval ); 02750 } 02751 02794 int 02795 PAPI_cleanup_eventset( int EventSet ) 02796 { 02797 EventSetInfo_t *ESI; 02798 int i, cidx, total, retval; 02799 02800 APIDBG("Attempting to cleanup Eventset %d\n",EventSet); 02801 02802 /* Is the EventSet already in existence? */ 02803 02804 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02805 if ( ESI == NULL ) 02806 papi_return( PAPI_ENOEVST ); 02807 02808 /* if the eventset has no index and no events, return OK 02809 otherwise return NOCMP */ 02810 cidx = valid_ESI_component( ESI ); 02811 if ( cidx < 0 ) { 02812 if ( ESI->NumberOfEvents ) 02813 papi_return( cidx ); 02814 papi_return( PAPI_OK ); 02815 } 02816 02817 /* Of course, it must be stopped in order to modify it. */ 02818 02819 if ( ESI->state & PAPI_RUNNING ) 02820 papi_return( PAPI_EISRUN ); 02821 02822 /* clear overflow flag and turn off hardware overflow handler */ 02823 if ( ESI->state & PAPI_OVERFLOWING ) { 02824 total = ESI->overflow.event_counter; 02825 for ( i = 0; i < total; i++ ) { 02826 retval = PAPI_overflow( EventSet, 02827 ESI->overflow.EventCode[0], 0, 0, NULL ); 02828 if ( retval != PAPI_OK ) 02829 papi_return( retval ); 02830 } 02831 } 02832 02833 /* clear profile flag and turn off hardware profile handler */ 02834 if ( ( ESI->state & PAPI_PROFILING ) && 02835 _papi_hwd[cidx]->cmp_info.hardware_intr && 02836 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02837 total = ESI->profile.event_counter; 02838 for ( i = 0; i < total; i++ ) { 02839 retval = 02840 PAPI_sprofil( NULL, 0, EventSet, ESI->profile.EventCode[0], 0, 02841 PAPI_PROFIL_POSIX ); 02842 if ( retval != PAPI_OK ) 02843 papi_return( retval ); 02844 } 02845 } 02846 02847 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02848 retval = MPX_cleanup( &ESI->multiplex.mpx_evset ); 02849 if ( retval != PAPI_OK ) 02850 papi_return( retval ); 02851 } 02852 02853 retval = _papi_hwd[cidx]->cleanup_eventset( ESI->ctl_state ); 02854 if ( retval != PAPI_OK ) 02855 papi_return( retval ); 02856 02857 /* Now do the magic */ 02858 papi_return( _papi_hwi_cleanup_eventset( ESI ) ); 02859 } 02860 02886 int 02887 PAPI_multiplex_init( void ) 02888 { 02889 int retval; 02890 02891 retval = mpx_init( _papi_os_info.itimer_ns ); 02892 papi_return( retval ); 02893 } 02894 02955 int 02956 PAPI_state( int EventSet, int *status ) 02957 { 02958 EventSetInfo_t *ESI; 02959 02960 if ( status == NULL ) 02961 papi_return( PAPI_EINVAL ); 02962 02963 /* check for good EventSetIndex value */ 02964 02965 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02966 if ( ESI == NULL ) 02967 papi_return( PAPI_ENOEVST ); 02968 02969 /*read status FROM ESI->state */ 02970 02971 *status = ESI->state; 02972 02973 return ( PAPI_OK ); 02974 } 02975 03026 int 03027 PAPI_set_debug( int level ) 03028 { 03029 PAPI_option_t option; 03030 03031 memset( &option, 0x0, sizeof ( option ) ); 03032 option.debug.level = level; 03033 option.debug.handler = _papi_hwi_debug_handler; 03034 return ( PAPI_set_opt( PAPI_DEBUG, &option ) ); 03035 } 03036 03037 /* Attaches to or detaches from the specified thread id */ 03038 inline_static int 03039 _papi_set_attach( int option, int EventSet, unsigned long tid ) 03040 { 03041 PAPI_option_t attach; 03042 03043 memset( &attach, 0x0, sizeof ( attach ) ); 03044 attach.attach.eventset = EventSet; 03045 attach.attach.tid = tid; 03046 return ( PAPI_set_opt( option, &attach ) ); 03047 } 03048 03099 int 03100 PAPI_attach( int EventSet, unsigned long tid ) 03101 { 03102 return ( _papi_set_attach( PAPI_ATTACH, EventSet, tid ) ); 03103 } 03104 03155 int 03156 PAPI_detach( int EventSet ) 03157 { 03158 return ( _papi_set_attach( PAPI_DETACH, EventSet, 0 ) ); 03159 } 03160 03229 int 03230 PAPI_set_multiplex( int EventSet ) 03231 { 03232 PAPI_option_t mpx; 03233 EventSetInfo_t *ESI; 03234 int cidx; 03235 int ret; 03236 03237 /* Is the EventSet already in existence? */ 03238 03239 ESI = _papi_hwi_lookup_EventSet( EventSet ); 03240 03241 if ( ESI == NULL ) 03242 papi_return( PAPI_ENOEVST ); 03243 03244 /* if the eventset has no index return NOCMP */ 03245 cidx = valid_ESI_component( ESI ); 03246 if ( cidx < 0 ) 03247 papi_return( cidx ); 03248 03249 if ( ( ret = mpx_check( EventSet ) ) != PAPI_OK ) 03250 papi_return( ret ); 03251 03252 memset( &mpx, 0x0, sizeof ( mpx ) ); 03253 mpx.multiplex.eventset = EventSet; 03254 mpx.multiplex.flags = PAPI_MULTIPLEX_DEFAULT; 03255 mpx.multiplex.ns = _papi_os_info.itimer_ns; 03256 return ( PAPI_set_opt( PAPI_MULTIPLEX, &mpx ) ); 03257 } 03258 03359 int 03360 PAPI_set_opt( int option, PAPI_option_t * ptr ) 03361 { 03362 APIDBG("Entry: option: %d, ptr: %p\n", option, ptr); 03363 03364 _papi_int_option_t internal; 03365 int retval = PAPI_OK; 03366 hwd_context_t *context; 03367 int cidx; 03368 03369 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 03370 papi_return( PAPI_ENOINIT ); 03371 if ( ptr == NULL ) 03372 papi_return( PAPI_EINVAL ); 03373 03374 memset( &internal, 0x0, sizeof ( _papi_int_option_t ) ); 03375 03376 switch ( option ) { 03377 case PAPI_DETACH: 03378 { 03379 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03380 if ( internal.attach.ESI == NULL ) 03381 papi_return( PAPI_ENOEVST ); 03382 03383 cidx = valid_ESI_component( internal.attach.ESI ); 03384 if ( cidx < 0 ) 03385 papi_return( cidx ); 03386 03387 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03388 papi_return( PAPI_ECMP ); 03389 03390 /* if attached to a cpu, return an error */ 03391 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03392 papi_return( PAPI_ECMP ); 03393 03394 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03395 papi_return( PAPI_EISRUN ); 03396 03397 if ( ( internal.attach.ESI->state & PAPI_ATTACHED ) == 0 ) 03398 papi_return( PAPI_EINVAL ); 03399 03400 internal.attach.tid = internal.attach.ESI->attach.tid; 03401 /* get the context we should use for this event set */ 03402 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03403 retval = _papi_hwd[cidx]->ctl( context, PAPI_DETACH, &internal ); 03404 if ( retval != PAPI_OK ) 03405 papi_return( retval ); 03406 03407 internal.attach.ESI->state ^= PAPI_ATTACHED; 03408 internal.attach.ESI->attach.tid = 0; 03409 return ( PAPI_OK ); 03410 } 03411 case PAPI_ATTACH: 03412 { 03413 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03414 if ( internal.attach.ESI == NULL ) 03415 papi_return( PAPI_ENOEVST ); 03416 03417 cidx = valid_ESI_component( internal.attach.ESI ); 03418 if ( cidx < 0 ) 03419 papi_return( cidx ); 03420 03421 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03422 papi_return( PAPI_ECMP ); 03423 03424 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03425 papi_return( PAPI_EISRUN ); 03426 03427 if ( internal.attach.ESI->state & PAPI_ATTACHED ) 03428 papi_return( PAPI_EINVAL ); 03429 03430 /* if attached to a cpu, return an error */ 03431 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03432 papi_return( PAPI_ECMP ); 03433 03434 internal.attach.tid = ptr->attach.tid; 03435 /* get the context we should use for this event set */ 03436 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03437 retval = _papi_hwd[cidx]->ctl( context, PAPI_ATTACH, &internal ); 03438 if ( retval != PAPI_OK ) 03439 papi_return( retval ); 03440 03441 internal.attach.ESI->state |= PAPI_ATTACHED; 03442 internal.attach.ESI->attach.tid = ptr->attach.tid; 03443 03444 papi_return (_papi_hwi_lookup_or_create_thread( 03445 &(internal.attach.ESI->master), ptr->attach.tid )); 03446 } 03447 case PAPI_CPU_ATTACH: 03448 { 03449 APIDBG("eventset: %d, cpu_num: %d\n", ptr->cpu.eventset, ptr->cpu.cpu_num); 03450 internal.cpu.ESI = _papi_hwi_lookup_EventSet( ptr->cpu.eventset ); 03451 if ( internal.cpu.ESI == NULL ) 03452 papi_return( PAPI_ENOEVST ); 03453 03454 internal.cpu.cpu_num = ptr->cpu.cpu_num; 03455 APIDBG("internal: %p, ESI: %p, cpu_num: %d\n", &internal, internal.cpu.ESI, internal.cpu.cpu_num); 03456 03457 cidx = valid_ESI_component( internal.cpu.ESI ); 03458 if ( cidx < 0 ) 03459 papi_return( cidx ); 03460 03461 if ( _papi_hwd[cidx]->cmp_info.cpu == 0 ) 03462 papi_return( PAPI_ECMP ); 03463 03464 // can not attach to a cpu if already attached to a process or 03465 // counters set to be inherited by child processes 03466 if ( internal.cpu.ESI->state & (PAPI_ATTACHED | PAPI_INHERIT) ) 03467 papi_return( PAPI_EINVAL ); 03468 03469 if ( ( internal.cpu.ESI->state & PAPI_STOPPED ) == 0 ) 03470 papi_return( PAPI_EISRUN ); 03471 03472 retval = _papi_hwi_lookup_or_create_cpu(&internal.cpu.ESI->CpuInfo, internal.cpu.cpu_num); 03473 if( retval != PAPI_OK) { 03474 papi_return( retval ); 03475 } 03476 03477 /* get the context we should use for this event set */ 03478 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03479 retval = _papi_hwd[cidx]->ctl( context, PAPI_CPU_ATTACH, &internal ); 03480 if ( retval != PAPI_OK ) 03481 papi_return( retval ); 03482 03483 /* set to show this event set is attached to a cpu not a thread */ 03484 internal.cpu.ESI->state |= PAPI_CPU_ATTACHED; 03485 return ( PAPI_OK ); 03486 } 03487 case PAPI_DEF_MPX_NS: 03488 { 03489 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03490 if ( ptr->multiplex.ns < 0 ) 03491 papi_return( PAPI_EINVAL ); 03492 /* We should check the resolution here with the system, either 03493 component if kernel multiplexing or PAPI if SW multiplexing. */ 03494 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03495 /* get the context we should use for this event set */ 03496 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03497 /* Low level just checks/adjusts the args for this component */ 03498 retval = _papi_hwd[cidx]->ctl( context, PAPI_DEF_MPX_NS, &internal ); 03499 if ( retval == PAPI_OK ) { 03500 _papi_os_info.itimer_ns = ( int ) internal.multiplex.ns; 03501 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03502 } 03503 papi_return( retval ); 03504 } 03505 case PAPI_DEF_ITIMER_NS: 03506 { 03507 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03508 if ( ptr->itimer.ns < 0 ) 03509 papi_return( PAPI_EINVAL ); 03510 internal.itimer.ns = ptr->itimer.ns; 03511 /* Low level just checks/adjusts the args for this component */ 03512 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER_NS, &internal ); 03513 if ( retval == PAPI_OK ) { 03514 _papi_os_info.itimer_ns = internal.itimer.ns; 03515 ptr->itimer.ns = internal.itimer.ns; 03516 } 03517 papi_return( retval ); 03518 } 03519 case PAPI_DEF_ITIMER: 03520 { 03521 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03522 if ( ptr->itimer.ns < 0 ) 03523 papi_return( PAPI_EINVAL ); 03524 memcpy( &internal.itimer, &ptr->itimer, 03525 sizeof ( PAPI_itimer_option_t ) ); 03526 /* Low level just checks/adjusts the args for this component */ 03527 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER, &internal ); 03528 if ( retval == PAPI_OK ) { 03529 _papi_os_info.itimer_num = ptr->itimer.itimer_num; 03530 _papi_os_info.itimer_sig = ptr->itimer.itimer_sig; 03531 if ( ptr->itimer.ns > 0 ) 03532 _papi_os_info.itimer_ns = ptr->itimer.ns; 03533 /* flags are currently ignored, eventually the flags will be able 03534 to specify whether or not we use POSIX itimers (clock_gettimer) */ 03535 } 03536 papi_return( retval ); 03537 } 03538 case PAPI_MULTIPLEX: 03539 { 03540 EventSetInfo_t *ESI; 03541 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 03542 03543 if ( ESI == NULL ) 03544 papi_return( PAPI_ENOEVST ); 03545 03546 cidx = valid_ESI_component( ESI ); 03547 if ( cidx < 0 ) 03548 papi_return( cidx ); 03549 03550 if ( !( ESI->state & PAPI_STOPPED ) ) 03551 papi_return( PAPI_EISRUN ); 03552 if ( ESI->state & PAPI_MULTIPLEXING ) 03553 papi_return( PAPI_EINVAL ); 03554 03555 if ( ptr->multiplex.ns < 0 ) 03556 papi_return( PAPI_EINVAL ); 03557 internal.multiplex.ESI = ESI; 03558 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03559 internal.multiplex.flags = ptr->multiplex.flags; 03560 if ( ( _papi_hwd[cidx]->cmp_info.kernel_multiplex ) && 03561 ( ( ptr->multiplex.flags & PAPI_MULTIPLEX_FORCE_SW ) == 0 ) ) { 03562 /* get the context we should use for this event set */ 03563 context = _papi_hwi_get_context( ESI, NULL ); 03564 retval = _papi_hwd[cidx]->ctl( context, PAPI_MULTIPLEX, &internal ); 03565 } 03566 /* Kernel or PAPI may have changed this value so send it back out to the user */ 03567 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03568 if ( retval == PAPI_OK ) 03569 papi_return( _papi_hwi_convert_eventset_to_multiplex 03570 ( &internal.multiplex ) ); 03571 return ( retval ); 03572 } 03573 case PAPI_DEBUG: 03574 { 03575 int level = ptr->debug.level; 03576 switch ( level ) { 03577 case PAPI_QUIET: 03578 case PAPI_VERB_ESTOP: 03579 case PAPI_VERB_ECONT: 03580 _papi_hwi_error_level = level; 03581 break; 03582 default: 03583 papi_return( PAPI_EINVAL ); 03584 } 03585 _papi_hwi_debug_handler = ptr->debug.handler; 03586 return ( PAPI_OK ); 03587 } 03588 case PAPI_DEFDOM: 03589 { 03590 int dom = ptr->defdomain.domain; 03591 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03592 papi_return( PAPI_EINVAL ); 03593 03594 /* Change the global structure. The _papi_hwd_init_control_state function 03595 in the components gets information from the global structure instead of 03596 per-thread information. */ 03597 cidx = valid_component( ptr->defdomain.def_cidx ); 03598 if ( cidx < 0 ) 03599 papi_return( cidx ); 03600 03601 /* Check what the component supports */ 03602 03603 if ( dom == PAPI_DOM_ALL ) 03604 dom = _papi_hwd[cidx]->cmp_info.available_domains; 03605 03606 if ( dom & ~_papi_hwd[cidx]->cmp_info.available_domains ) 03607 papi_return( PAPI_EINVAL ); 03608 03609 _papi_hwd[cidx]->cmp_info.default_domain = dom; 03610 03611 return ( PAPI_OK ); 03612 } 03613 case PAPI_DOMAIN: 03614 { 03615 int dom = ptr->domain.domain; 03616 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03617 papi_return( PAPI_EINVAL_DOM ); 03618 03619 internal.domain.ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 03620 if ( internal.domain.ESI == NULL ) 03621 papi_return( PAPI_ENOEVST ); 03622 03623 cidx = valid_ESI_component( internal.domain.ESI ); 03624 if ( cidx < 0 ) 03625 papi_return( cidx ); 03626 03627 /* Check what the component supports */ 03628 03629 if ( dom == PAPI_DOM_ALL ) 03630 dom = _papi_hwd[cidx]->cmp_info.available_domains; 03631 03632 if ( dom & ~_papi_hwd[cidx]->cmp_info.available_domains ) 03633 papi_return( PAPI_EINVAL_DOM ); 03634 03635 if ( !( internal.domain.ESI->state & PAPI_STOPPED ) ) 03636 papi_return( PAPI_EISRUN ); 03637 03638 /* Try to change the domain of the eventset in the hardware */ 03639 internal.domain.domain = dom; 03640 internal.domain.eventset = ptr->domain.eventset; 03641 /* get the context we should use for this event set */ 03642 context = _papi_hwi_get_context( internal.domain.ESI, NULL ); 03643 retval = _papi_hwd[cidx]->ctl( context, PAPI_DOMAIN, &internal ); 03644 if ( retval < PAPI_OK ) 03645 papi_return( retval ); 03646 03647 /* Change the domain of the eventset in the library */ 03648 03649 internal.domain.ESI->domain.domain = dom; 03650 03651 return ( retval ); 03652 } 03653 case PAPI_DEFGRN: 03654 { 03655 int grn = ptr->defgranularity.granularity; 03656 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03657 papi_return( PAPI_EINVAL ); 03658 03659 cidx = valid_component( ptr->defgranularity.def_cidx ); 03660 if ( cidx < 0 ) 03661 papi_return( cidx ); 03662 03663 /* Change the component structure. The _papi_hwd_init_control_state function 03664 in the components gets information from the global structure instead of 03665 per-thread information. */ 03666 03667 /* Check what the component supports */ 03668 03669 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03670 papi_return( PAPI_EINVAL ); 03671 03672 /* Make sure there is only 1 set. */ 03673 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03674 papi_return( PAPI_EINVAL ); 03675 03676 _papi_hwd[cidx]->cmp_info.default_granularity = grn; 03677 03678 return ( PAPI_OK ); 03679 } 03680 case PAPI_GRANUL: 03681 { 03682 int grn = ptr->granularity.granularity; 03683 03684 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03685 papi_return( PAPI_EINVAL ); 03686 03687 internal.granularity.ESI = 03688 _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 03689 if ( internal.granularity.ESI == NULL ) 03690 papi_return( PAPI_ENOEVST ); 03691 03692 cidx = valid_ESI_component( internal.granularity.ESI ); 03693 if ( cidx < 0 ) 03694 papi_return( cidx ); 03695 03696 /* Check what the component supports */ 03697 03698 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03699 papi_return( PAPI_EINVAL ); 03700 03701 /* Make sure there is only 1 set. */ 03702 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03703 papi_return( PAPI_EINVAL ); 03704 03705 internal.granularity.granularity = grn; 03706 internal.granularity.eventset = ptr->granularity.eventset; 03707 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_GRANUL, &internal ); 03708 if ( retval < PAPI_OK ) 03709 return ( retval ); 03710 03711 internal.granularity.ESI->granularity.granularity = grn; 03712 return ( retval ); 03713 } 03714 case PAPI_INHERIT: 03715 { 03716 EventSetInfo_t *ESI; 03717 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 03718 if ( ESI == NULL ) 03719 papi_return( PAPI_ENOEVST ); 03720 03721 cidx = valid_ESI_component( ESI ); 03722 if ( cidx < 0 ) 03723 papi_return( cidx ); 03724 03725 if ( _papi_hwd[cidx]->cmp_info.inherit == 0 ) 03726 papi_return( PAPI_ECMP ); 03727 03728 if ( ( ESI->state & PAPI_STOPPED ) == 0 ) 03729 papi_return( PAPI_EISRUN ); 03730 03731 /* if attached to a cpu, return an error */ 03732 if (ESI->state & PAPI_CPU_ATTACHED) 03733 papi_return( PAPI_ECMP ); 03734 03735 internal.inherit.ESI = ESI; 03736 internal.inherit.inherit = ptr->inherit.inherit; 03737 03738 /* get the context we should use for this event set */ 03739 context = _papi_hwi_get_context( internal.inherit.ESI, NULL ); 03740 retval = _papi_hwd[cidx]->ctl( context, PAPI_INHERIT, &internal ); 03741 if ( retval < PAPI_OK ) 03742 return ( retval ); 03743 03744 ESI->inherit.inherit = ptr->inherit.inherit; 03745 return ( retval ); 03746 } 03747 case PAPI_DATA_ADDRESS: 03748 case PAPI_INSTR_ADDRESS: 03749 { 03750 03751 EventSetInfo_t *ESI; 03752 03753 ESI = _papi_hwi_lookup_EventSet( ptr->addr.eventset ); 03754 if ( ESI == NULL ) 03755 papi_return( PAPI_ENOEVST ); 03756 03757 cidx = valid_ESI_component( ESI ); 03758 if ( cidx < 0 ) 03759 papi_return( cidx ); 03760 03761 internal.address_range.ESI = ESI; 03762 03763 if ( !( internal.address_range.ESI->state & PAPI_STOPPED ) ) 03764 papi_return( PAPI_EISRUN ); 03765 03766 /*set domain to be PAPI_DOM_USER */ 03767 internal.address_range.domain = PAPI_DOM_USER; 03768 03769 internal.address_range.start = ptr->addr.start; 03770 internal.address_range.end = ptr->addr.end; 03771 /* get the context we should use for this event set */ 03772 context = _papi_hwi_get_context( internal.address_range.ESI, NULL ); 03773 retval = _papi_hwd[cidx]->ctl( context, option, &internal ); 03774 ptr->addr.start_off = internal.address_range.start_off; 03775 ptr->addr.end_off = internal.address_range.end_off; 03776 papi_return( retval ); 03777 } 03778 case PAPI_USER_EVENTS_FILE: 03779 { 03780 SUBDBG("Filename is -%s-\n", ptr->events_file); 03781 _papi_user_defined_events_setup(ptr->events_file); 03782 return( PAPI_OK ); 03783 } 03784 default: 03785 papi_return( PAPI_EINVAL ); 03786 } 03787 } 03788 03798 int 03799 PAPI_num_hwctrs( void ) 03800 { 03801 return ( PAPI_num_cmp_hwctrs( 0 ) ); 03802 } 03803 03853 int 03854 PAPI_num_cmp_hwctrs( int cidx ) 03855 { 03856 return ( PAPI_get_cmp_opt( PAPI_MAX_HWCTRS, NULL, cidx ) ); 03857 } 03858 03915 int 03916 PAPI_get_multiplex( int EventSet ) 03917 { 03918 PAPI_option_t popt; 03919 int retval; 03920 03921 popt.multiplex.eventset = EventSet; 03922 retval = PAPI_get_opt( PAPI_MULTIPLEX, &popt ); 03923 if ( retval < 0 ) 03924 retval = 0; 03925 return retval; 03926 } 03927 04029 int 04030 PAPI_get_opt( int option, PAPI_option_t * ptr ) 04031 { 04032 EventSetInfo_t *ESI; 04033 04034 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 04035 papi_return( PAPI_ENOINIT ); 04036 04037 switch ( option ) { 04038 case PAPI_DETACH: 04039 { 04040 if ( ptr == NULL ) 04041 papi_return( PAPI_EINVAL ); 04042 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04043 if ( ESI == NULL ) 04044 papi_return( PAPI_ENOEVST ); 04045 ptr->attach.tid = ESI->attach.tid; 04046 return ( ( ESI->state & PAPI_ATTACHED ) == 0 ); 04047 } 04048 case PAPI_ATTACH: 04049 { 04050 if ( ptr == NULL ) 04051 papi_return( PAPI_EINVAL ); 04052 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04053 if ( ESI == NULL ) 04054 papi_return( PAPI_ENOEVST ); 04055 ptr->attach.tid = ESI->attach.tid; 04056 return ( ( ESI->state & PAPI_ATTACHED ) != 0 ); 04057 } 04058 case PAPI_CPU_ATTACH: 04059 { 04060 if ( ptr == NULL ) 04061 papi_return( PAPI_EINVAL ); 04062 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04063 if ( ESI == NULL ) 04064 papi_return( PAPI_ENOEVST ); 04065 ptr->cpu.cpu_num = ESI->CpuInfo->cpu_num; 04066 return ( ( ESI->state & PAPI_CPU_ATTACHED ) != 0 ); 04067 } 04068 case PAPI_DEF_MPX_NS: 04069 { 04070 /* xxxx for now, assume we only check against cpu component */ 04071 if ( ptr == NULL ) 04072 papi_return( PAPI_EINVAL ); 04073 ptr->multiplex.ns = _papi_os_info.itimer_ns; 04074 return ( PAPI_OK ); 04075 } 04076 case PAPI_DEF_ITIMER_NS: 04077 { 04078 /* xxxx for now, assume we only check against cpu component */ 04079 if ( ptr == NULL ) 04080 papi_return( PAPI_EINVAL ); 04081 ptr->itimer.ns = _papi_os_info.itimer_ns; 04082 return ( PAPI_OK ); 04083 } 04084 case PAPI_DEF_ITIMER: 04085 { 04086 /* xxxx for now, assume we only check against cpu component */ 04087 if ( ptr == NULL ) 04088 papi_return( PAPI_EINVAL ); 04089 ptr->itimer.itimer_num = _papi_os_info.itimer_num; 04090 ptr->itimer.itimer_sig = _papi_os_info.itimer_sig; 04091 ptr->itimer.ns = _papi_os_info.itimer_ns; 04092 ptr->itimer.flags = 0; 04093 return ( PAPI_OK ); 04094 } 04095 case PAPI_MULTIPLEX: 04096 { 04097 if ( ptr == NULL ) 04098 papi_return( PAPI_EINVAL ); 04099 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 04100 if ( ESI == NULL ) 04101 papi_return( PAPI_ENOEVST ); 04102 ptr->multiplex.ns = ESI->multiplex.ns; 04103 ptr->multiplex.flags = ESI->multiplex.flags; 04104 return ( ESI->state & PAPI_MULTIPLEXING ) != 0; 04105 } 04106 case PAPI_PRELOAD: 04107 if ( ptr == NULL ) 04108 papi_return( PAPI_EINVAL ); 04109 memcpy( &ptr->preload, &_papi_hwi_system_info.preload_info, 04110 sizeof ( PAPI_preload_info_t ) ); 04111 break; 04112 case PAPI_DEBUG: 04113 if ( ptr == NULL ) 04114 papi_return( PAPI_EINVAL ); 04115 ptr->debug.level = _papi_hwi_error_level; 04116 ptr->debug.handler = _papi_hwi_debug_handler; 04117 break; 04118 case PAPI_CLOCKRATE: 04119 return ( ( int ) _papi_hwi_system_info.hw_info.cpu_max_mhz ); 04120 case PAPI_MAX_CPUS: 04121 return ( _papi_hwi_system_info.hw_info.ncpu ); 04122 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04123 At some future point, they may map onto different values. 04124 */ 04125 case PAPI_INHERIT: 04126 { 04127 if ( ptr == NULL ) 04128 papi_return( PAPI_EINVAL ); 04129 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 04130 if ( ESI == NULL ) 04131 papi_return( PAPI_ENOEVST ); 04132 ptr->inherit.inherit = ESI->inherit.inherit; 04133 return ( PAPI_OK ); 04134 } 04135 case PAPI_GRANUL: 04136 if ( ptr == NULL ) 04137 papi_return( PAPI_EINVAL ); 04138 ESI = _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 04139 if ( ESI == NULL ) 04140 papi_return( PAPI_ENOEVST ); 04141 ptr->granularity.granularity = ESI->granularity.granularity; 04142 break; 04143 case PAPI_EXEINFO: 04144 if ( ptr == NULL ) 04145 papi_return( PAPI_EINVAL ); 04146 ptr->exe_info = &_papi_hwi_system_info.exe_info; 04147 break; 04148 case PAPI_HWINFO: 04149 if ( ptr == NULL ) 04150 papi_return( PAPI_EINVAL ); 04151 ptr->hw_info = &_papi_hwi_system_info.hw_info; 04152 break; 04153 04154 case PAPI_DOMAIN: 04155 if ( ptr == NULL ) 04156 papi_return( PAPI_EINVAL ); 04157 ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 04158 if ( ESI == NULL ) 04159 papi_return( PAPI_ENOEVST ); 04160 ptr->domain.domain = ESI->domain.domain; 04161 return ( PAPI_OK ); 04162 case PAPI_LIB_VERSION: 04163 return ( PAPI_VERSION ); 04164 /* The following cases all require a component index 04165 and are handled by PAPI_get_cmp_opt() with cidx == 0*/ 04166 case PAPI_MAX_HWCTRS: 04167 case PAPI_MAX_MPX_CTRS: 04168 case PAPI_DEFDOM: 04169 case PAPI_DEFGRN: 04170 case PAPI_SHLIBINFO: 04171 case PAPI_COMPONENTINFO: 04172 return ( PAPI_get_cmp_opt( option, ptr, 0 ) ); 04173 default: 04174 papi_return( PAPI_EINVAL ); 04175 } 04176 return ( PAPI_OK ); 04177 } 04178 04220 int 04221 PAPI_get_cmp_opt( int option, PAPI_option_t * ptr, int cidx ) 04222 { 04223 04224 if (_papi_hwi_invalid_cmp(cidx)) { 04225 return PAPI_ECMP; 04226 } 04227 04228 switch ( option ) { 04229 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04230 At some future point, they may map onto different values. 04231 */ 04232 case PAPI_MAX_HWCTRS: 04233 return ( _papi_hwd[cidx]->cmp_info.num_cntrs ); 04234 case PAPI_MAX_MPX_CTRS: 04235 return ( _papi_hwd[cidx]->cmp_info.num_mpx_cntrs ); 04236 case PAPI_DEFDOM: 04237 return ( _papi_hwd[cidx]->cmp_info.default_domain ); 04238 case PAPI_DEFGRN: 04239 return ( _papi_hwd[cidx]->cmp_info.default_granularity ); 04240 case PAPI_SHLIBINFO: 04241 { 04242 int retval; 04243 if ( ptr == NULL ) 04244 papi_return( PAPI_EINVAL ); 04245 retval = _papi_os_vector.update_shlib_info( &_papi_hwi_system_info ); 04246 ptr->shlib_info = &_papi_hwi_system_info.shlib_info; 04247 papi_return( retval ); 04248 } 04249 case PAPI_COMPONENTINFO: 04250 if ( ptr == NULL ) 04251 papi_return( PAPI_EINVAL ); 04252 ptr->cmp_info = &( _papi_hwd[cidx]->cmp_info ); 04253 return PAPI_OK; 04254 default: 04255 papi_return( PAPI_EINVAL ); 04256 } 04257 return PAPI_OK; 04258 } 04259 04271 int 04272 PAPI_num_components( void ) 04273 { 04274 return ( papi_num_components ); 04275 } 04276 04309 int 04310 PAPI_num_events( int EventSet ) 04311 { 04312 EventSetInfo_t *ESI; 04313 04314 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04315 if ( !ESI ) 04316 papi_return( PAPI_ENOEVST ); 04317 04318 #ifdef DEBUG 04319 /* Not necessary */ 04320 if ( ESI->NumberOfEvents == 0 ) 04321 papi_return( PAPI_EINVAL ); 04322 #endif 04323 04324 return ( ESI->NumberOfEvents ); 04325 } 04326 04327 04343 void 04344 PAPI_shutdown( void ) 04345 { 04346 EventSetInfo_t *ESI; 04347 ThreadInfo_t *master; 04348 DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map; 04349 int i, j = 0, retval; 04350 04351 04352 APIDBG( "Enter\n" ); 04353 if ( init_retval == DEADBEEF ) { 04354 PAPIERROR( PAPI_SHUTDOWN_str ); 04355 return; 04356 } 04357 04358 MPX_shutdown( ); 04359 04360 /* Free all EventSets for this thread */ 04361 04362 master = _papi_hwi_lookup_thread( 0 ); 04363 04364 /* Count number of running EventSets AND */ 04365 /* Stop any running EventSets in this thread */ 04366 04367 #ifdef DEBUG 04368 again: 04369 #endif 04370 for( i = 0; i < map->totalSlots; i++ ) { 04371 ESI = map->dataSlotArray[i]; 04372 if ( ESI ) { 04373 if ( ESI->master == master ) { 04374 if ( ESI->state & PAPI_RUNNING ) { 04375 retval=PAPI_stop( i, NULL ); 04376 } 04377 retval=PAPI_cleanup_eventset( i ); 04378 if (retval!=PAPI_OK) PAPIERROR("Error during cleanup.\n"); 04379 _papi_hwi_free_EventSet( ESI ); 04380 } 04381 else { 04382 if ( ESI->state & PAPI_RUNNING ) { 04383 j++; 04384 } 04385 } 04386 } 04387 } 04388 04389 /* No locking required, we're just waiting for the others 04390 to call shutdown or stop their eventsets. */ 04391 04392 #ifdef DEBUG 04393 if ( j != 0 ) { 04394 PAPIERROR( PAPI_SHUTDOWN_SYNC_str ); 04395 sleep( 1 ); 04396 j = 0; 04397 goto again; 04398 } 04399 #endif 04400 04401 /* Shutdown the entire component */ 04402 04403 _papi_cleanup_user_events(); 04404 04405 _papi_hwi_shutdown_highlevel( ); 04406 _papi_hwi_shutdown_global_internal( ); 04407 _papi_hwi_shutdown_global_threads( ); 04408 for( i = 0; i < papi_num_components; i++ ) { 04409 if (!_papi_hwd[i]->cmp_info.disabled) { 04410 _papi_hwd[i]->shutdown_component( ); 04411 } 04412 } 04413 04414 /* Now it is safe to call re-init */ 04415 04416 init_retval = DEADBEEF; 04417 init_level = PAPI_NOT_INITED; 04418 _papi_mem_cleanup_all( ); 04419 } 04420 04469 char * 04470 PAPI_strerror( int errorCode ) 04471 { 04472 if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) 04473 return ( NULL ); 04474 04475 return ( _papi_errlist[-errorCode] ); 04476 } 04477 04519 void 04520 PAPI_perror( char *msg ) 04521 { 04522 char *foo; 04523 04524 foo = PAPI_strerror( _papi_hwi_errno ); 04525 if ( foo == NULL ) 04526 return; 04527 04528 if ( msg ) 04529 if ( *msg ) 04530 fprintf( stderr, "%s: ", msg ); 04531 04532 fprintf( stderr, "%s\n", foo ); 04533 } 04534 04654 int 04655 PAPI_overflow( int EventSet, int EventCode, int threshold, int flags, 04656 PAPI_overflow_handler_t handler ) 04657 { 04658 int retval, cidx, index, i; 04659 EventSetInfo_t *ESI; 04660 04661 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04662 if ( ESI == NULL ) { 04663 OVFDBG("No EventSet\n"); 04664 papi_return( PAPI_ENOEVST ); 04665 } 04666 04667 cidx = valid_ESI_component( ESI ); 04668 if ( cidx < 0 ) { 04669 OVFDBG("Component Error\n"); 04670 papi_return( cidx ); 04671 } 04672 04673 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04674 OVFDBG("Already running\n"); 04675 papi_return( PAPI_EISRUN ); 04676 } 04677 04678 if ( ESI->state & PAPI_ATTACHED ) { 04679 OVFDBG("Attached\n"); 04680 papi_return( PAPI_EINVAL ); 04681 } 04682 04683 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04684 OVFDBG("CPU attached\n"); 04685 papi_return( PAPI_EINVAL ); 04686 } 04687 04688 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04689 ( unsigned int ) EventCode ) ) < 0 ) { 04690 papi_return( PAPI_ENOEVNT ); 04691 } 04692 04693 if ( threshold < 0 ) { 04694 OVFDBG("Threshold below zero\n"); 04695 papi_return( PAPI_EINVAL ); 04696 } 04697 04698 /* We do not support derived events in overflow */ 04699 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04700 04701 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && threshold != 0 && 04702 ( ESI->EventInfoArray[index].derived ) && 04703 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) ) { 04704 OVFDBG("Derived event in overflow\n"); 04705 papi_return( PAPI_EINVAL ); 04706 } 04707 04708 /* the first time to call PAPI_overflow function */ 04709 04710 if ( !( ESI->state & PAPI_OVERFLOWING ) ) { 04711 if ( handler == NULL ) { 04712 OVFDBG("NULL handler\n"); 04713 papi_return( PAPI_EINVAL ); 04714 } 04715 if ( threshold == 0 ) { 04716 OVFDBG("Zero threshold\n"); 04717 papi_return( PAPI_EINVAL ); 04718 } 04719 } 04720 if ( threshold > 0 && 04721 ESI->overflow.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs ) 04722 papi_return( PAPI_ECNFLCT ); 04723 04724 if ( threshold == 0 ) { 04725 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04726 if ( ESI->overflow.EventCode[i] == EventCode ) 04727 break; 04728 } 04729 /* EventCode not found */ 04730 if ( i == ESI->overflow.event_counter ) 04731 papi_return( PAPI_EINVAL ); 04732 /* compact these arrays */ 04733 while ( i < ESI->overflow.event_counter - 1 ) { 04734 ESI->overflow.deadline[i] = ESI->overflow.deadline[i + 1]; 04735 ESI->overflow.threshold[i] = ESI->overflow.threshold[i + 1]; 04736 ESI->overflow.EventIndex[i] = ESI->overflow.EventIndex[i + 1]; 04737 ESI->overflow.EventCode[i] = ESI->overflow.EventCode[i + 1]; 04738 i++; 04739 } 04740 ESI->overflow.deadline[i] = 0; 04741 ESI->overflow.threshold[i] = 0; 04742 ESI->overflow.EventIndex[i] = 0; 04743 ESI->overflow.EventCode[i] = 0; 04744 ESI->overflow.event_counter--; 04745 } else { 04746 if ( ESI->overflow.event_counter > 0 ) { 04747 if ( ( flags & PAPI_OVERFLOW_FORCE_SW ) && 04748 ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) 04749 papi_return( PAPI_ECNFLCT ); 04750 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && 04751 ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) 04752 papi_return( PAPI_ECNFLCT ); 04753 } 04754 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04755 if ( ESI->overflow.EventCode[i] == EventCode ) 04756 break; 04757 } 04758 /* A new entry */ 04759 if ( i == ESI->overflow.event_counter ) { 04760 ESI->overflow.EventCode[i] = EventCode; 04761 ESI->overflow.event_counter++; 04762 } 04763 /* New or existing entry */ 04764 ESI->overflow.deadline[i] = threshold; 04765 ESI->overflow.threshold[i] = threshold; 04766 ESI->overflow.EventIndex[i] = index; 04767 ESI->overflow.flags = flags; 04768 04769 } 04770 04771 /* If overflowing is already active, we should check to 04772 make sure that we don't specify a different handler 04773 or different flags here. You can't mix them. */ 04774 04775 ESI->overflow.handler = handler; 04776 04777 /* Set up the option structure for the low level. 04778 If we have hardware interrupts and we are not using 04779 forced software emulated interrupts */ 04780 04781 if ( _papi_hwd[cidx]->cmp_info.hardware_intr && 04782 !( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) { 04783 retval = _papi_hwd[cidx]->set_overflow( ESI, index, threshold ); 04784 if ( retval == PAPI_OK ) 04785 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 04786 else { 04787 papi_return( retval ); /* We should undo stuff here */ 04788 } 04789 } else { 04790 /* Make sure hardware overflow is not set */ 04791 ESI->overflow.flags &= ~( PAPI_OVERFLOW_HARDWARE ); 04792 } 04793 04794 APIDBG( "Overflow using: %s\n", 04795 ( ESI->overflow. 04796 flags & PAPI_OVERFLOW_HARDWARE ? "[Hardware]" : ESI->overflow. 04797 flags & PAPI_OVERFLOW_FORCE_SW ? "[Forced Software]" : 04798 "[Software]" ) ); 04799 04800 /* Toggle the overflow flags and ESI state */ 04801 04802 if ( ESI->overflow.event_counter >= 1 ) 04803 ESI->state |= PAPI_OVERFLOWING; 04804 else { 04805 ESI->state ^= PAPI_OVERFLOWING; 04806 ESI->overflow.flags = 0; 04807 ESI->overflow.handler = NULL; 04808 } 04809 04810 return PAPI_OK; 04811 } 04812 04909 int 04910 PAPI_sprofil( PAPI_sprofil_t *prof, int profcnt, int EventSet, 04911 int EventCode, int threshold, int flags ) 04912 { 04913 EventSetInfo_t *ESI; 04914 int retval, index, i, buckets; 04915 int forceSW = 0; 04916 int cidx; 04917 04918 /* Check to make sure EventSet exists */ 04919 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04920 if ( ESI == NULL ) { 04921 papi_return( PAPI_ENOEVST ); 04922 } 04923 04924 /* Check to make sure EventSet is stopped */ 04925 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04926 papi_return( PAPI_EISRUN ); 04927 } 04928 04929 /* We cannot profile if attached */ 04930 if ( ESI->state & PAPI_ATTACHED ) { 04931 papi_return( PAPI_EINVAL ); 04932 } 04933 04934 /* We cannot profile if cpu attached */ 04935 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04936 papi_return( PAPI_EINVAL ); 04937 } 04938 04939 /* Get component for EventSet */ 04940 cidx = valid_ESI_component( ESI ); 04941 if ( cidx < 0 ) { 04942 papi_return( cidx ); 04943 } 04944 04945 /* Get index of the Event we want to profile */ 04946 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04947 (unsigned int) EventCode ) ) < 0 ) { 04948 papi_return( PAPI_ENOEVNT ); 04949 } 04950 04951 /* We do not support derived events in overflow */ 04952 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04953 if ( ( ESI->EventInfoArray[index].derived ) && 04954 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) && 04955 !( flags & PAPI_PROFIL_FORCE_SW ) ) { 04956 papi_return( PAPI_EINVAL ); 04957 } 04958 04959 /* If no prof structures, then make sure count is 0 */ 04960 if ( prof == NULL ) { 04961 profcnt = 0; 04962 } 04963 04964 /* check all profile regions for valid scale factors of: 04965 2 (131072/65536), 04966 1 (65536/65536), 04967 or < 1 (65535 -> 2) as defined in unix profil() 04968 2/65536 is reserved for single bucket profiling 04969 {0,1}/65536 are traditionally used to terminate profiling 04970 but are unused here since PAPI uses threshold instead 04971 */ 04972 for( i = 0; i < profcnt; i++ ) { 04973 if ( !( ( prof[i].pr_scale == 131072 ) || 04974 ( ( prof[i].pr_scale <= 65536 && prof[i].pr_scale > 1 ) ) ) ) { 04975 APIDBG( "Improper scale factor: %d\n", prof[i].pr_scale ); 04976 papi_return( PAPI_EINVAL ); 04977 } 04978 } 04979 04980 /* Make sure threshold is valid */ 04981 if ( threshold < 0 ) { 04982 papi_return( PAPI_EINVAL ); 04983 } 04984 04985 /* the first time to call PAPI_sprofil */ 04986 if ( !( ESI->state & PAPI_PROFILING ) ) { 04987 if ( threshold == 0 ) { 04988 papi_return( PAPI_EINVAL ); 04989 } 04990 } 04991 04992 /* ??? */ 04993 if ( (threshold > 0) && 04994 (ESI->profile.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs) ) { 04995 papi_return( PAPI_ECNFLCT ); 04996 } 04997 04998 if ( threshold == 0 ) { 04999 for( i = 0; i < ESI->profile.event_counter; i++ ) { 05000 if ( ESI->profile.EventCode[i] == EventCode ) { 05001 break; 05002 } 05003 } 05004 05005 /* EventCode not found */ 05006 if ( i == ESI->profile.event_counter ) { 05007 papi_return( PAPI_EINVAL ); 05008 } 05009 05010 /* compact these arrays */ 05011 while ( i < ESI->profile.event_counter - 1 ) { 05012 ESI->profile.prof[i] = ESI->profile.prof[i + 1]; 05013 ESI->profile.count[i] = ESI->profile.count[i + 1]; 05014 ESI->profile.threshold[i] = ESI->profile.threshold[i + 1]; 05015 ESI->profile.EventIndex[i] = ESI->profile.EventIndex[i + 1]; 05016 ESI->profile.EventCode[i] = ESI->profile.EventCode[i + 1]; 05017 i++; 05018 } 05019 ESI->profile.prof[i] = NULL; 05020 ESI->profile.count[i] = 0; 05021 ESI->profile.threshold[i] = 0; 05022 ESI->profile.EventIndex[i] = 0; 05023 ESI->profile.EventCode[i] = 0; 05024 ESI->profile.event_counter--; 05025 } else { 05026 if ( ESI->profile.event_counter > 0 ) { 05027 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05028 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05029 papi_return( PAPI_ECNFLCT ); 05030 } 05031 if ( !( flags & PAPI_PROFIL_FORCE_SW ) && 05032 ( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05033 papi_return( PAPI_ECNFLCT ); 05034 } 05035 } 05036 05037 for( i = 0; i < ESI->profile.event_counter; i++ ) { 05038 if ( ESI->profile.EventCode[i] == EventCode ) { 05039 break; 05040 } 05041 } 05042 05043 if ( i == ESI->profile.event_counter ) { 05044 i = ESI->profile.event_counter; 05045 ESI->profile.event_counter++; 05046 ESI->profile.EventCode[i] = EventCode; 05047 } 05048 ESI->profile.prof[i] = prof; 05049 ESI->profile.count[i] = profcnt; 05050 ESI->profile.threshold[i] = threshold; 05051 ESI->profile.EventIndex[i] = index; 05052 } 05053 05054 APIDBG( "Profile event counter is %d\n", ESI->profile.event_counter ); 05055 05056 /* Clear out old flags */ 05057 if ( threshold == 0 ) { 05058 flags |= ESI->profile.flags; 05059 } 05060 05061 /* make sure no invalid flags are set */ 05062 if ( flags & 05063 ~( PAPI_PROFIL_POSIX | PAPI_PROFIL_RANDOM | PAPI_PROFIL_WEIGHTED | 05064 PAPI_PROFIL_COMPRESS | PAPI_PROFIL_BUCKETS | PAPI_PROFIL_FORCE_SW | 05065 PAPI_PROFIL_INST_EAR | PAPI_PROFIL_DATA_EAR ) ) { 05066 papi_return( PAPI_EINVAL ); 05067 } 05068 05069 /* if we have kernel-based profiling, then we're just asking for 05070 signals on interrupt. */ 05071 /* if we don't have kernel-based profiling, then we're asking for 05072 emulated PMU interrupt */ 05073 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05074 ( _papi_hwd[cidx]->cmp_info.kernel_profile == 0 ) ) { 05075 forceSW = PAPI_OVERFLOW_FORCE_SW; 05076 } 05077 05078 /* make sure one and only one bucket size is set */ 05079 buckets = flags & PAPI_PROFIL_BUCKETS; 05080 if ( !buckets ) { 05081 flags |= PAPI_PROFIL_BUCKET_16; /* default to 16 bit if nothing set */ 05082 } 05083 else { 05084 /* return error if more than one set */ 05085 if ( !( ( buckets == PAPI_PROFIL_BUCKET_16 ) || 05086 ( buckets == PAPI_PROFIL_BUCKET_32 ) || 05087 ( buckets == PAPI_PROFIL_BUCKET_64 ) ) ) { 05088 papi_return( PAPI_EINVAL ); 05089 } 05090 } 05091 05092 /* Set up the option structure for the low level */ 05093 ESI->profile.flags = flags; 05094 05095 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 05096 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05097 retval = _papi_hwd[cidx]->set_profile( ESI, index, threshold ); 05098 if ( ( retval == PAPI_OK ) && ( threshold > 0 ) ) { 05099 /* We need overflowing because we use the overflow dispatch handler */ 05100 ESI->state |= PAPI_OVERFLOWING; 05101 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 05102 } 05103 } else { 05104 retval = PAPI_overflow( EventSet, EventCode, threshold, forceSW, 05105 _papi_hwi_dummy_handler ); 05106 } 05107 05108 if ( retval < PAPI_OK ) { 05109 papi_return( retval ); /* We should undo stuff here */ 05110 } 05111 05112 /* Toggle the profiling flags and ESI state */ 05113 05114 if ( ESI->profile.event_counter >= 1 ) { 05115 ESI->state |= PAPI_PROFILING; 05116 } 05117 else { 05118 ESI->state ^= PAPI_PROFILING; 05119 ESI->profile.flags = 0; 05120 } 05121 05122 return PAPI_OK; 05123 } 05124 05302 int 05303 PAPI_profil( void *buf, unsigned bufsiz, caddr_t offset, 05304 unsigned scale, int EventSet, int EventCode, int threshold, 05305 int flags ) 05306 { 05307 EventSetInfo_t *ESI; 05308 int i; 05309 int retval; 05310 05311 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05312 if ( ESI == NULL ) 05313 papi_return( PAPI_ENOEVST ); 05314 05315 /* scale factors are checked for validity in PAPI_sprofil */ 05316 05317 if ( threshold > 0 ) { 05318 PAPI_sprofil_t *prof; 05319 05320 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05321 if ( ESI->profile.EventCode[i] == EventCode ) 05322 break; 05323 } 05324 05325 if ( i == ESI->profile.event_counter ) { 05326 prof = 05327 ( PAPI_sprofil_t * ) papi_malloc( sizeof ( PAPI_sprofil_t ) ); 05328 memset( prof, 0x0, sizeof ( PAPI_sprofil_t ) ); 05329 prof->pr_base = buf; 05330 prof->pr_size = bufsiz; 05331 prof->pr_off = offset; 05332 prof->pr_scale = scale; 05333 05334 retval = 05335 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05336 05337 if ( retval != PAPI_OK ) 05338 papi_free( prof ); 05339 } else { 05340 prof = ESI->profile.prof[i]; 05341 prof->pr_base = buf; 05342 prof->pr_size = bufsiz; 05343 prof->pr_off = offset; 05344 prof->pr_scale = scale; 05345 retval = 05346 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05347 } 05348 papi_return( retval ); 05349 } 05350 05351 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05352 if ( ESI->profile.EventCode[i] == EventCode ) 05353 break; 05354 } 05355 /* EventCode not found */ 05356 if ( i == ESI->profile.event_counter ) 05357 papi_return( PAPI_EINVAL ); 05358 05359 papi_free( ESI->profile.prof[i] ); 05360 ESI->profile.prof[i] = NULL; 05361 05362 papi_return( PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, flags ) ); 05363 } 05364 05365 /* This function sets the low level default granularity 05366 for all newly manufactured eventsets. The first function 05367 preserves API compatibility and assumes component 0; 05368 The second function takes a component argument. */ 05369 05420 int 05421 PAPI_set_granularity( int granularity ) 05422 { 05423 return ( PAPI_set_cmp_granularity( granularity, 0 ) ); 05424 } 05425 05485 int 05486 PAPI_set_cmp_granularity( int granularity, int cidx ) 05487 { 05488 PAPI_option_t ptr; 05489 05490 memset( &ptr, 0, sizeof ( ptr ) ); 05491 ptr.defgranularity.def_cidx = cidx; 05492 ptr.defgranularity.granularity = granularity; 05493 papi_return( PAPI_set_opt( PAPI_DEFGRN, &ptr ) ); 05494 } 05495 05496 /* This function sets the low level default counting domain 05497 for all newly manufactured eventsets. The first function 05498 preserves API compatibility and assumes component 0; 05499 The second function takes a component argument. */ 05500 05551 int 05552 PAPI_set_domain( int domain ) 05553 { 05554 return ( PAPI_set_cmp_domain( domain, 0 ) ); 05555 } 05556 05621 int 05622 PAPI_set_cmp_domain( int domain, int cidx ) 05623 { 05624 PAPI_option_t ptr; 05625 05626 memset( &ptr, 0, sizeof ( ptr ) ); 05627 ptr.defdomain.def_cidx = cidx; 05628 ptr.defdomain.domain = domain; 05629 papi_return( PAPI_set_opt( PAPI_DEFDOM, &ptr ) ); 05630 } 05631 05706 int 05707 PAPI_add_events( int EventSet, int *Events, int number ) 05708 { 05709 int i, retval; 05710 05711 if ( ( Events == NULL ) || ( number <= 0 ) ) 05712 papi_return( PAPI_EINVAL ); 05713 05714 for ( i = 0; i < number; i++ ) { 05715 retval = PAPI_add_event( EventSet, Events[i] ); 05716 if ( retval != PAPI_OK ) { 05717 if ( i == 0 ) 05718 papi_return( retval ); 05719 else 05720 return ( i ); 05721 } 05722 } 05723 return ( PAPI_OK ); 05724 } 05725 05793 int 05794 PAPI_remove_events( int EventSet, int *Events, int number ) 05795 { 05796 int i, retval; 05797 05798 if ( ( Events == NULL ) || ( number <= 0 ) ) 05799 papi_return( PAPI_EINVAL ); 05800 05801 for ( i = 0; i < number; i++ ) { 05802 retval = PAPI_remove_event( EventSet, Events[i] ); 05803 if ( retval != PAPI_OK ) { 05804 if ( i == 0 ) 05805 papi_return( retval ); 05806 else 05807 return ( i ); 05808 } 05809 } 05810 return ( PAPI_OK ); 05811 } 05812 05862 int 05863 PAPI_list_events( int EventSet, int *Events, int *number ) 05864 { 05865 EventSetInfo_t *ESI; 05866 int i, j; 05867 05868 if ( *number < 0 ) 05869 papi_return( PAPI_EINVAL ); 05870 05871 if ( ( Events == NULL ) && ( *number > 0 ) ) 05872 papi_return( PAPI_EINVAL ); 05873 05874 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05875 if ( !ESI ) 05876 papi_return( PAPI_ENOEVST ); 05877 05878 if ( ( Events == NULL ) || ( *number == 0 ) ) { 05879 *number = ESI->NumberOfEvents; 05880 papi_return( PAPI_OK ); 05881 } 05882 05883 for ( i = 0, j = 0; j < ESI->NumberOfEvents; i++ ) { 05884 if ( ( int ) ESI->EventInfoArray[i].event_code != PAPI_NULL ) { 05885 Events[j] = ( int ) ESI->EventInfoArray[i].event_code; 05886 j++; 05887 if ( j == *number ) 05888 break; 05889 } 05890 } 05891 05892 *number = j; 05893 05894 return ( PAPI_OK ); 05895 } 05896 05897 /* xxx This is OS dependent, not component dependent, right? */ 05923 int 05924 PAPI_get_dmem_info( PAPI_dmem_info_t * dest ) 05925 { 05926 if ( dest == NULL ) 05927 return PAPI_EINVAL; 05928 05929 memset( ( void * ) dest, 0x0, sizeof ( PAPI_dmem_info_t ) ); 05930 return ( _papi_os_vector.get_dmem_info( dest ) ); 05931 } 05932 05933 05974 const PAPI_exe_info_t * 05975 PAPI_get_executable_info( void ) 05976 { 05977 PAPI_option_t ptr; 05978 int retval; 05979 05980 memset( &ptr, 0, sizeof ( ptr ) ); 05981 retval = PAPI_get_opt( PAPI_EXEINFO, &ptr ); 05982 if ( retval == PAPI_OK ) 05983 return ( ptr.exe_info ); 05984 else 05985 return ( NULL ); 05986 } 05987 06004 const PAPI_shlib_info_t * 06005 PAPI_get_shared_lib_info( void ) 06006 { 06007 PAPI_option_t ptr; 06008 int retval; 06009 06010 memset( &ptr, 0, sizeof ( ptr ) ); 06011 retval = PAPI_get_opt( PAPI_SHLIBINFO, &ptr ); 06012 if ( retval == PAPI_OK ) 06013 return ( ptr.shlib_info ); 06014 else 06015 return ( NULL ); 06016 } 06045 const PAPI_hw_info_t * 06046 PAPI_get_hardware_info( void ) 06047 { 06048 PAPI_option_t ptr; 06049 int retval; 06050 06051 memset( &ptr, 0, sizeof ( ptr ) ); 06052 retval = PAPI_get_opt( PAPI_HWINFO, &ptr ); 06053 if ( retval == PAPI_OK ) 06054 return ( ptr.hw_info ); 06055 else 06056 return ( NULL ); 06057 } 06058 06059 06060 /* The next 4 timing functions always use component 0 */ 06061 06077 long long 06078 PAPI_get_real_cyc( void ) 06079 { 06080 return ( _papi_os_vector.get_real_cycles( ) ); 06081 } 06082 06096 /* FIXME */ 06097 long long 06098 PAPI_get_real_nsec( void ) 06099 { 06100 return ( ( _papi_os_vector.get_real_nsec( ))); 06101 06102 } 06103 06124 long long 06125 PAPI_get_real_usec( void ) 06126 { 06127 return ( _papi_os_vector.get_real_usec( ) ); 06128 } 06129 06160 long long 06161 PAPI_get_virt_cyc( void ) 06162 { 06163 06164 return ( ( long long ) _papi_os_vector.get_virt_cycles( ) ); 06165 } 06166 06190 long long 06191 PAPI_get_virt_nsec( void ) 06192 { 06193 06194 return ( ( _papi_os_vector.get_virt_nsec())); 06195 06196 } 06197 06232 long long 06233 PAPI_get_virt_usec( void ) 06234 { 06235 06236 return ( ( long long ) _papi_os_vector.get_virt_usec() ); 06237 } 06238 06261 int 06262 PAPI_lock( int lck ) 06263 { 06264 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06265 papi_return( PAPI_EINVAL ); 06266 06267 papi_return( _papi_hwi_lock( lck ) ); 06268 } 06269 06281 int 06282 PAPI_unlock( int lck ) 06283 { 06284 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06285 papi_return( PAPI_EINVAL ); 06286 06287 papi_return( _papi_hwi_unlock( lck ) ); 06288 } 06289 06323 int 06324 PAPI_is_initialized( void ) 06325 { 06326 return ( init_level ); 06327 } 06328 06329 /* This function maps the overflow_vector to event indexes in the event 06330 set, so that user can know which PAPI event overflowed. 06331 int *array---- an array of event indexes in eventset; the first index 06332 maps to the highest set bit in overflow_vector 06333 int *number--- this is an input/output parameter, user should put the 06334 size of the array into this parameter, after the function 06335 is executed, the number of indexes in *array is written 06336 to this parameter 06337 */ 06338 06377 int 06378 PAPI_get_overflow_event_index( int EventSet, long long overflow_vector, 06379 int *array, int *number ) 06380 { 06381 EventSetInfo_t *ESI; 06382 int set_bit, j, pos; 06383 int count = 0, k; 06384 06385 if ( overflow_vector == ( long long ) 0 ) 06386 papi_return( PAPI_EINVAL ); 06387 06388 if ( ( array == NULL ) || ( number == NULL ) ) 06389 papi_return( PAPI_EINVAL ); 06390 06391 if ( *number < 1 ) 06392 papi_return( PAPI_EINVAL ); 06393 06394 ESI = _papi_hwi_lookup_EventSet( EventSet ); 06395 if ( ESI == NULL ) 06396 papi_return( PAPI_ENOEVST ); 06397 06398 /* in case the eventset is empty */ 06399 if ( ESI->NumberOfEvents == 0 ) 06400 papi_return( PAPI_EINVAL ); 06401 06402 while ( ( set_bit = ffsll( overflow_vector ) ) ) { 06403 set_bit -= 1; 06404 overflow_vector ^= ( long long ) 1 << set_bit; 06405 for ( j = 0; j < ESI->NumberOfEvents; j++ ) { 06406 for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0; k++ ) { 06407 pos = ESI->EventInfoArray[j].pos[k]; 06408 if ( ( set_bit == pos ) && 06409 ( ( ESI->EventInfoArray[j].derived == NOT_DERIVED ) || 06410 ( ESI->EventInfoArray[j].derived == DERIVED_CMPD ) ) ) { 06411 array[count++] = j; 06412 if ( count == *number ) 06413 return PAPI_OK; 06414 06415 break; 06416 } 06417 } 06418 } 06419 } 06420 *number = count; 06421 return PAPI_OK; 06422 } 06423 06424 06442 int 06443 PAPI_get_event_component( int EventCode) 06444 { 06445 return _papi_hwi_component_index( EventCode); 06446 } 06447 06469 int PAPI_get_component_index(char *name) 06470 { 06471 int cidx; 06472 06473 const PAPI_component_info_t *cinfo; 06474 06475 for(cidx=0;cidx<papi_num_components;cidx++) { 06476 06477 cinfo=PAPI_get_component_info(cidx); 06478 if (cinfo==NULL) return PAPI_ENOCMP; 06479 06480 if (!strcmp(name,cinfo->name)) { 06481 return cidx; 06482 } 06483 } 06484 06485 return PAPI_ENOCMP; 06486 } 06487 06488 06523 int 06524 PAPI_disable_component( int cidx ) 06525 { 06526 06527 const PAPI_component_info_t *cinfo; 06528 06529 /* Can only run before PAPI_library_init() is called */ 06530 if (init_level != PAPI_NOT_INITED) { 06531 return PAPI_ENOINIT; 06532 } 06533 06534 cinfo=PAPI_get_component_info(cidx); 06535 if (cinfo==NULL) return PAPI_ENOCMP; 06536 06537 ((PAPI_component_info_t *)cinfo)->disabled=1; 06538 strcpy(((PAPI_component_info_t *)cinfo)->disabled_reason, 06539 "Disabled by PAPI_disable_component()"); 06540 06541 return PAPI_OK; 06542 06543 } 06544 06573 int 06574 PAPI_disable_component_by_name( char *name ) 06575 { 06576 int cidx; 06577 06578 /* I can only be called before init time */ 06579 if (init_level!=PAPI_NOT_INITED) { 06580 return PAPI_ENOINIT; 06581 } 06582 06583 cidx = PAPI_get_component_index(name); 06584 if (cidx>=0) { 06585 return PAPI_disable_component(cidx); 06586 } 06587 06588 return PAPI_ENOCMP; 06589 }