|
PAPI
5.1.0.2
|
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 "extras.h" 00037 #include "sw_multiplex.h" 00038 #include "papi_hl.h" 00039 00040 /*******************************/ 00041 /* BEGIN EXTERNAL DECLARATIONS */ 00042 /*******************************/ 00043 00044 00045 #ifdef DEBUG 00046 #define papi_return(a) do { \ 00047 int b = a; \ 00048 if (b != PAPI_OK) {\ 00049 _papi_hwi_errno = b;\ 00050 } \ 00051 return((_papi_hwi_debug_handler ? _papi_hwi_debug_handler(b) : b)); \ 00052 } while (0) 00053 #else 00054 #define papi_return(a) do { \ 00055 int b = a; \ 00056 if (b != PAPI_OK) {\ 00057 _papi_hwi_errno = b;\ 00058 } \ 00059 return(b);\ 00060 } while(0) 00061 #endif 00062 00063 00064 /* 00065 #ifdef DEBUG 00066 #define papi_return(a) return((_papi_hwi_debug_handler ? _papi_hwi_debug_handler(a) : a)) 00067 #else 00068 #define papi_return(a) return(a) 00069 #endif 00070 */ 00071 00072 #ifdef DEBUG 00073 int _papi_hwi_debug; 00074 #endif 00075 00076 00077 static int init_retval = DEADBEEF; 00078 00079 inline_static int 00080 valid_component( int cidx ) 00081 { 00082 if ( _papi_hwi_invalid_cmp( cidx ) ) 00083 return ( PAPI_ENOCMP ); 00084 return ( cidx ); 00085 } 00086 00087 inline_static int 00088 valid_ESI_component( EventSetInfo_t * ESI ) 00089 { 00090 return ( valid_component( ESI->CmpIdx ) ); 00091 } 00092 00116 int 00117 PAPI_thread_init( unsigned long int ( *id_fn ) ( void ) ) 00118 { 00119 /* Thread support not implemented on Alpha/OSF because the OSF pfm 00120 * counter device driver does not support per-thread counters. 00121 * When this is updated, we can remove this if statement 00122 */ 00123 if ( init_level == PAPI_NOT_INITED ) 00124 papi_return( PAPI_ENOINIT ); 00125 00126 if ( ( init_level & PAPI_THREAD_LEVEL_INITED ) ) 00127 papi_return( PAPI_OK ); 00128 00129 init_level |= PAPI_THREAD_LEVEL_INITED; 00130 papi_return( _papi_hwi_set_thread_id_fn( id_fn ) ); 00131 } 00132 00155 unsigned long 00156 PAPI_thread_id( void ) 00157 { 00158 if ( _papi_hwi_thread_id_fn != NULL ) 00159 return ( ( *_papi_hwi_thread_id_fn ) ( ) ); 00160 else 00161 #ifdef DEBUG 00162 if ( _papi_hwi_debug_handler ) 00163 return ( unsigned long ) _papi_hwi_debug_handler( PAPI_EMISC ); 00164 #endif 00165 return ( unsigned long ) PAPI_EMISC; 00166 } 00167 00168 /* Thread Functions */ 00169 00170 /* 00171 * Notify PAPI that a thread has 'appeared' 00172 * We lookup the thread, if it does not exist we create it 00173 */ 00174 00203 int 00204 PAPI_register_thread( void ) 00205 { 00206 ThreadInfo_t *thread; 00207 00208 if ( init_level == PAPI_NOT_INITED ) 00209 papi_return( PAPI_ENOINIT ); 00210 papi_return( _papi_hwi_lookup_or_create_thread( &thread, 0 ) ); 00211 } 00212 00213 /* 00214 * Notify PAPI that a thread has 'disappeared' 00215 * We lookup the thread, if it does not exist we return an error 00216 */ 00239 int 00240 PAPI_unregister_thread( void ) 00241 { 00242 ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 ); 00243 00244 if ( thread ) 00245 papi_return( _papi_hwi_shutdown_thread( thread ) ); 00246 00247 papi_return( PAPI_EMISC ); 00248 } 00249 00283 int 00284 PAPI_list_threads( PAPI_thread_id_t *tids, int *number ) 00285 { 00286 PAPI_all_thr_spec_t tmp; 00287 int retval; 00288 00289 /* If tids == NULL, then just count the threads, don't gather a list. */ 00290 /* If tids != NULL, then we need the length of the tids array in num. */ 00291 00292 if ( ( number == NULL ) || ( tids && ( *number <= 0 ) ) ) 00293 papi_return( PAPI_EINVAL ); 00294 00295 memset( &tmp, 0x0, sizeof ( tmp ) ); 00296 00297 /* data == NULL, since we don't want the thread specific pointers. */ 00298 /* tids may be NULL, if the user doesn't want the thread IDs. */ 00299 00300 tmp.num = *number; 00301 tmp.id = tids; 00302 tmp.data = NULL; 00303 00304 retval = _papi_hwi_gather_all_thrspec_data( 0, &tmp ); 00305 if ( retval == PAPI_OK ) 00306 *number = tmp.num; 00307 00308 papi_return( retval ); 00309 } 00310 00359 int 00360 PAPI_get_thr_specific( int tag, void **ptr ) 00361 { 00362 ThreadInfo_t *thread; 00363 int doall = 0, retval = PAPI_OK; 00364 00365 if ( init_level == PAPI_NOT_INITED ) 00366 papi_return( PAPI_ENOINIT ); 00367 if ( tag & PAPI_TLS_ALL_THREADS ) { 00368 tag = tag ^ PAPI_TLS_ALL_THREADS; 00369 doall = 1; 00370 } 00371 if ( ( tag < 0 ) || ( tag > PAPI_TLS_NUM ) ) 00372 papi_return( PAPI_EINVAL ); 00373 00374 if ( doall ) 00375 papi_return( _papi_hwi_gather_all_thrspec_data 00376 ( tag, ( PAPI_all_thr_spec_t * ) ptr ) ); 00377 00378 retval = _papi_hwi_lookup_or_create_thread( &thread, 0 ); 00379 if ( retval == PAPI_OK ) 00380 *ptr = thread->thread_storage[tag]; 00381 else 00382 papi_return( retval ); 00383 00384 return ( PAPI_OK ); 00385 } 00386 00435 int 00436 PAPI_set_thr_specific( int tag, void *ptr ) 00437 { 00438 ThreadInfo_t *thread; 00439 int retval = PAPI_OK; 00440 00441 if ( init_level == PAPI_NOT_INITED ) 00442 papi_return( PAPI_ENOINIT ); 00443 if ( ( tag < 0 ) || ( tag > PAPI_NUM_TLS ) ) 00444 papi_return( PAPI_EINVAL ); 00445 00446 retval = _papi_hwi_lookup_or_create_thread( &thread, 0 ); 00447 if ( retval == PAPI_OK ) { 00448 _papi_hwi_lock( THREADS_LOCK ); 00449 thread->thread_storage[tag] = ptr; 00450 _papi_hwi_unlock( THREADS_LOCK ); 00451 } 00452 else 00453 return ( retval ); 00454 00455 return ( PAPI_OK ); 00456 } 00457 00458 00497 int 00498 PAPI_library_init( int version ) 00499 { 00500 char *filename; 00501 int tmp = 0, tmpel; 00502 00503 /* This is a poor attempt at a lock. 00504 For 3.1 this should be replaced with a 00505 true UNIX semaphore. We cannot use PAPI 00506 locks here because they are not initialized yet */ 00507 static int _in_papi_library_init_cnt = 0; 00508 #ifdef DEBUG 00509 char *var; 00510 #endif 00511 _papi_hwi_init_errors(); 00512 00513 if ( version != PAPI_VER_CURRENT ) 00514 papi_return( PAPI_EINVAL ); 00515 00516 ++_in_papi_library_init_cnt; 00517 while ( _in_papi_library_init_cnt > 1 ) { 00518 PAPIERROR( "Multiple callers of PAPI_library_init" ); 00519 sleep( 1 ); 00520 } 00521 00522 /* This checks to see if we have forked or called init more than once. 00523 If we have forked, then we continue to init. If we have not forked, 00524 we check to see the status of initialization. */ 00525 00526 APIDBG( "Initializing library: current PID %d, old PID %d\n", 00527 getpid( ), _papi_hwi_system_info.pid ); 00528 00529 if ( _papi_hwi_system_info.pid == getpid( ) ) { 00530 /* If the magic environment variable PAPI_ALLOW_STOLEN is set, 00531 we call shutdown if PAPI has been initialized. This allows 00532 tools that use LD_PRELOAD to run on applications that use PAPI. 00533 In this circumstance, PAPI_ALLOW_STOLEN will be set to 'stolen' 00534 so the tool can check for this case. */ 00535 00536 if ( getenv( "PAPI_ALLOW_STOLEN" ) ) { 00537 char buf[PAPI_HUGE_STR_LEN]; 00538 if ( init_level != PAPI_NOT_INITED ) 00539 PAPI_shutdown( ); 00540 sprintf( buf, "%s=%s", "PAPI_ALLOW_STOLEN", "stolen" ); 00541 putenv( buf ); 00542 } 00543 00544 /* If the library has been successfully initialized *OR* 00545 the library attempted initialization but failed. */ 00546 00547 else if ( ( init_level != PAPI_NOT_INITED ) || 00548 ( init_retval != DEADBEEF ) ) { 00549 _in_papi_library_init_cnt--; 00550 if ( init_retval < PAPI_OK ) 00551 papi_return( init_retval ); 00552 else 00553 return ( init_retval ); 00554 } 00555 00556 APIDBG( "system_info was initialized, but init did not succeed\n" ); 00557 } 00558 #ifdef DEBUG 00559 var = ( char * ) getenv( "PAPI_DEBUG" ); 00560 _papi_hwi_debug = 0; 00561 00562 if ( var != NULL ) { 00563 if ( strlen( var ) != 0 ) { 00564 if ( strstr( var, "SUBSTRATE" ) ) 00565 _papi_hwi_debug |= DEBUG_SUBSTRATE; 00566 if ( strstr( var, "API" ) ) 00567 _papi_hwi_debug |= DEBUG_API; 00568 if ( strstr( var, "INTERNAL" ) ) 00569 _papi_hwi_debug |= DEBUG_INTERNAL; 00570 if ( strstr( var, "THREADS" ) ) 00571 _papi_hwi_debug |= DEBUG_THREADS; 00572 if ( strstr( var, "MULTIPLEX" ) ) 00573 _papi_hwi_debug |= DEBUG_MULTIPLEX; 00574 if ( strstr( var, "OVERFLOW" ) ) 00575 _papi_hwi_debug |= DEBUG_OVERFLOW; 00576 if ( strstr( var, "PROFILE" ) ) 00577 _papi_hwi_debug |= DEBUG_PROFILE; 00578 if ( strstr( var, "MEMORY" ) ) 00579 _papi_hwi_debug |= DEBUG_MEMORY; 00580 if ( strstr( var, "LEAK" ) ) 00581 _papi_hwi_debug |= DEBUG_LEAK; 00582 if ( strstr( var, "ALL" ) ) 00583 _papi_hwi_debug |= DEBUG_ALL; 00584 } 00585 00586 if ( _papi_hwi_debug == 0 ) 00587 _papi_hwi_debug |= DEBUG_API; 00588 } 00589 #endif 00590 00591 /* Be verbose for now */ 00592 00593 tmpel = _papi_hwi_error_level; 00594 _papi_hwi_error_level = PAPI_VERB_ECONT; 00595 00596 /* Initialize internal globals */ 00597 if ( _papi_hwi_init_global_internal( ) != PAPI_OK ) { 00598 _in_papi_library_init_cnt--; 00599 _papi_hwi_error_level = tmpel; 00600 papi_return( PAPI_EINVAL ); 00601 } 00602 00603 /* Initialize OS */ 00604 tmp = _papi_hwi_init_os(); 00605 if ( tmp ) { 00606 init_retval = tmp; 00607 _papi_hwi_shutdown_global_internal( ); 00608 _in_papi_library_init_cnt--; 00609 _papi_hwi_error_level = tmpel; 00610 papi_return( init_retval ); 00611 } 00612 00613 /* Initialize component globals */ 00614 00615 tmp = _papi_hwi_init_global( ); 00616 if ( tmp ) { 00617 init_retval = tmp; 00618 _papi_hwi_shutdown_global_internal( ); 00619 _in_papi_library_init_cnt--; 00620 _papi_hwi_error_level = tmpel; 00621 papi_return( init_retval ); 00622 } 00623 00624 /* Initialize thread globals, including the main threads */ 00625 00626 tmp = _papi_hwi_init_global_threads( ); 00627 if ( tmp ) { 00628 int i; 00629 init_retval = tmp; 00630 _papi_hwi_shutdown_global_internal( ); 00631 for ( i = 0; i < papi_num_components; i++ ) { 00632 if (!_papi_hwd[i]->cmp_info.disabled) { 00633 _papi_hwd[i]->shutdown_component( ); 00634 } 00635 } 00636 _in_papi_library_init_cnt--; 00637 _papi_hwi_error_level = tmpel; 00638 papi_return( init_retval ); 00639 } 00640 00641 init_level = PAPI_LOW_LEVEL_INITED; 00642 _in_papi_library_init_cnt--; 00643 _papi_hwi_error_level = tmpel; 00644 00645 #ifdef STATIC_USER_EVENTS 00646 _papi_user_defined_events_setup(NULL); 00647 #endif 00648 00649 if ( (filename = getenv( "PAPI_USER_EVENTS_FILE" )) != NULL ) { 00650 _papi_user_defined_events_setup(filename); 00651 } 00652 00653 return ( init_retval = PAPI_VER_CURRENT ); 00654 } 00655 00699 int 00700 PAPI_query_event( int EventCode ) 00701 { 00702 if ( IS_PRESET(EventCode) ) { 00703 EventCode &= PAPI_PRESET_AND_MASK; 00704 if ( EventCode >= PAPI_MAX_PRESET_EVENTS ) 00705 papi_return( PAPI_ENOTPRESET ); 00706 00707 if ( _papi_hwi_presets[EventCode].count ) 00708 papi_return (PAPI_OK); 00709 else 00710 return PAPI_ENOEVNT; 00711 } 00712 00713 if ( IS_NATIVE(EventCode) ) { 00714 papi_return( _papi_hwi_query_native_event 00715 ( ( unsigned int ) EventCode ) ); 00716 } 00717 00718 if ( IS_USER_DEFINED(EventCode) ) { 00719 EventCode &= PAPI_UE_AND_MASK; 00720 if ( EventCode < 0 || EventCode > (int)_papi_user_events_count) 00721 return ( PAPI_EINVAL ); 00722 00723 papi_return( PAPI_OK ); 00724 } 00725 00726 papi_return( PAPI_ENOEVNT ); 00727 } 00728 00769 int 00770 PAPI_query_named_event( char *EventName ) 00771 { 00772 int ret, code; 00773 00774 ret = PAPI_event_name_to_code( EventName, &code ); 00775 if ( ret == PAPI_OK ) ret = PAPI_query_event( code ); 00776 papi_return( ret); 00777 } 00778 00779 00809 const PAPI_component_info_t * 00810 PAPI_get_component_info( int cidx ) 00811 { 00812 if ( _papi_hwi_invalid_cmp( cidx ) ) 00813 return ( NULL ); 00814 else 00815 return ( &( _papi_hwd[cidx]->cmp_info ) ); 00816 } 00817 00818 /* PAPI_get_event_info: 00819 tests input EventCode and returns a filled in PAPI_event_info_t 00820 structure containing descriptive strings and values for the 00821 specified event. Handles both preset and native events by 00822 calling either _papi_hwi_get_event_info or 00823 _papi_hwi_get_native_event_info. 00824 */ 00847 int 00848 PAPI_get_event_info( int EventCode, PAPI_event_info_t *info ) 00849 { 00850 int i; 00851 00852 if ( info == NULL ) 00853 papi_return( PAPI_EINVAL ); 00854 00855 if ( IS_PRESET(EventCode) ) { 00856 i = EventCode & PAPI_PRESET_AND_MASK; 00857 if ( i >= PAPI_MAX_PRESET_EVENTS ) 00858 papi_return( PAPI_ENOTPRESET ); 00859 papi_return( _papi_hwi_get_preset_event_info( EventCode, info ) ); 00860 } 00861 00862 if ( IS_NATIVE(EventCode) ) { 00863 papi_return( _papi_hwi_get_native_event_info 00864 ( ( unsigned int ) EventCode, info ) ); 00865 } 00866 00867 if ( IS_USER_DEFINED(EventCode) ) { 00868 papi_return( PAPI_OK ); 00869 } 00870 papi_return( PAPI_ENOTPRESET ); 00871 } 00872 00873 00925 int 00926 PAPI_event_code_to_name( int EventCode, char *out ) 00927 { 00928 if ( out == NULL ) 00929 papi_return( PAPI_EINVAL ); 00930 00931 if ( IS_PRESET(EventCode) ) { 00932 EventCode &= PAPI_PRESET_AND_MASK; 00933 if ( ( EventCode >= PAPI_MAX_PRESET_EVENTS ) 00934 || ( _papi_hwi_presets[EventCode].symbol == NULL ) ) 00935 papi_return( PAPI_ENOTPRESET ); 00936 00937 strncpy( out, _papi_hwi_presets[EventCode].symbol, 00938 PAPI_MAX_STR_LEN ); 00939 papi_return( PAPI_OK ); 00940 } 00941 00942 if ( IS_NATIVE(EventCode) ) { 00943 return ( _papi_hwi_native_code_to_name 00944 ( ( unsigned int ) EventCode, out, PAPI_MAX_STR_LEN ) ); 00945 } 00946 00947 if ( IS_USER_DEFINED(EventCode) ) { 00948 EventCode &= PAPI_UE_AND_MASK; 00949 00950 if ( EventCode < 0 || EventCode > (int)_papi_user_events_count ) 00951 papi_return( PAPI_EINVAL ); 00952 00953 strncpy( out, _papi_user_events[EventCode].symbol, 00954 PAPI_MIN_STR_LEN); 00955 papi_return( PAPI_OK ); 00956 } 00957 00958 papi_return( PAPI_ENOEVNT ); 00959 } 00960 01012 int 01013 PAPI_event_name_to_code( char *in, int *out ) 01014 { 01015 APIDBG("Entry: in: %p, name: %s, out: %p\n", in, in, out); 01016 int i; 01017 01018 if ( ( in == NULL ) || ( out == NULL ) ) 01019 papi_return( PAPI_EINVAL ); 01020 01021 if ( init_level == PAPI_NOT_INITED ) 01022 papi_return( PAPI_ENOINIT ); 01023 01024 /* All presets start with "PAPI_" so no need to */ 01025 /* do an exhaustive search if that's not there */ 01026 if (strncmp(in, "PAPI_", 5) == 0) { 01027 for(i = 0; i < PAPI_MAX_PRESET_EVENTS; i++ ) { 01028 if ( ( _papi_hwi_presets[i].symbol ) 01029 && ( strcasecmp( _papi_hwi_presets[i].symbol, in ) == 0) ) { 01030 *out = ( int ) ( i | PAPI_PRESET_MASK ); 01031 papi_return( PAPI_OK ); 01032 } 01033 } 01034 } 01035 01036 for ( i=0; i < (int)_papi_user_events_count; i++ ) { 01037 if ( strcasecmp( _papi_user_events[i].symbol, in ) == 0 ) { 01038 *out = (int) ( i | PAPI_UE_MASK ); 01039 papi_return( PAPI_OK ); 01040 } 01041 } 01042 01043 papi_return( _papi_hwi_native_name_to_code( in, out ) ); 01044 } 01045 01046 /* Updates EventCode to next valid value, or returns error; 01047 modifier can specify {all / available} for presets, or other values for native tables 01048 and may be platform specific (Major groups / all mask bits; P / M / E chip, etc) */ 01049 01155 int 01156 PAPI_enum_event( int *EventCode, int modifier ) 01157 { 01158 int i = *EventCode; 01159 int retval; 01160 int cidx; 01161 int event_code; 01162 01163 cidx = _papi_hwi_component_index( *EventCode ); 01164 if (cidx < 0) return PAPI_ENOCMP; 01165 01166 /* Do we handle presets in componets other than CPU? */ 01167 /* if (( IS_PRESET(i) ) && cidx > 0 )) return PAPI_ENOCMP; */ 01168 01169 if ( IS_PRESET(i) ) { 01170 if ( modifier == PAPI_ENUM_FIRST ) { 01171 *EventCode = ( int ) PAPI_PRESET_MASK; 01172 return ( PAPI_OK ); 01173 } 01174 i &= PAPI_PRESET_AND_MASK; 01175 while ( ++i < PAPI_MAX_PRESET_EVENTS ) { 01176 if ( _papi_hwi_presets[i].symbol == NULL ) 01177 return ( PAPI_ENOEVNT ); /* NULL pointer terminates list */ 01178 if ( modifier & PAPI_PRESET_ENUM_AVAIL ) { 01179 if ( _papi_hwi_presets[i].count == 0 ) 01180 continue; 01181 } 01182 *EventCode = ( int ) ( i | PAPI_PRESET_MASK ); 01183 return ( PAPI_OK ); 01184 } 01185 } else if ( IS_NATIVE(i) ) { 01186 /* Should check against num native events here */ 01187 01188 event_code=_papi_hwi_eventcode_to_native((int)*EventCode); 01189 retval = _papi_hwd[cidx]->ntv_enum_events((unsigned int *)&event_code, modifier ); 01190 01191 /* re-apply Component ID to the returned Event */ 01192 *EventCode = _papi_hwi_native_to_eventcode(cidx,event_code); 01193 01194 return retval; 01195 } else if ( IS_USER_DEFINED(i) ) { 01196 if ( modifier == PAPI_ENUM_FIRST ) { 01197 *EventCode = (int) 0x0; 01198 return ( PAPI_OK ); 01199 } 01200 01201 i &= PAPI_UE_AND_MASK; 01202 ++i; 01203 01204 if ( (int)_papi_user_events_count <= i ) 01205 *EventCode = i; 01206 return ( PAPI_OK ); 01207 } 01208 01209 papi_return( PAPI_EINVAL ); 01210 } 01211 01212 01320 int 01321 PAPI_enum_cmp_event( int *EventCode, int modifier, int cidx ) 01322 { 01323 int i = *EventCode; 01324 int retval; 01325 int event_code; 01326 01327 if ( _papi_hwi_invalid_cmp(cidx) || ( (IS_PRESET(i)) && cidx > 0 ) ) { 01328 return PAPI_ENOCMP; 01329 } 01330 01331 if ( IS_PRESET(i) ) { 01332 if ( modifier == PAPI_ENUM_FIRST ) { 01333 *EventCode = ( int ) PAPI_PRESET_MASK; 01334 return PAPI_OK; 01335 } 01336 i &= PAPI_PRESET_AND_MASK; 01337 while ( ++i < PAPI_MAX_PRESET_EVENTS ) { 01338 if ( _papi_hwi_presets[i].symbol == NULL ) 01339 return ( PAPI_ENOEVNT ); /* NULL pointer terminates list */ 01340 if ( modifier & PAPI_PRESET_ENUM_AVAIL ) { 01341 if ( _papi_hwi_presets[i].count == 0 ) 01342 continue; 01343 } 01344 *EventCode = ( int ) ( i | PAPI_PRESET_MASK ); 01345 return PAPI_OK; 01346 } 01347 } else if ( IS_NATIVE(i) ) { 01348 // if (!_papi_hwd[cidx]->cmp_info.disabled) { 01349 // return PAPI_ENOEVNT 01350 // } 01351 /* Should we check against num native events here? */ 01352 event_code=_papi_hwi_eventcode_to_native(*EventCode); 01353 retval = _papi_hwd[cidx]->ntv_enum_events((unsigned int *)&event_code, modifier ); 01354 01355 /* re-apply Component ID to the returned Event */ 01356 *EventCode = _papi_hwi_native_to_eventcode(cidx,event_code); 01357 01358 return retval; 01359 } 01360 01361 papi_return( PAPI_EINVAL ); 01362 } 01363 01410 int 01411 PAPI_create_eventset( int *EventSet ) 01412 { 01413 APIDBG("Entry: EventSet: %p\n", EventSet); 01414 ThreadInfo_t *master; 01415 int retval; 01416 01417 if ( init_level == PAPI_NOT_INITED ) 01418 papi_return( PAPI_ENOINIT ); 01419 retval = _papi_hwi_lookup_or_create_thread( &master, 0 ); 01420 if ( retval ) 01421 papi_return( retval ); 01422 01423 papi_return( _papi_hwi_create_eventset( EventSet, master ) ); 01424 } 01425 01474 int 01475 PAPI_assign_eventset_component( int EventSet, int cidx ) 01476 { 01477 EventSetInfo_t *ESI; 01478 int retval; 01479 01480 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01481 if ( ESI == NULL ) 01482 papi_return( PAPI_ENOEVST ); 01483 01484 /* validate cidx */ 01485 retval = valid_component( cidx ); 01486 if ( retval < 0 ) 01487 papi_return( retval ); 01488 01489 /* cowardly refuse to reassign eventsets */ 01490 if ( ESI->CmpIdx >= 0 ) 01491 return PAPI_EINVAL; 01492 01493 return ( _papi_hwi_assign_eventset( ESI, cidx ) ); 01494 } 01495 01517 int 01518 PAPI_get_eventset_component( int EventSet) 01519 { 01520 EventSetInfo_t *ESI; 01521 int retval; 01522 01523 /* validate eventset */ 01524 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01525 if ( ESI == NULL ) 01526 papi_return( PAPI_ENOEVST ); 01527 01528 /* check if a component has been assigned */ 01529 if ( ESI->CmpIdx < 0 ) 01530 papi_return( PAPI_ENOCMP ); 01531 01532 /* validate CmpIdx */ 01533 retval = valid_component( ESI->CmpIdx ); 01534 if ( retval < 0 ) 01535 papi_return( retval ); 01536 01537 /* return the index */ 01538 return ( ESI->CmpIdx ); 01539 } 01540 01541 01611 int 01612 PAPI_add_event( int EventSet, int EventCode ) 01613 { 01614 APIDBG("Entry: EventSet: %d, EventCode: 0x%x\n", EventSet, EventCode); 01615 EventSetInfo_t *ESI; 01616 01617 /* Is the EventSet already in existence? */ 01618 01619 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01620 if ( ESI == NULL ) 01621 papi_return( PAPI_ENOEVST ); 01622 01623 /* Check argument for validity */ 01624 01625 if ( ( ( EventCode & PAPI_PRESET_MASK ) == 0 ) && 01626 ( EventCode & PAPI_NATIVE_MASK ) == 0 ) 01627 papi_return( PAPI_EINVAL ); 01628 01629 /* Of course, it must be stopped in order to modify it. */ 01630 01631 if ( ESI->state & PAPI_RUNNING ) 01632 papi_return( PAPI_EISRUN ); 01633 01634 /* Now do the magic. */ 01635 01636 papi_return( _papi_hwi_add_event( ESI, EventCode ) ); 01637 } 01638 01706 int 01707 PAPI_remove_event( int EventSet, int EventCode ) 01708 { 01709 EventSetInfo_t *ESI; 01710 int i,retval; 01711 01712 /* check for pre-existing ESI */ 01713 01714 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01715 if ( ESI == NULL ) 01716 papi_return( PAPI_ENOEVST ); 01717 01718 /* Check argument for validity */ 01719 01720 if ( ( !IS_PRESET(EventCode) ) && 01721 ( !IS_NATIVE(EventCode) ) && 01722 ( !IS_USER_DEFINED(EventCode) )) 01723 papi_return( PAPI_EINVAL ); 01724 01725 /* Of course, it must be stopped in order to modify it. */ 01726 01727 if ( !( ESI->state & PAPI_STOPPED ) ) 01728 papi_return( PAPI_EISRUN ); 01729 01730 /* if the state is PAPI_OVERFLOWING, you must first call 01731 PAPI_overflow with threshold=0 to remove the overflow flag */ 01732 01733 /* Turn off the event that is overflowing */ 01734 if ( ESI->state & PAPI_OVERFLOWING ) { 01735 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 01736 if ( ESI->overflow.EventCode[i] == EventCode ) { 01737 retval = PAPI_overflow( EventSet, EventCode, 0, 0, 01738 ESI->overflow.handler ); 01739 if (retval!=PAPI_OK) return retval; 01740 break; 01741 } 01742 } 01743 } 01744 01745 /* force the user to call PAPI_profil to clear the PAPI_PROFILING flag */ 01746 if ( ESI->state & PAPI_PROFILING ) { 01747 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 01748 if ( ESI->profile.EventCode[i] == EventCode ) { 01749 PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, 0 ); 01750 break; 01751 } 01752 } 01753 } 01754 01755 /* Now do the magic. */ 01756 01757 papi_return( _papi_hwi_remove_event( ESI, EventCode ) ); 01758 } 01759 01823 int 01824 PAPI_add_named_event( int EventSet, char *EventName ) 01825 { 01826 int ret, code; 01827 01828 ret = PAPI_event_name_to_code( EventName, &code ); 01829 if ( ret == PAPI_OK ) ret = PAPI_add_event( EventSet, code ); 01830 papi_return( ret ); 01831 } 01832 01900 int 01901 PAPI_remove_named_event( int EventSet, char *EventName ) 01902 { 01903 int ret, code; 01904 01905 ret = PAPI_event_name_to_code( EventName, &code ); 01906 if ( ret == PAPI_OK ) ret = PAPI_remove_event( EventSet, code ); 01907 papi_return( ret ); 01908 } 01909 01951 int 01952 PAPI_destroy_eventset( int *EventSet ) 01953 { 01954 EventSetInfo_t *ESI; 01955 01956 APIDBG("Destroying Eventset %d\n",*EventSet); 01957 01958 /* check for pre-existing ESI */ 01959 01960 if ( EventSet == NULL ) 01961 papi_return( PAPI_EINVAL ); 01962 01963 ESI = _papi_hwi_lookup_EventSet( *EventSet ); 01964 if ( ESI == NULL ) 01965 papi_return( PAPI_ENOEVST ); 01966 01967 if ( !( ESI->state & PAPI_STOPPED ) ) 01968 papi_return( PAPI_EISRUN ); 01969 01970 if ( ESI->NumberOfEvents ) 01971 papi_return( PAPI_EINVAL ); 01972 01973 _papi_hwi_remove_EventSet( ESI ); 01974 *EventSet = PAPI_NULL; 01975 01976 return PAPI_OK; 01977 } 01978 01979 /* simply checks for valid EventSet, calls component start() call */ 02033 int 02034 PAPI_start( int EventSet ) 02035 { 02036 APIDBG("Entry: EventSet: %d\n", EventSet); 02037 int is_dirty=0; 02038 int retval; 02039 EventSetInfo_t *ESI; 02040 ThreadInfo_t *thread = NULL; 02041 CpuInfo_t *cpu = NULL; 02042 hwd_context_t *context; 02043 int cidx; 02044 02045 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02046 if ( ESI == NULL ) { 02047 papi_return( PAPI_ENOEVST ); 02048 } 02049 02050 cidx = valid_ESI_component( ESI ); 02051 if ( cidx < 0 ) { 02052 papi_return( cidx ); 02053 } 02054 02055 /* only one event set per thread/cpu can be running at any time, */ 02056 /* so if another event set is running, the user must stop that */ 02057 /* event set explicitly */ 02058 02059 thread = ESI->master; 02060 cpu = ESI->CpuInfo; 02061 02062 /* check cpu attached case first */ 02063 if (ESI->state & PAPI_CPU_ATTACHED) { 02064 if ( cpu->running_eventset[cidx] ) { 02065 papi_return( PAPI_EISRUN ); 02066 } 02067 } else { 02068 if ( thread->running_eventset[cidx] ) { 02069 papi_return( PAPI_EISRUN ); 02070 } 02071 } 02072 02073 /* Check that there are added events */ 02074 if ( ESI->NumberOfEvents < 1 ) { 02075 papi_return( PAPI_EINVAL ); 02076 } 02077 02078 /* If multiplexing is enabled for this eventset, 02079 call John May's code. */ 02080 02081 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02082 retval = MPX_start( ESI->multiplex.mpx_evset ); 02083 if ( retval != PAPI_OK ) { 02084 papi_return( retval ); 02085 } 02086 02087 /* Update the state of this EventSet */ 02088 ESI->state ^= PAPI_STOPPED; 02089 ESI->state |= PAPI_RUNNING; 02090 02091 return PAPI_OK; 02092 } 02093 02094 /* get the context we should use for this event set */ 02095 context = _papi_hwi_get_context( ESI, &is_dirty ); 02096 if (is_dirty) { 02097 /* we need to reset the context state because it was last used */ 02098 /* for some other event set and does not contain the information */ 02099 /* for our events. */ 02100 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( 02101 ESI->ctl_state, 02102 ESI->NativeInfoArray, 02103 ESI->NativeCount, 02104 context); 02105 if ( retval != PAPI_OK ) { 02106 papi_return( retval ); 02107 } 02108 02109 /* now that the context contains this event sets information, */ 02110 /* make sure the position array in the EventInfoArray is correct */ 02111 02112 /* We have to do this because ->update_control_state() can */ 02113 /* in theory re-order the native events out from under us. */ 02114 _papi_hwi_map_events_to_native( ESI ); 02115 02116 } 02117 02118 /* If overflowing is enabled, turn it on */ 02119 if ( ( ESI->state & PAPI_OVERFLOWING ) && 02120 !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02121 retval = _papi_hwi_start_signal( _papi_os_info.itimer_sig, 02122 NEED_CONTEXT, cidx ); 02123 if ( retval != PAPI_OK ) { 02124 papi_return( retval ); 02125 } 02126 02127 /* Update the state of this EventSet and thread */ 02128 /* before to avoid races */ 02129 ESI->state ^= PAPI_STOPPED; 02130 ESI->state |= PAPI_RUNNING; 02131 /* can not be attached to thread or cpu if overflowing */ 02132 thread->running_eventset[cidx] = ESI; 02133 02134 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02135 if ( retval != PAPI_OK ) { 02136 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02137 ESI->state ^= PAPI_RUNNING; 02138 ESI->state |= PAPI_STOPPED; 02139 thread->running_eventset[cidx] = NULL; 02140 papi_return( retval ); 02141 } 02142 02143 retval = _papi_hwi_start_timer( _papi_os_info.itimer_num, 02144 _papi_os_info.itimer_sig, 02145 _papi_os_info.itimer_ns ); 02146 if ( retval != PAPI_OK ) { 02147 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02148 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02149 ESI->state ^= PAPI_RUNNING; 02150 ESI->state |= PAPI_STOPPED; 02151 thread->running_eventset[cidx] = NULL; 02152 papi_return( retval ); 02153 } 02154 } else { 02155 /* Update the state of this EventSet and thread before */ 02156 /* to avoid races */ 02157 ESI->state ^= PAPI_STOPPED; 02158 ESI->state |= PAPI_RUNNING; 02159 02160 /* if not attached to cpu or another process */ 02161 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02162 if ( !( ESI->state & PAPI_ATTACHED ) ) { 02163 thread->running_eventset[cidx] = ESI; 02164 } 02165 } else { 02166 cpu->running_eventset[cidx] = ESI; 02167 } 02168 02169 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02170 if ( retval != PAPI_OK ) { 02171 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02172 ESI->state ^= PAPI_RUNNING; 02173 ESI->state |= PAPI_STOPPED; 02174 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02175 if ( !( ESI->state & PAPI_ATTACHED ) ) 02176 thread->running_eventset[cidx] = NULL; 02177 } else { 02178 cpu->running_eventset[cidx] = NULL; 02179 } 02180 papi_return( retval ); 02181 } 02182 } 02183 02184 return retval; 02185 } 02186 02187 /* checks for valid EventSet, calls component stop() function. */ 02238 int 02239 PAPI_stop( int EventSet, long long *values ) 02240 { 02241 APIDBG("Entry: EventSet: %d, values: %p\n", EventSet, values); 02242 EventSetInfo_t *ESI; 02243 hwd_context_t *context; 02244 int cidx, retval; 02245 02246 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02247 if ( ESI == NULL ) 02248 papi_return( PAPI_ENOEVST ); 02249 02250 cidx = valid_ESI_component( ESI ); 02251 if ( cidx < 0 ) 02252 papi_return( cidx ); 02253 02254 if ( !( ESI->state & PAPI_RUNNING ) ) 02255 papi_return( PAPI_ENOTRUN ); 02256 02257 /* If multiplexing is enabled for this eventset, turn if off */ 02258 02259 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02260 retval = MPX_stop( ESI->multiplex.mpx_evset, values ); 02261 if ( retval != PAPI_OK ) 02262 papi_return( retval ); 02263 02264 /* Update the state of this EventSet */ 02265 02266 ESI->state ^= PAPI_RUNNING; 02267 ESI->state |= PAPI_STOPPED; 02268 02269 return ( PAPI_OK ); 02270 } 02271 02272 /* get the context we should use for this event set */ 02273 context = _papi_hwi_get_context( ESI, NULL ); 02274 /* Read the current counter values into the EventSet */ 02275 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02276 if ( retval != PAPI_OK ) 02277 papi_return( retval ); 02278 02279 /* Remove the control bits from the active counter config. */ 02280 retval = _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02281 if ( retval != PAPI_OK ) 02282 papi_return( retval ); 02283 if ( values ) 02284 memcpy( values, ESI->sw_stop, 02285 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02286 02287 /* If kernel profiling is in use, flush and process the kernel buffer */ 02288 02289 if ( ESI->state & PAPI_PROFILING ) { 02290 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 02291 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02292 retval = _papi_hwd[cidx]->stop_profiling( ESI->master, ESI ); 02293 if ( retval < PAPI_OK ) 02294 papi_return( retval ); 02295 } 02296 } 02297 02298 /* If overflowing is enabled, turn it off */ 02299 02300 if ( ESI->state & PAPI_OVERFLOWING ) { 02301 if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02302 retval = _papi_hwi_stop_timer( _papi_os_info.itimer_num, 02303 _papi_os_info.itimer_sig ); 02304 if ( retval != PAPI_OK ) 02305 papi_return( retval ); 02306 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02307 } 02308 } 02309 02310 /* Update the state of this EventSet */ 02311 02312 ESI->state ^= PAPI_RUNNING; 02313 ESI->state |= PAPI_STOPPED; 02314 02315 /* Update the running event set for this thread */ 02316 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02317 if ( !( ESI->state & PAPI_ATTACHED )) 02318 ESI->master->running_eventset[cidx] = NULL; 02319 } else { 02320 ESI->CpuInfo->running_eventset[cidx] = NULL; 02321 } 02322 02323 #if defined(DEBUG) 02324 if ( _papi_hwi_debug & DEBUG_API ) { 02325 int i; 02326 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02327 APIDBG( "PAPI_stop ESI->sw_stop[%d]:\t%llu\n", i, ESI->sw_stop[i] ); 02328 } 02329 } 02330 #endif 02331 02332 return ( PAPI_OK ); 02333 } 02334 02383 int 02384 PAPI_reset( int EventSet ) 02385 { 02386 int retval = PAPI_OK; 02387 EventSetInfo_t *ESI; 02388 hwd_context_t *context; 02389 int cidx; 02390 02391 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02392 if ( ESI == NULL ) 02393 papi_return( PAPI_ENOEVST ); 02394 02395 cidx = valid_ESI_component( ESI ); 02396 if ( cidx < 0 ) 02397 papi_return( cidx ); 02398 02399 if ( ESI->state & PAPI_RUNNING ) { 02400 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02401 retval = MPX_reset( ESI->multiplex.mpx_evset ); 02402 } else { 02403 /* If we're not the only one running, then just 02404 read the current values into the ESI->start 02405 array. This holds the starting value for counters 02406 that are shared. */ 02407 /* get the context we should use for this event set */ 02408 context = _papi_hwi_get_context( ESI, NULL ); 02409 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02410 } 02411 } else { 02412 #ifdef __bgp__ 02413 // For BG/P, we always want to reset the 'real' hardware counters. The counters 02414 // can be controlled via multiple interfaces, and we need to ensure that the values 02415 // are truly zero... 02416 /* get the context we should use for this event set */ 02417 context = _papi_hwi_get_context( ESI, NULL ); 02418 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02419 #endif 02420 memset( ESI->sw_stop, 0x00, 02421 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02422 } 02423 02424 APIDBG( "PAPI_reset returns %d\n", retval ); 02425 papi_return( retval ); 02426 } 02427 02484 int 02485 PAPI_read( int EventSet, long long *values ) 02486 { 02487 EventSetInfo_t *ESI; 02488 hwd_context_t *context; 02489 int cidx, retval = PAPI_OK; 02490 02491 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02492 if ( ESI == NULL ) 02493 papi_return( PAPI_ENOEVST ); 02494 02495 cidx = valid_ESI_component( ESI ); 02496 if ( cidx < 0 ) 02497 papi_return( cidx ); 02498 02499 if ( values == NULL ) 02500 papi_return( PAPI_EINVAL ); 02501 02502 if ( ESI->state & PAPI_RUNNING ) { 02503 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02504 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02505 } else { 02506 /* get the context we should use for this event set */ 02507 context = _papi_hwi_get_context( ESI, NULL ); 02508 retval = _papi_hwi_read( context, ESI, values ); 02509 } 02510 if ( retval != PAPI_OK ) 02511 papi_return( retval ); 02512 } else { 02513 memcpy( values, ESI->sw_stop, 02514 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02515 } 02516 02517 #if defined(DEBUG) 02518 if ( ISLEVEL( DEBUG_API ) ) { 02519 int i; 02520 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02521 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02522 } 02523 } 02524 #endif 02525 02526 APIDBG( "PAPI_read returns %d\n", retval ); 02527 return ( PAPI_OK ); 02528 } 02529 02574 int 02575 PAPI_read_ts( int EventSet, long long *values, long long *cycles ) 02576 { 02577 EventSetInfo_t *ESI; 02578 hwd_context_t *context; 02579 int cidx, retval = PAPI_OK; 02580 02581 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02582 if ( ESI == NULL ) 02583 papi_return( PAPI_ENOEVST ); 02584 02585 cidx = valid_ESI_component( ESI ); 02586 if ( cidx < 0 ) 02587 papi_return( cidx ); 02588 02589 if ( values == NULL ) 02590 papi_return( PAPI_EINVAL ); 02591 02592 if ( ESI->state & PAPI_RUNNING ) { 02593 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02594 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02595 } else { 02596 /* get the context we should use for this event set */ 02597 context = _papi_hwi_get_context( ESI, NULL ); 02598 retval = _papi_hwi_read( context, ESI, values ); 02599 } 02600 if ( retval != PAPI_OK ) 02601 papi_return( retval ); 02602 } else { 02603 memcpy( values, ESI->sw_stop, 02604 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02605 } 02606 02607 *cycles = _papi_os_vector.get_real_cycles( ); 02608 02609 #if defined(DEBUG) 02610 if ( ISLEVEL( DEBUG_API ) ) { 02611 int i; 02612 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02613 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02614 } 02615 } 02616 #endif 02617 02618 APIDBG( "PAPI_read_ts returns %d\n", retval ); 02619 return PAPI_OK; 02620 } 02621 02670 int 02671 PAPI_accum( int EventSet, long long *values ) 02672 { 02673 EventSetInfo_t *ESI; 02674 hwd_context_t *context; 02675 int i, cidx, retval; 02676 long long a, b, c; 02677 02678 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02679 if ( ESI == NULL ) 02680 papi_return( PAPI_ENOEVST ); 02681 02682 cidx = valid_ESI_component( ESI ); 02683 if ( cidx < 0 ) 02684 papi_return( cidx ); 02685 02686 if ( values == NULL ) 02687 papi_return( PAPI_EINVAL ); 02688 02689 if ( ESI->state & PAPI_RUNNING ) { 02690 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02691 retval = MPX_read( ESI->multiplex.mpx_evset, ESI->sw_stop, 0 ); 02692 } else { 02693 /* get the context we should use for this event set */ 02694 context = _papi_hwi_get_context( ESI, NULL ); 02695 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02696 } 02697 if ( retval != PAPI_OK ) 02698 papi_return( retval ); 02699 } 02700 02701 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02702 a = ESI->sw_stop[i]; 02703 b = values[i]; 02704 c = a + b; 02705 values[i] = c; 02706 } 02707 02708 papi_return( PAPI_reset( EventSet ) ); 02709 } 02710 02737 int 02738 PAPI_write( int EventSet, long long *values ) 02739 { 02740 int cidx, retval = PAPI_OK; 02741 EventSetInfo_t *ESI; 02742 hwd_context_t *context; 02743 02744 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02745 if ( ESI == NULL ) 02746 papi_return( PAPI_ENOEVST ); 02747 02748 cidx = valid_ESI_component( ESI ); 02749 if ( cidx < 0 ) 02750 papi_return( cidx ); 02751 02752 if ( values == NULL ) 02753 papi_return( PAPI_EINVAL ); 02754 02755 if ( ESI->state & PAPI_RUNNING ) { 02756 /* get the context we should use for this event set */ 02757 context = _papi_hwi_get_context( ESI, NULL ); 02758 retval = _papi_hwd[cidx]->write( context, ESI->ctl_state, values ); 02759 if ( retval != PAPI_OK ) 02760 return ( retval ); 02761 } 02762 02763 memcpy( ESI->hw_start, values, 02764 ( size_t ) _papi_hwd[cidx]->cmp_info.num_cntrs * 02765 sizeof ( long long ) ); 02766 02767 return ( retval ); 02768 } 02769 02812 int 02813 PAPI_cleanup_eventset( int EventSet ) 02814 { 02815 EventSetInfo_t *ESI; 02816 int i, cidx, total, retval; 02817 02818 APIDBG("Attempting to cleanup Eventset %d\n",EventSet); 02819 02820 /* Is the EventSet already in existence? */ 02821 02822 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02823 if ( ESI == NULL ) 02824 papi_return( PAPI_ENOEVST ); 02825 02826 /* if the eventset has no index and no events, return OK 02827 otherwise return NOCMP */ 02828 cidx = valid_ESI_component( ESI ); 02829 if ( cidx < 0 ) { 02830 if ( ESI->NumberOfEvents ) 02831 papi_return( cidx ); 02832 papi_return( PAPI_OK ); 02833 } 02834 02835 /* Of course, it must be stopped in order to modify it. */ 02836 02837 if ( ESI->state & PAPI_RUNNING ) 02838 papi_return( PAPI_EISRUN ); 02839 02840 /* clear overflow flag and turn off hardware overflow handler */ 02841 if ( ESI->state & PAPI_OVERFLOWING ) { 02842 total = ESI->overflow.event_counter; 02843 for ( i = 0; i < total; i++ ) { 02844 retval = PAPI_overflow( EventSet, 02845 ESI->overflow.EventCode[0], 0, 0, NULL ); 02846 if ( retval != PAPI_OK ) 02847 papi_return( retval ); 02848 } 02849 } 02850 02851 /* clear profile flag and turn off hardware profile handler */ 02852 if ( ( ESI->state & PAPI_PROFILING ) && 02853 _papi_hwd[cidx]->cmp_info.hardware_intr && 02854 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02855 total = ESI->profile.event_counter; 02856 for ( i = 0; i < total; i++ ) { 02857 retval = 02858 PAPI_sprofil( NULL, 0, EventSet, ESI->profile.EventCode[0], 0, 02859 PAPI_PROFIL_POSIX ); 02860 if ( retval != PAPI_OK ) 02861 papi_return( retval ); 02862 } 02863 } 02864 02865 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02866 retval = MPX_cleanup( &ESI->multiplex.mpx_evset ); 02867 if ( retval != PAPI_OK ) 02868 papi_return( retval ); 02869 } 02870 02871 retval = _papi_hwd[cidx]->cleanup_eventset( ESI->ctl_state ); 02872 if ( retval != PAPI_OK ) 02873 papi_return( retval ); 02874 02875 /* Now do the magic */ 02876 papi_return( _papi_hwi_cleanup_eventset( ESI ) ); 02877 } 02878 02906 int 02907 PAPI_multiplex_init( void ) 02908 { 02909 int retval; 02910 02911 retval = mpx_init( _papi_os_info.itimer_ns ); 02912 papi_return( retval ); 02913 } 02914 02975 int 02976 PAPI_state( int EventSet, int *status ) 02977 { 02978 EventSetInfo_t *ESI; 02979 02980 if ( status == NULL ) 02981 papi_return( PAPI_EINVAL ); 02982 02983 /* check for good EventSetIndex value */ 02984 02985 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02986 if ( ESI == NULL ) 02987 papi_return( PAPI_ENOEVST ); 02988 02989 /*read status FROM ESI->state */ 02990 02991 *status = ESI->state; 02992 02993 return ( PAPI_OK ); 02994 } 02995 03046 int 03047 PAPI_set_debug( int level ) 03048 { 03049 PAPI_option_t option; 03050 03051 memset( &option, 0x0, sizeof ( option ) ); 03052 option.debug.level = level; 03053 option.debug.handler = _papi_hwi_debug_handler; 03054 return ( PAPI_set_opt( PAPI_DEBUG, &option ) ); 03055 } 03056 03057 /* Attaches to or detaches from the specified thread id */ 03058 inline_static int 03059 _papi_set_attach( int option, int EventSet, unsigned long tid ) 03060 { 03061 PAPI_option_t attach; 03062 03063 memset( &attach, 0x0, sizeof ( attach ) ); 03064 attach.attach.eventset = EventSet; 03065 attach.attach.tid = tid; 03066 return ( PAPI_set_opt( option, &attach ) ); 03067 } 03068 03122 int 03123 PAPI_attach( int EventSet, unsigned long tid ) 03124 { 03125 return ( _papi_set_attach( PAPI_ATTACH, EventSet, tid ) ); 03126 } 03127 03181 int 03182 PAPI_detach( int EventSet ) 03183 { 03184 return ( _papi_set_attach( PAPI_DETACH, EventSet, 0 ) ); 03185 } 03186 03255 int 03256 PAPI_set_multiplex( int EventSet ) 03257 { 03258 PAPI_option_t mpx; 03259 EventSetInfo_t *ESI; 03260 int cidx; 03261 int ret; 03262 03263 /* Is the EventSet already in existence? */ 03264 03265 ESI = _papi_hwi_lookup_EventSet( EventSet ); 03266 03267 if ( ESI == NULL ) 03268 papi_return( PAPI_ENOEVST ); 03269 03270 /* if the eventset has no index return NOCMP */ 03271 cidx = valid_ESI_component( ESI ); 03272 if ( cidx < 0 ) 03273 papi_return( cidx ); 03274 03275 if ( ( ret = mpx_check( EventSet ) ) != PAPI_OK ) 03276 papi_return( ret ); 03277 03278 memset( &mpx, 0x0, sizeof ( mpx ) ); 03279 mpx.multiplex.eventset = EventSet; 03280 mpx.multiplex.flags = PAPI_MULTIPLEX_DEFAULT; 03281 mpx.multiplex.ns = _papi_os_info.itimer_ns; 03282 return ( PAPI_set_opt( PAPI_MULTIPLEX, &mpx ) ); 03283 } 03284 03385 int 03386 PAPI_set_opt( int option, PAPI_option_t * ptr ) 03387 { 03388 APIDBG("Entry: option: %d, ptr: %p\n", option, ptr); 03389 03390 _papi_int_option_t internal; 03391 int retval = PAPI_OK; 03392 hwd_context_t *context; 03393 int cidx; 03394 03395 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 03396 papi_return( PAPI_ENOINIT ); 03397 if ( ptr == NULL ) 03398 papi_return( PAPI_EINVAL ); 03399 03400 memset( &internal, 0x0, sizeof ( _papi_int_option_t ) ); 03401 03402 switch ( option ) { 03403 case PAPI_DETACH: 03404 { 03405 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03406 if ( internal.attach.ESI == NULL ) 03407 papi_return( PAPI_ENOEVST ); 03408 03409 cidx = valid_ESI_component( internal.attach.ESI ); 03410 if ( cidx < 0 ) 03411 papi_return( cidx ); 03412 03413 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03414 papi_return( PAPI_ECMP ); 03415 03416 /* if attached to a cpu, return an error */ 03417 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03418 papi_return( PAPI_ECMP ); 03419 03420 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03421 papi_return( PAPI_EISRUN ); 03422 03423 if ( ( internal.attach.ESI->state & PAPI_ATTACHED ) == 0 ) 03424 papi_return( PAPI_EINVAL ); 03425 03426 internal.attach.tid = internal.attach.ESI->attach.tid; 03427 /* get the context we should use for this event set */ 03428 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03429 retval = _papi_hwd[cidx]->ctl( context, PAPI_DETACH, &internal ); 03430 if ( retval != PAPI_OK ) 03431 papi_return( retval ); 03432 03433 internal.attach.ESI->state ^= PAPI_ATTACHED; 03434 internal.attach.ESI->attach.tid = 0; 03435 return ( PAPI_OK ); 03436 } 03437 case PAPI_ATTACH: 03438 { 03439 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03440 if ( internal.attach.ESI == NULL ) 03441 papi_return( PAPI_ENOEVST ); 03442 03443 cidx = valid_ESI_component( internal.attach.ESI ); 03444 if ( cidx < 0 ) 03445 papi_return( cidx ); 03446 03447 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03448 papi_return( PAPI_ECMP ); 03449 03450 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03451 papi_return( PAPI_EISRUN ); 03452 03453 if ( internal.attach.ESI->state & PAPI_ATTACHED ) 03454 papi_return( PAPI_EINVAL ); 03455 03456 /* if attached to a cpu, return an error */ 03457 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03458 papi_return( PAPI_ECMP ); 03459 03460 internal.attach.tid = ptr->attach.tid; 03461 /* get the context we should use for this event set */ 03462 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03463 retval = _papi_hwd[cidx]->ctl( context, PAPI_ATTACH, &internal ); 03464 if ( retval != PAPI_OK ) 03465 papi_return( retval ); 03466 03467 internal.attach.ESI->state |= PAPI_ATTACHED; 03468 internal.attach.ESI->attach.tid = ptr->attach.tid; 03469 03470 papi_return (_papi_hwi_lookup_or_create_thread( 03471 &(internal.attach.ESI->master), ptr->attach.tid )); 03472 } 03473 case PAPI_CPU_ATTACH: 03474 { 03475 APIDBG("eventset: %d, cpu_num: %d\n", ptr->cpu.eventset, ptr->cpu.cpu_num); 03476 internal.cpu.ESI = _papi_hwi_lookup_EventSet( ptr->cpu.eventset ); 03477 if ( internal.cpu.ESI == NULL ) 03478 papi_return( PAPI_ENOEVST ); 03479 03480 internal.cpu.cpu_num = ptr->cpu.cpu_num; 03481 APIDBG("internal: %p, ESI: %p, cpu_num: %d\n", &internal, internal.cpu.ESI, internal.cpu.cpu_num); 03482 03483 cidx = valid_ESI_component( internal.cpu.ESI ); 03484 if ( cidx < 0 ) 03485 papi_return( cidx ); 03486 03487 if ( _papi_hwd[cidx]->cmp_info.cpu == 0 ) 03488 papi_return( PAPI_ECMP ); 03489 03490 // can not attach to a cpu if already attached to a process or 03491 // counters set to be inherited by child processes 03492 if ( internal.cpu.ESI->state & (PAPI_ATTACHED | PAPI_INHERIT) ) 03493 papi_return( PAPI_EINVAL ); 03494 03495 if ( ( internal.cpu.ESI->state & PAPI_STOPPED ) == 0 ) 03496 papi_return( PAPI_EISRUN ); 03497 03498 retval = _papi_hwi_lookup_or_create_cpu(&internal.cpu.ESI->CpuInfo, internal.cpu.cpu_num); 03499 if( retval != PAPI_OK) { 03500 papi_return( retval ); 03501 } 03502 03503 /* get the context we should use for this event set */ 03504 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03505 retval = _papi_hwd[cidx]->ctl( context, PAPI_CPU_ATTACH, &internal ); 03506 if ( retval != PAPI_OK ) 03507 papi_return( retval ); 03508 03509 /* set to show this event set is attached to a cpu not a thread */ 03510 internal.cpu.ESI->state |= PAPI_CPU_ATTACHED; 03511 return ( PAPI_OK ); 03512 } 03513 case PAPI_DEF_MPX_NS: 03514 { 03515 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03516 if ( ptr->multiplex.ns < 0 ) 03517 papi_return( PAPI_EINVAL ); 03518 /* We should check the resolution here with the system, either 03519 component if kernel multiplexing or PAPI if SW multiplexing. */ 03520 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03521 /* get the context we should use for this event set */ 03522 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03523 /* Low level just checks/adjusts the args for this component */ 03524 retval = _papi_hwd[cidx]->ctl( context, PAPI_DEF_MPX_NS, &internal ); 03525 if ( retval == PAPI_OK ) { 03526 _papi_os_info.itimer_ns = ( int ) internal.multiplex.ns; 03527 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03528 } 03529 papi_return( retval ); 03530 } 03531 case PAPI_DEF_ITIMER_NS: 03532 { 03533 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03534 if ( ptr->itimer.ns < 0 ) 03535 papi_return( PAPI_EINVAL ); 03536 internal.itimer.ns = ptr->itimer.ns; 03537 /* Low level just checks/adjusts the args for this component */ 03538 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER_NS, &internal ); 03539 if ( retval == PAPI_OK ) { 03540 _papi_os_info.itimer_ns = internal.itimer.ns; 03541 ptr->itimer.ns = internal.itimer.ns; 03542 } 03543 papi_return( retval ); 03544 } 03545 case PAPI_DEF_ITIMER: 03546 { 03547 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03548 if ( ptr->itimer.ns < 0 ) 03549 papi_return( PAPI_EINVAL ); 03550 memcpy( &internal.itimer, &ptr->itimer, 03551 sizeof ( PAPI_itimer_option_t ) ); 03552 /* Low level just checks/adjusts the args for this component */ 03553 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER, &internal ); 03554 if ( retval == PAPI_OK ) { 03555 _papi_os_info.itimer_num = ptr->itimer.itimer_num; 03556 _papi_os_info.itimer_sig = ptr->itimer.itimer_sig; 03557 if ( ptr->itimer.ns > 0 ) 03558 _papi_os_info.itimer_ns = ptr->itimer.ns; 03559 /* flags are currently ignored, eventually the flags will be able 03560 to specify whether or not we use POSIX itimers (clock_gettimer) */ 03561 } 03562 papi_return( retval ); 03563 } 03564 case PAPI_MULTIPLEX: 03565 { 03566 EventSetInfo_t *ESI; 03567 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 03568 03569 if ( ESI == NULL ) 03570 papi_return( PAPI_ENOEVST ); 03571 03572 cidx = valid_ESI_component( ESI ); 03573 if ( cidx < 0 ) 03574 papi_return( cidx ); 03575 03576 if ( !( ESI->state & PAPI_STOPPED ) ) 03577 papi_return( PAPI_EISRUN ); 03578 if ( ESI->state & PAPI_MULTIPLEXING ) 03579 papi_return( PAPI_EINVAL ); 03580 03581 if ( ptr->multiplex.ns < 0 ) 03582 papi_return( PAPI_EINVAL ); 03583 internal.multiplex.ESI = ESI; 03584 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03585 internal.multiplex.flags = ptr->multiplex.flags; 03586 if ( ( _papi_hwd[cidx]->cmp_info.kernel_multiplex ) && 03587 ( ( ptr->multiplex.flags & PAPI_MULTIPLEX_FORCE_SW ) == 0 ) ) { 03588 /* get the context we should use for this event set */ 03589 context = _papi_hwi_get_context( ESI, NULL ); 03590 retval = _papi_hwd[cidx]->ctl( context, PAPI_MULTIPLEX, &internal ); 03591 } 03592 /* Kernel or PAPI may have changed this value so send it back out to the user */ 03593 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03594 if ( retval == PAPI_OK ) 03595 papi_return( _papi_hwi_convert_eventset_to_multiplex 03596 ( &internal.multiplex ) ); 03597 return ( retval ); 03598 } 03599 case PAPI_DEBUG: 03600 { 03601 int level = ptr->debug.level; 03602 switch ( level ) { 03603 case PAPI_QUIET: 03604 case PAPI_VERB_ESTOP: 03605 case PAPI_VERB_ECONT: 03606 _papi_hwi_error_level = level; 03607 break; 03608 default: 03609 papi_return( PAPI_EINVAL ); 03610 } 03611 _papi_hwi_debug_handler = ptr->debug.handler; 03612 return ( PAPI_OK ); 03613 } 03614 case PAPI_DEFDOM: 03615 { 03616 int dom = ptr->defdomain.domain; 03617 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03618 papi_return( PAPI_EINVAL ); 03619 03620 /* Change the global structure. The _papi_hwd_init_control_state function 03621 in the components gets information from the global structure instead of 03622 per-thread information. */ 03623 cidx = valid_component( ptr->defdomain.def_cidx ); 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 ); 03634 03635 _papi_hwd[cidx]->cmp_info.default_domain = dom; 03636 03637 return ( PAPI_OK ); 03638 } 03639 case PAPI_DOMAIN: 03640 { 03641 int dom = ptr->domain.domain; 03642 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03643 papi_return( PAPI_EINVAL_DOM ); 03644 03645 internal.domain.ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 03646 if ( internal.domain.ESI == NULL ) 03647 papi_return( PAPI_ENOEVST ); 03648 03649 cidx = valid_ESI_component( internal.domain.ESI ); 03650 if ( cidx < 0 ) 03651 papi_return( cidx ); 03652 03653 /* Check what the component supports */ 03654 03655 if ( dom == PAPI_DOM_ALL ) 03656 dom = _papi_hwd[cidx]->cmp_info.available_domains; 03657 03658 if ( dom & ~_papi_hwd[cidx]->cmp_info.available_domains ) 03659 papi_return( PAPI_EINVAL_DOM ); 03660 03661 if ( !( internal.domain.ESI->state & PAPI_STOPPED ) ) 03662 papi_return( PAPI_EISRUN ); 03663 03664 /* Try to change the domain of the eventset in the hardware */ 03665 internal.domain.domain = dom; 03666 internal.domain.eventset = ptr->domain.eventset; 03667 /* get the context we should use for this event set */ 03668 context = _papi_hwi_get_context( internal.domain.ESI, NULL ); 03669 retval = _papi_hwd[cidx]->ctl( context, PAPI_DOMAIN, &internal ); 03670 if ( retval < PAPI_OK ) 03671 papi_return( retval ); 03672 03673 /* Change the domain of the eventset in the library */ 03674 03675 internal.domain.ESI->domain.domain = dom; 03676 03677 return ( retval ); 03678 } 03679 case PAPI_DEFGRN: 03680 { 03681 int grn = ptr->defgranularity.granularity; 03682 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03683 papi_return( PAPI_EINVAL ); 03684 03685 cidx = valid_component( ptr->defgranularity.def_cidx ); 03686 if ( cidx < 0 ) 03687 papi_return( cidx ); 03688 03689 /* Change the component structure. The _papi_hwd_init_control_state function 03690 in the components gets information from the global structure instead of 03691 per-thread information. */ 03692 03693 /* Check what the component supports */ 03694 03695 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03696 papi_return( PAPI_EINVAL ); 03697 03698 /* Make sure there is only 1 set. */ 03699 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03700 papi_return( PAPI_EINVAL ); 03701 03702 _papi_hwd[cidx]->cmp_info.default_granularity = grn; 03703 03704 return ( PAPI_OK ); 03705 } 03706 case PAPI_GRANUL: 03707 { 03708 int grn = ptr->granularity.granularity; 03709 03710 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03711 papi_return( PAPI_EINVAL ); 03712 03713 internal.granularity.ESI = 03714 _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 03715 if ( internal.granularity.ESI == NULL ) 03716 papi_return( PAPI_ENOEVST ); 03717 03718 cidx = valid_ESI_component( internal.granularity.ESI ); 03719 if ( cidx < 0 ) 03720 papi_return( cidx ); 03721 03722 /* Check what the component supports */ 03723 03724 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03725 papi_return( PAPI_EINVAL ); 03726 03727 /* Make sure there is only 1 set. */ 03728 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03729 papi_return( PAPI_EINVAL ); 03730 03731 internal.granularity.granularity = grn; 03732 internal.granularity.eventset = ptr->granularity.eventset; 03733 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_GRANUL, &internal ); 03734 if ( retval < PAPI_OK ) 03735 return ( retval ); 03736 03737 internal.granularity.ESI->granularity.granularity = grn; 03738 return ( retval ); 03739 } 03740 case PAPI_INHERIT: 03741 { 03742 EventSetInfo_t *ESI; 03743 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 03744 if ( ESI == NULL ) 03745 papi_return( PAPI_ENOEVST ); 03746 03747 cidx = valid_ESI_component( ESI ); 03748 if ( cidx < 0 ) 03749 papi_return( cidx ); 03750 03751 if ( _papi_hwd[cidx]->cmp_info.inherit == 0 ) 03752 papi_return( PAPI_ECMP ); 03753 03754 if ( ( ESI->state & PAPI_STOPPED ) == 0 ) 03755 papi_return( PAPI_EISRUN ); 03756 03757 /* if attached to a cpu, return an error */ 03758 if (ESI->state & PAPI_CPU_ATTACHED) 03759 papi_return( PAPI_ECMP ); 03760 03761 internal.inherit.ESI = ESI; 03762 internal.inherit.inherit = ptr->inherit.inherit; 03763 03764 /* get the context we should use for this event set */ 03765 context = _papi_hwi_get_context( internal.inherit.ESI, NULL ); 03766 retval = _papi_hwd[cidx]->ctl( context, PAPI_INHERIT, &internal ); 03767 if ( retval < PAPI_OK ) 03768 return ( retval ); 03769 03770 ESI->inherit.inherit = ptr->inherit.inherit; 03771 return ( retval ); 03772 } 03773 case PAPI_DATA_ADDRESS: 03774 case PAPI_INSTR_ADDRESS: 03775 { 03776 03777 EventSetInfo_t *ESI; 03778 03779 ESI = _papi_hwi_lookup_EventSet( ptr->addr.eventset ); 03780 if ( ESI == NULL ) 03781 papi_return( PAPI_ENOEVST ); 03782 03783 cidx = valid_ESI_component( ESI ); 03784 if ( cidx < 0 ) 03785 papi_return( cidx ); 03786 03787 internal.address_range.ESI = ESI; 03788 03789 if ( !( internal.address_range.ESI->state & PAPI_STOPPED ) ) 03790 papi_return( PAPI_EISRUN ); 03791 03792 /*set domain to be PAPI_DOM_USER */ 03793 internal.address_range.domain = PAPI_DOM_USER; 03794 03795 internal.address_range.start = ptr->addr.start; 03796 internal.address_range.end = ptr->addr.end; 03797 /* get the context we should use for this event set */ 03798 context = _papi_hwi_get_context( internal.address_range.ESI, NULL ); 03799 retval = _papi_hwd[cidx]->ctl( context, option, &internal ); 03800 ptr->addr.start_off = internal.address_range.start_off; 03801 ptr->addr.end_off = internal.address_range.end_off; 03802 papi_return( retval ); 03803 } 03804 case PAPI_USER_EVENTS_FILE: 03805 { 03806 SUBDBG("Filename is -%s-\n", ptr->events_file); 03807 _papi_user_defined_events_setup(ptr->events_file); 03808 return( PAPI_OK ); 03809 } 03810 default: 03811 papi_return( PAPI_EINVAL ); 03812 } 03813 } 03814 03824 int 03825 PAPI_num_hwctrs( void ) 03826 { 03827 return ( PAPI_num_cmp_hwctrs( 0 ) ); 03828 } 03829 03879 int 03880 PAPI_num_cmp_hwctrs( int cidx ) 03881 { 03882 return ( PAPI_get_cmp_opt( PAPI_MAX_HWCTRS, NULL, cidx ) ); 03883 } 03884 03941 int 03942 PAPI_get_multiplex( int EventSet ) 03943 { 03944 PAPI_option_t popt; 03945 int retval; 03946 03947 popt.multiplex.eventset = EventSet; 03948 retval = PAPI_get_opt( PAPI_MULTIPLEX, &popt ); 03949 if ( retval < 0 ) 03950 retval = 0; 03951 return retval; 03952 } 03953 04055 int 04056 PAPI_get_opt( int option, PAPI_option_t * ptr ) 04057 { 04058 EventSetInfo_t *ESI; 04059 04060 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 04061 papi_return( PAPI_ENOINIT ); 04062 04063 switch ( option ) { 04064 case PAPI_DETACH: 04065 { 04066 if ( ptr == NULL ) 04067 papi_return( PAPI_EINVAL ); 04068 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04069 if ( ESI == NULL ) 04070 papi_return( PAPI_ENOEVST ); 04071 ptr->attach.tid = ESI->attach.tid; 04072 return ( ( ESI->state & PAPI_ATTACHED ) == 0 ); 04073 } 04074 case PAPI_ATTACH: 04075 { 04076 if ( ptr == NULL ) 04077 papi_return( PAPI_EINVAL ); 04078 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04079 if ( ESI == NULL ) 04080 papi_return( PAPI_ENOEVST ); 04081 ptr->attach.tid = ESI->attach.tid; 04082 return ( ( ESI->state & PAPI_ATTACHED ) != 0 ); 04083 } 04084 case PAPI_CPU_ATTACH: 04085 { 04086 if ( ptr == NULL ) 04087 papi_return( PAPI_EINVAL ); 04088 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04089 if ( ESI == NULL ) 04090 papi_return( PAPI_ENOEVST ); 04091 ptr->cpu.cpu_num = ESI->CpuInfo->cpu_num; 04092 return ( ( ESI->state & PAPI_CPU_ATTACHED ) != 0 ); 04093 } 04094 case PAPI_DEF_MPX_NS: 04095 { 04096 /* xxxx for now, assume we only check against cpu component */ 04097 if ( ptr == NULL ) 04098 papi_return( PAPI_EINVAL ); 04099 ptr->multiplex.ns = _papi_os_info.itimer_ns; 04100 return ( PAPI_OK ); 04101 } 04102 case PAPI_DEF_ITIMER_NS: 04103 { 04104 /* xxxx for now, assume we only check against cpu component */ 04105 if ( ptr == NULL ) 04106 papi_return( PAPI_EINVAL ); 04107 ptr->itimer.ns = _papi_os_info.itimer_ns; 04108 return ( PAPI_OK ); 04109 } 04110 case PAPI_DEF_ITIMER: 04111 { 04112 /* xxxx for now, assume we only check against cpu component */ 04113 if ( ptr == NULL ) 04114 papi_return( PAPI_EINVAL ); 04115 ptr->itimer.itimer_num = _papi_os_info.itimer_num; 04116 ptr->itimer.itimer_sig = _papi_os_info.itimer_sig; 04117 ptr->itimer.ns = _papi_os_info.itimer_ns; 04118 ptr->itimer.flags = 0; 04119 return ( PAPI_OK ); 04120 } 04121 case PAPI_MULTIPLEX: 04122 { 04123 if ( ptr == NULL ) 04124 papi_return( PAPI_EINVAL ); 04125 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 04126 if ( ESI == NULL ) 04127 papi_return( PAPI_ENOEVST ); 04128 ptr->multiplex.ns = ESI->multiplex.ns; 04129 ptr->multiplex.flags = ESI->multiplex.flags; 04130 return ( ESI->state & PAPI_MULTIPLEXING ) != 0; 04131 } 04132 case PAPI_PRELOAD: 04133 if ( ptr == NULL ) 04134 papi_return( PAPI_EINVAL ); 04135 memcpy( &ptr->preload, &_papi_hwi_system_info.preload_info, 04136 sizeof ( PAPI_preload_info_t ) ); 04137 break; 04138 case PAPI_DEBUG: 04139 if ( ptr == NULL ) 04140 papi_return( PAPI_EINVAL ); 04141 ptr->debug.level = _papi_hwi_error_level; 04142 ptr->debug.handler = _papi_hwi_debug_handler; 04143 break; 04144 case PAPI_CLOCKRATE: 04145 return ( ( int ) _papi_hwi_system_info.hw_info.cpu_max_mhz ); 04146 case PAPI_MAX_CPUS: 04147 return ( _papi_hwi_system_info.hw_info.ncpu ); 04148 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04149 At some future point, they may map onto different values. 04150 */ 04151 case PAPI_INHERIT: 04152 { 04153 if ( ptr == NULL ) 04154 papi_return( PAPI_EINVAL ); 04155 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 04156 if ( ESI == NULL ) 04157 papi_return( PAPI_ENOEVST ); 04158 ptr->inherit.inherit = ESI->inherit.inherit; 04159 return ( PAPI_OK ); 04160 } 04161 case PAPI_GRANUL: 04162 if ( ptr == NULL ) 04163 papi_return( PAPI_EINVAL ); 04164 ESI = _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 04165 if ( ESI == NULL ) 04166 papi_return( PAPI_ENOEVST ); 04167 ptr->granularity.granularity = ESI->granularity.granularity; 04168 break; 04169 case PAPI_EXEINFO: 04170 if ( ptr == NULL ) 04171 papi_return( PAPI_EINVAL ); 04172 ptr->exe_info = &_papi_hwi_system_info.exe_info; 04173 break; 04174 case PAPI_HWINFO: 04175 if ( ptr == NULL ) 04176 papi_return( PAPI_EINVAL ); 04177 ptr->hw_info = &_papi_hwi_system_info.hw_info; 04178 break; 04179 04180 case PAPI_DOMAIN: 04181 if ( ptr == NULL ) 04182 papi_return( PAPI_EINVAL ); 04183 ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 04184 if ( ESI == NULL ) 04185 papi_return( PAPI_ENOEVST ); 04186 ptr->domain.domain = ESI->domain.domain; 04187 return ( PAPI_OK ); 04188 case PAPI_LIB_VERSION: 04189 return ( PAPI_VERSION ); 04190 /* The following cases all require a component index 04191 and are handled by PAPI_get_cmp_opt() with cidx == 0*/ 04192 case PAPI_MAX_HWCTRS: 04193 case PAPI_MAX_MPX_CTRS: 04194 case PAPI_DEFDOM: 04195 case PAPI_DEFGRN: 04196 case PAPI_SHLIBINFO: 04197 case PAPI_COMPONENTINFO: 04198 return ( PAPI_get_cmp_opt( option, ptr, 0 ) ); 04199 default: 04200 papi_return( PAPI_EINVAL ); 04201 } 04202 return ( PAPI_OK ); 04203 } 04204 04246 int 04247 PAPI_get_cmp_opt( int option, PAPI_option_t * ptr, int cidx ) 04248 { 04249 04250 if (_papi_hwi_invalid_cmp(cidx)) { 04251 return PAPI_ECMP; 04252 } 04253 04254 switch ( option ) { 04255 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04256 At some future point, they may map onto different values. 04257 */ 04258 case PAPI_MAX_HWCTRS: 04259 return ( _papi_hwd[cidx]->cmp_info.num_cntrs ); 04260 case PAPI_MAX_MPX_CTRS: 04261 return ( _papi_hwd[cidx]->cmp_info.num_mpx_cntrs ); 04262 case PAPI_DEFDOM: 04263 return ( _papi_hwd[cidx]->cmp_info.default_domain ); 04264 case PAPI_DEFGRN: 04265 return ( _papi_hwd[cidx]->cmp_info.default_granularity ); 04266 case PAPI_SHLIBINFO: 04267 { 04268 int retval; 04269 if ( ptr == NULL ) 04270 papi_return( PAPI_EINVAL ); 04271 retval = _papi_os_vector.update_shlib_info( &_papi_hwi_system_info ); 04272 ptr->shlib_info = &_papi_hwi_system_info.shlib_info; 04273 papi_return( retval ); 04274 } 04275 case PAPI_COMPONENTINFO: 04276 if ( ptr == NULL ) 04277 papi_return( PAPI_EINVAL ); 04278 ptr->cmp_info = &( _papi_hwd[cidx]->cmp_info ); 04279 return PAPI_OK; 04280 default: 04281 papi_return( PAPI_EINVAL ); 04282 } 04283 return PAPI_OK; 04284 } 04285 04297 int 04298 PAPI_num_components( void ) 04299 { 04300 return ( papi_num_components ); 04301 } 04302 04337 int 04338 PAPI_num_events( int EventSet ) 04339 { 04340 EventSetInfo_t *ESI; 04341 04342 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04343 if ( !ESI ) 04344 papi_return( PAPI_ENOEVST ); 04345 04346 #ifdef DEBUG 04347 /* Not necessary */ 04348 if ( ESI->NumberOfEvents == 0 ) 04349 papi_return( PAPI_EINVAL ); 04350 #endif 04351 04352 return ( ESI->NumberOfEvents ); 04353 } 04354 04355 04371 void 04372 PAPI_shutdown( void ) 04373 { 04374 EventSetInfo_t *ESI; 04375 ThreadInfo_t *master; 04376 DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map; 04377 int i, j = 0, retval; 04378 04379 04380 APIDBG( "Enter\n" ); 04381 if ( init_retval == DEADBEEF ) { 04382 PAPIERROR( PAPI_SHUTDOWN_str ); 04383 return; 04384 } 04385 04386 MPX_shutdown( ); 04387 04388 /* Free all EventSets for this thread */ 04389 04390 master = _papi_hwi_lookup_thread( 0 ); 04391 04392 /* Count number of running EventSets AND */ 04393 /* Stop any running EventSets in this thread */ 04394 04395 #ifdef DEBUG 04396 again: 04397 #endif 04398 for( i = 0; i < map->totalSlots; i++ ) { 04399 ESI = map->dataSlotArray[i]; 04400 if ( ESI ) { 04401 if ( ESI->master == master ) { 04402 if ( ESI->state & PAPI_RUNNING ) { 04403 retval=PAPI_stop( i, NULL ); 04404 } 04405 retval=PAPI_cleanup_eventset( i ); 04406 if (retval!=PAPI_OK) PAPIERROR("Error during cleanup.\n"); 04407 _papi_hwi_free_EventSet( ESI ); 04408 } 04409 else { 04410 if ( ESI->state & PAPI_RUNNING ) { 04411 j++; 04412 } 04413 } 04414 } 04415 } 04416 04417 /* No locking required, we're just waiting for the others 04418 to call shutdown or stop their eventsets. */ 04419 04420 #ifdef DEBUG 04421 if ( j != 0 ) { 04422 PAPIERROR( PAPI_SHUTDOWN_SYNC_str ); 04423 sleep( 1 ); 04424 j = 0; 04425 goto again; 04426 } 04427 #endif 04428 04429 /* Shutdown the entire component */ 04430 04431 _papi_cleanup_user_events(); 04432 04433 _papi_hwi_shutdown_highlevel( ); 04434 _papi_hwi_shutdown_global_internal( ); 04435 _papi_hwi_shutdown_global_threads( ); 04436 for( i = 0; i < papi_num_components; i++ ) { 04437 if (!_papi_hwd[i]->cmp_info.disabled) { 04438 _papi_hwd[i]->shutdown_component( ); 04439 } 04440 } 04441 04442 /* Now it is safe to call re-init */ 04443 04444 init_retval = DEADBEEF; 04445 init_level = PAPI_NOT_INITED; 04446 _papi_mem_cleanup_all( ); 04447 } 04448 04497 char * 04498 PAPI_strerror( int errorCode ) 04499 { 04500 if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) 04501 return ( NULL ); 04502 04503 return ( _papi_errlist[-errorCode] ); 04504 } 04505 04547 void 04548 PAPI_perror( char *msg ) 04549 { 04550 char *foo; 04551 04552 foo = PAPI_strerror( _papi_hwi_errno ); 04553 if ( foo == NULL ) 04554 return; 04555 04556 if ( msg ) 04557 if ( *msg ) 04558 fprintf( stderr, "%s: ", msg ); 04559 04560 fprintf( stderr, "%s\n", foo ); 04561 } 04562 04683 int 04684 PAPI_overflow( int EventSet, int EventCode, int threshold, int flags, 04685 PAPI_overflow_handler_t handler ) 04686 { 04687 int retval, cidx, index, i; 04688 EventSetInfo_t *ESI; 04689 04690 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04691 if ( ESI == NULL ) { 04692 OVFDBG("No EventSet\n"); 04693 papi_return( PAPI_ENOEVST ); 04694 } 04695 04696 cidx = valid_ESI_component( ESI ); 04697 if ( cidx < 0 ) { 04698 OVFDBG("Component Error\n"); 04699 papi_return( cidx ); 04700 } 04701 04702 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04703 OVFDBG("Already running\n"); 04704 papi_return( PAPI_EISRUN ); 04705 } 04706 04707 if ( ESI->state & PAPI_ATTACHED ) { 04708 OVFDBG("Attached\n"); 04709 papi_return( PAPI_EINVAL ); 04710 } 04711 04712 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04713 OVFDBG("CPU attached\n"); 04714 papi_return( PAPI_EINVAL ); 04715 } 04716 04717 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04718 ( unsigned int ) EventCode ) ) < 0 ) { 04719 papi_return( PAPI_ENOEVNT ); 04720 } 04721 04722 if ( threshold < 0 ) { 04723 OVFDBG("Threshold below zero\n"); 04724 papi_return( PAPI_EINVAL ); 04725 } 04726 04727 /* We do not support derived events in overflow */ 04728 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04729 04730 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && threshold != 0 && 04731 ( ESI->EventInfoArray[index].derived ) && 04732 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) ) { 04733 OVFDBG("Derived event in overflow\n"); 04734 papi_return( PAPI_EINVAL ); 04735 } 04736 04737 /* the first time to call PAPI_overflow function */ 04738 04739 if ( !( ESI->state & PAPI_OVERFLOWING ) ) { 04740 if ( handler == NULL ) { 04741 OVFDBG("NULL handler\n"); 04742 papi_return( PAPI_EINVAL ); 04743 } 04744 if ( threshold == 0 ) { 04745 OVFDBG("Zero threshold\n"); 04746 papi_return( PAPI_EINVAL ); 04747 } 04748 } 04749 if ( threshold > 0 && 04750 ESI->overflow.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs ) 04751 papi_return( PAPI_ECNFLCT ); 04752 04753 if ( threshold == 0 ) { 04754 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04755 if ( ESI->overflow.EventCode[i] == EventCode ) 04756 break; 04757 } 04758 /* EventCode not found */ 04759 if ( i == ESI->overflow.event_counter ) 04760 papi_return( PAPI_EINVAL ); 04761 /* compact these arrays */ 04762 while ( i < ESI->overflow.event_counter - 1 ) { 04763 ESI->overflow.deadline[i] = ESI->overflow.deadline[i + 1]; 04764 ESI->overflow.threshold[i] = ESI->overflow.threshold[i + 1]; 04765 ESI->overflow.EventIndex[i] = ESI->overflow.EventIndex[i + 1]; 04766 ESI->overflow.EventCode[i] = ESI->overflow.EventCode[i + 1]; 04767 i++; 04768 } 04769 ESI->overflow.deadline[i] = 0; 04770 ESI->overflow.threshold[i] = 0; 04771 ESI->overflow.EventIndex[i] = 0; 04772 ESI->overflow.EventCode[i] = 0; 04773 ESI->overflow.event_counter--; 04774 } else { 04775 if ( ESI->overflow.event_counter > 0 ) { 04776 if ( ( flags & PAPI_OVERFLOW_FORCE_SW ) && 04777 ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) 04778 papi_return( PAPI_ECNFLCT ); 04779 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && 04780 ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) 04781 papi_return( PAPI_ECNFLCT ); 04782 } 04783 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04784 if ( ESI->overflow.EventCode[i] == EventCode ) 04785 break; 04786 } 04787 /* A new entry */ 04788 if ( i == ESI->overflow.event_counter ) { 04789 ESI->overflow.EventCode[i] = EventCode; 04790 ESI->overflow.event_counter++; 04791 } 04792 /* New or existing entry */ 04793 ESI->overflow.deadline[i] = threshold; 04794 ESI->overflow.threshold[i] = threshold; 04795 ESI->overflow.EventIndex[i] = index; 04796 ESI->overflow.flags = flags; 04797 04798 } 04799 04800 /* If overflowing is already active, we should check to 04801 make sure that we don't specify a different handler 04802 or different flags here. You can't mix them. */ 04803 04804 ESI->overflow.handler = handler; 04805 04806 /* Set up the option structure for the low level. 04807 If we have hardware interrupts and we are not using 04808 forced software emulated interrupts */ 04809 04810 if ( _papi_hwd[cidx]->cmp_info.hardware_intr && 04811 !( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) { 04812 retval = _papi_hwd[cidx]->set_overflow( ESI, index, threshold ); 04813 if ( retval == PAPI_OK ) 04814 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 04815 else { 04816 papi_return( retval ); /* We should undo stuff here */ 04817 } 04818 } else { 04819 /* Make sure hardware overflow is not set */ 04820 ESI->overflow.flags &= ~( PAPI_OVERFLOW_HARDWARE ); 04821 } 04822 04823 APIDBG( "Overflow using: %s\n", 04824 ( ESI->overflow. 04825 flags & PAPI_OVERFLOW_HARDWARE ? "[Hardware]" : ESI->overflow. 04826 flags & PAPI_OVERFLOW_FORCE_SW ? "[Forced Software]" : 04827 "[Software]" ) ); 04828 04829 /* Toggle the overflow flags and ESI state */ 04830 04831 if ( ESI->overflow.event_counter >= 1 ) 04832 ESI->state |= PAPI_OVERFLOWING; 04833 else { 04834 ESI->state ^= PAPI_OVERFLOWING; 04835 ESI->overflow.flags = 0; 04836 ESI->overflow.handler = NULL; 04837 } 04838 04839 return PAPI_OK; 04840 } 04841 04938 int 04939 PAPI_sprofil( PAPI_sprofil_t *prof, int profcnt, int EventSet, 04940 int EventCode, int threshold, int flags ) 04941 { 04942 EventSetInfo_t *ESI; 04943 int retval, index, i, buckets; 04944 int forceSW = 0; 04945 int cidx; 04946 04947 /* Check to make sure EventSet exists */ 04948 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04949 if ( ESI == NULL ) { 04950 papi_return( PAPI_ENOEVST ); 04951 } 04952 04953 /* Check to make sure EventSet is stopped */ 04954 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04955 papi_return( PAPI_EISRUN ); 04956 } 04957 04958 /* We cannot profile if attached */ 04959 if ( ESI->state & PAPI_ATTACHED ) { 04960 papi_return( PAPI_EINVAL ); 04961 } 04962 04963 /* We cannot profile if cpu attached */ 04964 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04965 papi_return( PAPI_EINVAL ); 04966 } 04967 04968 /* Get component for EventSet */ 04969 cidx = valid_ESI_component( ESI ); 04970 if ( cidx < 0 ) { 04971 papi_return( cidx ); 04972 } 04973 04974 /* Get index of the Event we want to profile */ 04975 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04976 (unsigned int) EventCode ) ) < 0 ) { 04977 papi_return( PAPI_ENOEVNT ); 04978 } 04979 04980 /* We do not support derived events in overflow */ 04981 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04982 if ( ( ESI->EventInfoArray[index].derived ) && 04983 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) && 04984 !( flags & PAPI_PROFIL_FORCE_SW ) ) { 04985 papi_return( PAPI_EINVAL ); 04986 } 04987 04988 /* If no prof structures, then make sure count is 0 */ 04989 if ( prof == NULL ) { 04990 profcnt = 0; 04991 } 04992 04993 /* check all profile regions for valid scale factors of: 04994 2 (131072/65536), 04995 1 (65536/65536), 04996 or < 1 (65535 -> 2) as defined in unix profil() 04997 2/65536 is reserved for single bucket profiling 04998 {0,1}/65536 are traditionally used to terminate profiling 04999 but are unused here since PAPI uses threshold instead 05000 */ 05001 for( i = 0; i < profcnt; i++ ) { 05002 if ( !( ( prof[i].pr_scale == 131072 ) || 05003 ( ( prof[i].pr_scale <= 65536 && prof[i].pr_scale > 1 ) ) ) ) { 05004 APIDBG( "Improper scale factor: %d\n", prof[i].pr_scale ); 05005 papi_return( PAPI_EINVAL ); 05006 } 05007 } 05008 05009 /* Make sure threshold is valid */ 05010 if ( threshold < 0 ) { 05011 papi_return( PAPI_EINVAL ); 05012 } 05013 05014 /* the first time to call PAPI_sprofil */ 05015 if ( !( ESI->state & PAPI_PROFILING ) ) { 05016 if ( threshold == 0 ) { 05017 papi_return( PAPI_EINVAL ); 05018 } 05019 } 05020 05021 /* ??? */ 05022 if ( (threshold > 0) && 05023 (ESI->profile.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs) ) { 05024 papi_return( PAPI_ECNFLCT ); 05025 } 05026 05027 if ( threshold == 0 ) { 05028 for( i = 0; i < ESI->profile.event_counter; i++ ) { 05029 if ( ESI->profile.EventCode[i] == EventCode ) { 05030 break; 05031 } 05032 } 05033 05034 /* EventCode not found */ 05035 if ( i == ESI->profile.event_counter ) { 05036 papi_return( PAPI_EINVAL ); 05037 } 05038 05039 /* compact these arrays */ 05040 while ( i < ESI->profile.event_counter - 1 ) { 05041 ESI->profile.prof[i] = ESI->profile.prof[i + 1]; 05042 ESI->profile.count[i] = ESI->profile.count[i + 1]; 05043 ESI->profile.threshold[i] = ESI->profile.threshold[i + 1]; 05044 ESI->profile.EventIndex[i] = ESI->profile.EventIndex[i + 1]; 05045 ESI->profile.EventCode[i] = ESI->profile.EventCode[i + 1]; 05046 i++; 05047 } 05048 ESI->profile.prof[i] = NULL; 05049 ESI->profile.count[i] = 0; 05050 ESI->profile.threshold[i] = 0; 05051 ESI->profile.EventIndex[i] = 0; 05052 ESI->profile.EventCode[i] = 0; 05053 ESI->profile.event_counter--; 05054 } else { 05055 if ( ESI->profile.event_counter > 0 ) { 05056 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05057 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05058 papi_return( PAPI_ECNFLCT ); 05059 } 05060 if ( !( flags & PAPI_PROFIL_FORCE_SW ) && 05061 ( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05062 papi_return( PAPI_ECNFLCT ); 05063 } 05064 } 05065 05066 for( i = 0; i < ESI->profile.event_counter; i++ ) { 05067 if ( ESI->profile.EventCode[i] == EventCode ) { 05068 break; 05069 } 05070 } 05071 05072 if ( i == ESI->profile.event_counter ) { 05073 i = ESI->profile.event_counter; 05074 ESI->profile.event_counter++; 05075 ESI->profile.EventCode[i] = EventCode; 05076 } 05077 ESI->profile.prof[i] = prof; 05078 ESI->profile.count[i] = profcnt; 05079 ESI->profile.threshold[i] = threshold; 05080 ESI->profile.EventIndex[i] = index; 05081 } 05082 05083 APIDBG( "Profile event counter is %d\n", ESI->profile.event_counter ); 05084 05085 /* Clear out old flags */ 05086 if ( threshold == 0 ) { 05087 flags |= ESI->profile.flags; 05088 } 05089 05090 /* make sure no invalid flags are set */ 05091 if ( flags & 05092 ~( PAPI_PROFIL_POSIX | PAPI_PROFIL_RANDOM | PAPI_PROFIL_WEIGHTED | 05093 PAPI_PROFIL_COMPRESS | PAPI_PROFIL_BUCKETS | PAPI_PROFIL_FORCE_SW | 05094 PAPI_PROFIL_INST_EAR | PAPI_PROFIL_DATA_EAR ) ) { 05095 papi_return( PAPI_EINVAL ); 05096 } 05097 05098 /* if we have kernel-based profiling, then we're just asking for 05099 signals on interrupt. */ 05100 /* if we don't have kernel-based profiling, then we're asking for 05101 emulated PMU interrupt */ 05102 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05103 ( _papi_hwd[cidx]->cmp_info.kernel_profile == 0 ) ) { 05104 forceSW = PAPI_OVERFLOW_FORCE_SW; 05105 } 05106 05107 /* make sure one and only one bucket size is set */ 05108 buckets = flags & PAPI_PROFIL_BUCKETS; 05109 if ( !buckets ) { 05110 flags |= PAPI_PROFIL_BUCKET_16; /* default to 16 bit if nothing set */ 05111 } 05112 else { 05113 /* return error if more than one set */ 05114 if ( !( ( buckets == PAPI_PROFIL_BUCKET_16 ) || 05115 ( buckets == PAPI_PROFIL_BUCKET_32 ) || 05116 ( buckets == PAPI_PROFIL_BUCKET_64 ) ) ) { 05117 papi_return( PAPI_EINVAL ); 05118 } 05119 } 05120 05121 /* Set up the option structure for the low level */ 05122 ESI->profile.flags = flags; 05123 05124 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 05125 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05126 retval = _papi_hwd[cidx]->set_profile( ESI, index, threshold ); 05127 if ( ( retval == PAPI_OK ) && ( threshold > 0 ) ) { 05128 /* We need overflowing because we use the overflow dispatch handler */ 05129 ESI->state |= PAPI_OVERFLOWING; 05130 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 05131 } 05132 } else { 05133 retval = PAPI_overflow( EventSet, EventCode, threshold, forceSW, 05134 _papi_hwi_dummy_handler ); 05135 } 05136 05137 if ( retval < PAPI_OK ) { 05138 papi_return( retval ); /* We should undo stuff here */ 05139 } 05140 05141 /* Toggle the profiling flags and ESI state */ 05142 05143 if ( ESI->profile.event_counter >= 1 ) { 05144 ESI->state |= PAPI_PROFILING; 05145 } 05146 else { 05147 ESI->state ^= PAPI_PROFILING; 05148 ESI->profile.flags = 0; 05149 } 05150 05151 return PAPI_OK; 05152 } 05153 05331 int 05332 PAPI_profil( void *buf, unsigned bufsiz, caddr_t offset, 05333 unsigned scale, int EventSet, int EventCode, int threshold, 05334 int flags ) 05335 { 05336 EventSetInfo_t *ESI; 05337 int i; 05338 int retval; 05339 05340 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05341 if ( ESI == NULL ) 05342 papi_return( PAPI_ENOEVST ); 05343 05344 /* scale factors are checked for validity in PAPI_sprofil */ 05345 05346 if ( threshold > 0 ) { 05347 PAPI_sprofil_t *prof; 05348 05349 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05350 if ( ESI->profile.EventCode[i] == EventCode ) 05351 break; 05352 } 05353 05354 if ( i == ESI->profile.event_counter ) { 05355 prof = 05356 ( PAPI_sprofil_t * ) papi_malloc( sizeof ( PAPI_sprofil_t ) ); 05357 memset( prof, 0x0, sizeof ( PAPI_sprofil_t ) ); 05358 prof->pr_base = buf; 05359 prof->pr_size = bufsiz; 05360 prof->pr_off = offset; 05361 prof->pr_scale = scale; 05362 05363 retval = 05364 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05365 05366 if ( retval != PAPI_OK ) 05367 papi_free( prof ); 05368 } else { 05369 prof = ESI->profile.prof[i]; 05370 prof->pr_base = buf; 05371 prof->pr_size = bufsiz; 05372 prof->pr_off = offset; 05373 prof->pr_scale = scale; 05374 retval = 05375 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05376 } 05377 papi_return( retval ); 05378 } 05379 05380 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05381 if ( ESI->profile.EventCode[i] == EventCode ) 05382 break; 05383 } 05384 /* EventCode not found */ 05385 if ( i == ESI->profile.event_counter ) 05386 papi_return( PAPI_EINVAL ); 05387 05388 papi_free( ESI->profile.prof[i] ); 05389 ESI->profile.prof[i] = NULL; 05390 05391 papi_return( PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, flags ) ); 05392 } 05393 05394 /* This function sets the low level default granularity 05395 for all newly manufactured eventsets. The first function 05396 preserves API compatibility and assumes component 0; 05397 The second function takes a component argument. */ 05398 05449 int 05450 PAPI_set_granularity( int granularity ) 05451 { 05452 return ( PAPI_set_cmp_granularity( granularity, 0 ) ); 05453 } 05454 05514 int 05515 PAPI_set_cmp_granularity( int granularity, int cidx ) 05516 { 05517 PAPI_option_t ptr; 05518 05519 memset( &ptr, 0, sizeof ( ptr ) ); 05520 ptr.defgranularity.def_cidx = cidx; 05521 ptr.defgranularity.granularity = granularity; 05522 papi_return( PAPI_set_opt( PAPI_DEFGRN, &ptr ) ); 05523 } 05524 05525 /* This function sets the low level default counting domain 05526 for all newly manufactured eventsets. The first function 05527 preserves API compatibility and assumes component 0; 05528 The second function takes a component argument. */ 05529 05580 int 05581 PAPI_set_domain( int domain ) 05582 { 05583 return ( PAPI_set_cmp_domain( domain, 0 ) ); 05584 } 05585 05650 int 05651 PAPI_set_cmp_domain( int domain, int cidx ) 05652 { 05653 PAPI_option_t ptr; 05654 05655 memset( &ptr, 0, sizeof ( ptr ) ); 05656 ptr.defdomain.def_cidx = cidx; 05657 ptr.defdomain.domain = domain; 05658 papi_return( PAPI_set_opt( PAPI_DEFDOM, &ptr ) ); 05659 } 05660 05735 int 05736 PAPI_add_events( int EventSet, int *Events, int number ) 05737 { 05738 int i, retval; 05739 05740 if ( ( Events == NULL ) || ( number <= 0 ) ) 05741 papi_return( PAPI_EINVAL ); 05742 05743 for ( i = 0; i < number; i++ ) { 05744 retval = PAPI_add_event( EventSet, Events[i] ); 05745 if ( retval != PAPI_OK ) { 05746 if ( i == 0 ) 05747 papi_return( retval ); 05748 else 05749 return ( i ); 05750 } 05751 } 05752 return ( PAPI_OK ); 05753 } 05754 05822 int 05823 PAPI_remove_events( int EventSet, int *Events, int number ) 05824 { 05825 int i, retval; 05826 05827 if ( ( Events == NULL ) || ( number <= 0 ) ) 05828 papi_return( PAPI_EINVAL ); 05829 05830 for ( i = 0; i < number; i++ ) { 05831 retval = PAPI_remove_event( EventSet, Events[i] ); 05832 if ( retval != PAPI_OK ) { 05833 if ( i == 0 ) 05834 papi_return( retval ); 05835 else 05836 return ( i ); 05837 } 05838 } 05839 return ( PAPI_OK ); 05840 } 05841 05882 int 05883 PAPI_list_events( int EventSet, int *Events, int *number ) 05884 { 05885 EventSetInfo_t *ESI; 05886 int i, j; 05887 05888 if ( ( Events == NULL ) || ( *number <= 0 ) ) 05889 papi_return( PAPI_EINVAL ); 05890 05891 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05892 if ( !ESI ) 05893 papi_return( PAPI_ENOEVST ); 05894 05895 for ( i = 0, j = 0; j < ESI->NumberOfEvents; i++ ) { 05896 if ( ( int ) ESI->EventInfoArray[i].event_code != PAPI_NULL ) { 05897 Events[j] = ( int ) ESI->EventInfoArray[i].event_code; 05898 j++; 05899 if ( j == *number ) 05900 break; 05901 } 05902 } 05903 05904 *number = j; 05905 05906 return ( PAPI_OK ); 05907 } 05908 05909 /* xxx This is OS dependent, not component dependent, right? */ 05935 int 05936 PAPI_get_dmem_info( PAPI_dmem_info_t * dest ) 05937 { 05938 if ( dest == NULL ) 05939 return PAPI_EINVAL; 05940 05941 memset( ( void * ) dest, 0x0, sizeof ( PAPI_dmem_info_t ) ); 05942 return ( _papi_os_vector.get_dmem_info( dest ) ); 05943 } 05944 05945 05989 const PAPI_exe_info_t * 05990 PAPI_get_executable_info( void ) 05991 { 05992 PAPI_option_t ptr; 05993 int retval; 05994 05995 memset( &ptr, 0, sizeof ( ptr ) ); 05996 retval = PAPI_get_opt( PAPI_EXEINFO, &ptr ); 05997 if ( retval == PAPI_OK ) 05998 return ( ptr.exe_info ); 05999 else 06000 return ( NULL ); 06001 } 06002 06019 const PAPI_shlib_info_t * 06020 PAPI_get_shared_lib_info( void ) 06021 { 06022 PAPI_option_t ptr; 06023 int retval; 06024 06025 memset( &ptr, 0, sizeof ( ptr ) ); 06026 retval = PAPI_get_opt( PAPI_SHLIBINFO, &ptr ); 06027 if ( retval == PAPI_OK ) 06028 return ( ptr.shlib_info ); 06029 else 06030 return ( NULL ); 06031 } 06060 const PAPI_hw_info_t * 06061 PAPI_get_hardware_info( void ) 06062 { 06063 PAPI_option_t ptr; 06064 int retval; 06065 06066 memset( &ptr, 0, sizeof ( ptr ) ); 06067 retval = PAPI_get_opt( PAPI_HWINFO, &ptr ); 06068 if ( retval == PAPI_OK ) 06069 return ( ptr.hw_info ); 06070 else 06071 return ( NULL ); 06072 } 06073 06074 06075 /* The next 4 timing functions always use component 0 */ 06076 06092 long long 06093 PAPI_get_real_cyc( void ) 06094 { 06095 return ( _papi_os_vector.get_real_cycles( ) ); 06096 } 06097 06111 /* FIXME */ 06112 long long 06113 PAPI_get_real_nsec( void ) 06114 { 06115 return ( ( _papi_os_vector.get_real_nsec( ))); 06116 06117 } 06118 06139 long long 06140 PAPI_get_real_usec( void ) 06141 { 06142 return ( _papi_os_vector.get_real_usec( ) ); 06143 } 06144 06175 long long 06176 PAPI_get_virt_cyc( void ) 06177 { 06178 06179 return ( ( long long ) _papi_os_vector.get_virt_cycles( ) ); 06180 } 06181 06205 long long 06206 PAPI_get_virt_nsec( void ) 06207 { 06208 06209 return ( ( _papi_os_vector.get_virt_nsec())); 06210 06211 } 06212 06247 long long 06248 PAPI_get_virt_usec( void ) 06249 { 06250 06251 return ( ( long long ) _papi_os_vector.get_virt_usec() ); 06252 } 06253 06278 int 06279 PAPI_lock( int lck ) 06280 { 06281 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06282 papi_return( PAPI_EINVAL ); 06283 06284 papi_return( _papi_hwi_lock( lck ) ); 06285 } 06286 06298 int 06299 PAPI_unlock( int lck ) 06300 { 06301 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06302 papi_return( PAPI_EINVAL ); 06303 06304 papi_return( _papi_hwi_unlock( lck ) ); 06305 } 06306 06340 int 06341 PAPI_is_initialized( void ) 06342 { 06343 return ( init_level ); 06344 } 06345 06346 /* This function maps the overflow_vector to event indexes in the event 06347 set, so that user can know which PAPI event overflowed. 06348 int *array---- an array of event indexes in eventset; the first index 06349 maps to the highest set bit in overflow_vector 06350 int *number--- this is an input/output parameter, user should put the 06351 size of the array into this parameter, after the function 06352 is executed, the number of indexes in *array is written 06353 to this parameter 06354 */ 06355 06394 int 06395 PAPI_get_overflow_event_index( int EventSet, long long overflow_vector, 06396 int *array, int *number ) 06397 { 06398 EventSetInfo_t *ESI; 06399 int set_bit, j, pos; 06400 int count = 0, k; 06401 06402 if ( overflow_vector == ( long long ) 0 ) 06403 papi_return( PAPI_EINVAL ); 06404 06405 if ( ( array == NULL ) || ( number == NULL ) ) 06406 papi_return( PAPI_EINVAL ); 06407 06408 if ( *number < 1 ) 06409 papi_return( PAPI_EINVAL ); 06410 06411 ESI = _papi_hwi_lookup_EventSet( EventSet ); 06412 if ( ESI == NULL ) 06413 papi_return( PAPI_ENOEVST ); 06414 06415 /* in case the eventset is empty */ 06416 if ( ESI->NumberOfEvents == 0 ) 06417 papi_return( PAPI_EINVAL ); 06418 06419 while ( ( set_bit = ffsll( overflow_vector ) ) ) { 06420 set_bit -= 1; 06421 overflow_vector ^= ( long long ) 1 << set_bit; 06422 for ( j = 0; j < ESI->NumberOfEvents; j++ ) { 06423 for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0; k++ ) { 06424 pos = ESI->EventInfoArray[j].pos[k]; 06425 if ( ( set_bit == pos ) && 06426 ( ( ESI->EventInfoArray[j].derived == NOT_DERIVED ) || 06427 ( ESI->EventInfoArray[j].derived == DERIVED_CMPD ) ) ) { 06428 array[count++] = j; 06429 if ( count == *number ) 06430 return PAPI_OK; 06431 06432 break; 06433 } 06434 } 06435 } 06436 } 06437 *number = count; 06438 return PAPI_OK; 06439 } 06440 06441 06459 int 06460 PAPI_get_event_component( int EventCode) 06461 { 06462 return _papi_hwi_component_index( EventCode); 06463 } 06464 06486 int PAPI_get_component_index(char *name) 06487 { 06488 int cidx; 06489 06490 const PAPI_component_info_t *cinfo; 06491 06492 for(cidx=0;cidx<papi_num_components;cidx++) { 06493 06494 cinfo=PAPI_get_component_info(cidx); 06495 if (cinfo==NULL) return PAPI_ENOCMP; 06496 06497 if (!strncmp(name,cinfo->name,strlen(cinfo->name))) { 06498 return cidx; 06499 } 06500 } 06501 06502 return PAPI_ENOCMP; 06503 } 06504 06505 06541 int 06542 PAPI_disable_component( int cidx ) 06543 { 06544 06545 const PAPI_component_info_t *cinfo; 06546 06547 /* Can only run before PAPI_library_init() is called */ 06548 if (init_level != PAPI_NOT_INITED) { 06549 return PAPI_ENOINIT; 06550 } 06551 06552 cinfo=PAPI_get_component_info(cidx); 06553 if (cinfo==NULL) return PAPI_ENOCMP; 06554 06555 ((PAPI_component_info_t *)cinfo)->disabled=1; 06556 strcpy(((PAPI_component_info_t *)cinfo)->disabled_reason, 06557 "Disabled by PAPI_disable_component()"); 06558 06559 return PAPI_OK; 06560 06561 } 06562 06591 int 06592 PAPI_disable_component_by_name( char *name ) 06593 { 06594 int cidx; 06595 06596 /* I can only be called before init time */ 06597 if (init_level!=PAPI_NOT_INITED) { 06598 return PAPI_ENOINIT; 06599 } 06600 06601 cidx = PAPI_get_component_index(name); 06602 if (cidx>=0) { 06603 return PAPI_disable_component(cidx); 06604 } 06605 06606 return PAPI_ENOCMP; 06607 }