|
PAPI
5.0.1.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 "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 01565 int 01566 PAPI_add_event( int EventSet, int EventCode ) 01567 { 01568 APIDBG("Entry: EventSet: %d, EventCode: 0x%x\n", EventSet, EventCode); 01569 EventSetInfo_t *ESI; 01570 01571 /* Is the EventSet already in existence? */ 01572 01573 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01574 if ( ESI == NULL ) 01575 papi_return( PAPI_ENOEVST ); 01576 01577 /* Check argument for validity */ 01578 01579 if ( ( ( EventCode & PAPI_PRESET_MASK ) == 0 ) && 01580 ( EventCode & PAPI_NATIVE_MASK ) == 0 ) 01581 papi_return( PAPI_EINVAL ); 01582 01583 /* Of course, it must be stopped in order to modify it. */ 01584 01585 if ( ESI->state & PAPI_RUNNING ) 01586 papi_return( PAPI_EISRUN ); 01587 01588 /* Now do the magic. */ 01589 01590 papi_return( _papi_hwi_add_event( ESI, EventCode ) ); 01591 } 01592 01660 int 01661 PAPI_remove_event( int EventSet, int EventCode ) 01662 { 01663 EventSetInfo_t *ESI; 01664 int i,retval; 01665 01666 /* check for pre-existing ESI */ 01667 01668 ESI = _papi_hwi_lookup_EventSet( EventSet ); 01669 if ( ESI == NULL ) 01670 papi_return( PAPI_ENOEVST ); 01671 01672 /* Check argument for validity */ 01673 01674 if ( ( !IS_PRESET(EventCode) ) && 01675 ( !IS_NATIVE(EventCode) ) && 01676 ( !IS_USER_DEFINED(EventCode) )) 01677 papi_return( PAPI_EINVAL ); 01678 01679 /* Of course, it must be stopped in order to modify it. */ 01680 01681 if ( !( ESI->state & PAPI_STOPPED ) ) 01682 papi_return( PAPI_EISRUN ); 01683 01684 /* if the state is PAPI_OVERFLOWING, you must first call 01685 PAPI_overflow with threshold=0 to remove the overflow flag */ 01686 01687 /* Turn off the event that is overflowing */ 01688 if ( ESI->state & PAPI_OVERFLOWING ) { 01689 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 01690 if ( ESI->overflow.EventCode[i] == EventCode ) { 01691 retval = PAPI_overflow( EventSet, EventCode, 0, 0, 01692 ESI->overflow.handler ); 01693 if (retval!=PAPI_OK) return retval; 01694 break; 01695 } 01696 } 01697 } 01698 01699 /* force the user to call PAPI_profil to clear the PAPI_PROFILING flag */ 01700 if ( ESI->state & PAPI_PROFILING ) { 01701 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 01702 if ( ESI->profile.EventCode[i] == EventCode ) { 01703 PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, 0 ); 01704 break; 01705 } 01706 } 01707 } 01708 01709 /* Now do the magic. */ 01710 01711 papi_return( _papi_hwi_remove_event( ESI, EventCode ) ); 01712 } 01713 01777 int 01778 PAPI_add_named_event( int EventSet, char *EventName ) 01779 { 01780 int ret, code; 01781 01782 ret = PAPI_event_name_to_code( EventName, &code ); 01783 if ( ret == PAPI_OK ) ret = PAPI_add_event( EventSet, code ); 01784 papi_return( ret ); 01785 } 01786 01854 int 01855 PAPI_remove_named_event( int EventSet, char *EventName ) 01856 { 01857 int ret, code; 01858 01859 ret = PAPI_event_name_to_code( EventName, &code ); 01860 if ( ret == PAPI_OK ) ret = PAPI_remove_event( EventSet, code ); 01861 papi_return( ret ); 01862 } 01863 01905 int 01906 PAPI_destroy_eventset( int *EventSet ) 01907 { 01908 EventSetInfo_t *ESI; 01909 01910 APIDBG("Destroying Eventset %d\n",*EventSet); 01911 01912 /* check for pre-existing ESI */ 01913 01914 if ( EventSet == NULL ) 01915 papi_return( PAPI_EINVAL ); 01916 01917 ESI = _papi_hwi_lookup_EventSet( *EventSet ); 01918 if ( ESI == NULL ) 01919 papi_return( PAPI_ENOEVST ); 01920 01921 if ( !( ESI->state & PAPI_STOPPED ) ) 01922 papi_return( PAPI_EISRUN ); 01923 01924 if ( ESI->NumberOfEvents ) 01925 papi_return( PAPI_EINVAL ); 01926 01927 _papi_hwi_remove_EventSet( ESI ); 01928 *EventSet = PAPI_NULL; 01929 01930 return PAPI_OK; 01931 } 01932 01933 /* simply checks for valid EventSet, calls component start() call */ 01987 int 01988 PAPI_start( int EventSet ) 01989 { 01990 APIDBG("Entry: EventSet: %d\n", EventSet); 01991 int is_dirty=0; 01992 int retval; 01993 EventSetInfo_t *ESI; 01994 ThreadInfo_t *thread = NULL; 01995 CpuInfo_t *cpu = NULL; 01996 hwd_context_t *context; 01997 int cidx; 01998 01999 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02000 if ( ESI == NULL ) { 02001 papi_return( PAPI_ENOEVST ); 02002 } 02003 02004 cidx = valid_ESI_component( ESI ); 02005 if ( cidx < 0 ) { 02006 papi_return( cidx ); 02007 } 02008 02009 /* only one event set per thread/cpu can be running at any time, */ 02010 /* so if another event set is running, the user must stop that */ 02011 /* event set explicitly */ 02012 02013 thread = ESI->master; 02014 cpu = ESI->CpuInfo; 02015 02016 /* check cpu attached case first */ 02017 if (ESI->state & PAPI_CPU_ATTACHED) { 02018 if ( cpu->running_eventset[cidx] ) { 02019 papi_return( PAPI_EISRUN ); 02020 } 02021 } else { 02022 if ( thread->running_eventset[cidx] ) { 02023 papi_return( PAPI_EISRUN ); 02024 } 02025 } 02026 02027 /* Check that there are added events */ 02028 if ( ESI->NumberOfEvents < 1 ) { 02029 papi_return( PAPI_EINVAL ); 02030 } 02031 02032 /* If multiplexing is enabled for this eventset, 02033 call John May's code. */ 02034 02035 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02036 retval = MPX_start( ESI->multiplex.mpx_evset ); 02037 if ( retval != PAPI_OK ) { 02038 papi_return( retval ); 02039 } 02040 02041 /* Update the state of this EventSet */ 02042 ESI->state ^= PAPI_STOPPED; 02043 ESI->state |= PAPI_RUNNING; 02044 02045 return PAPI_OK; 02046 } 02047 02048 /* get the context we should use for this event set */ 02049 context = _papi_hwi_get_context( ESI, &is_dirty ); 02050 if (is_dirty) { 02051 /* we need to reset the context state because it was last used */ 02052 /* for some other event set and does not contain the information */ 02053 /* for our events. */ 02054 retval = _papi_hwd[ESI->CmpIdx]->update_control_state( 02055 ESI->ctl_state, 02056 ESI->NativeInfoArray, 02057 ESI->NativeCount, 02058 context); 02059 if ( retval != PAPI_OK ) { 02060 papi_return( retval ); 02061 } 02062 02063 /* now that the context contains this event sets information, */ 02064 /* make sure the position array in the EventInfoArray is correct */ 02065 02066 /* We have to do this because ->update_control_state() can */ 02067 /* in theory re-order the native events out from under us. */ 02068 _papi_hwi_map_events_to_native( ESI ); 02069 02070 } 02071 02072 /* If overflowing is enabled, turn it on */ 02073 if ( ( ESI->state & PAPI_OVERFLOWING ) && 02074 !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02075 retval = _papi_hwi_start_signal( _papi_os_info.itimer_sig, 02076 NEED_CONTEXT, cidx ); 02077 if ( retval != PAPI_OK ) { 02078 papi_return( retval ); 02079 } 02080 02081 /* Update the state of this EventSet and thread */ 02082 /* before to avoid races */ 02083 ESI->state ^= PAPI_STOPPED; 02084 ESI->state |= PAPI_RUNNING; 02085 /* can not be attached to thread or cpu if overflowing */ 02086 thread->running_eventset[cidx] = ESI; 02087 02088 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02089 if ( retval != PAPI_OK ) { 02090 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02091 ESI->state ^= PAPI_RUNNING; 02092 ESI->state |= PAPI_STOPPED; 02093 thread->running_eventset[cidx] = NULL; 02094 papi_return( retval ); 02095 } 02096 02097 retval = _papi_hwi_start_timer( _papi_os_info.itimer_num, 02098 _papi_os_info.itimer_sig, 02099 _papi_os_info.itimer_ns ); 02100 if ( retval != PAPI_OK ) { 02101 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02102 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02103 ESI->state ^= PAPI_RUNNING; 02104 ESI->state |= PAPI_STOPPED; 02105 thread->running_eventset[cidx] = NULL; 02106 papi_return( retval ); 02107 } 02108 } else { 02109 /* Update the state of this EventSet and thread before */ 02110 /* to avoid races */ 02111 ESI->state ^= PAPI_STOPPED; 02112 ESI->state |= PAPI_RUNNING; 02113 02114 /* if not attached to cpu or another process */ 02115 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02116 if ( !( ESI->state & PAPI_ATTACHED ) ) { 02117 thread->running_eventset[cidx] = ESI; 02118 } 02119 } else { 02120 cpu->running_eventset[cidx] = ESI; 02121 } 02122 02123 retval = _papi_hwd[cidx]->start( context, ESI->ctl_state ); 02124 if ( retval != PAPI_OK ) { 02125 _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02126 ESI->state ^= PAPI_RUNNING; 02127 ESI->state |= PAPI_STOPPED; 02128 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02129 if ( !( ESI->state & PAPI_ATTACHED ) ) 02130 thread->running_eventset[cidx] = NULL; 02131 } else { 02132 cpu->running_eventset[cidx] = NULL; 02133 } 02134 papi_return( retval ); 02135 } 02136 } 02137 02138 return retval; 02139 } 02140 02141 /* checks for valid EventSet, calls component stop() function. */ 02192 int 02193 PAPI_stop( int EventSet, long long *values ) 02194 { 02195 APIDBG("Entry: EventSet: %d, values: %p\n", EventSet, values); 02196 EventSetInfo_t *ESI; 02197 hwd_context_t *context; 02198 int cidx, retval; 02199 02200 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02201 if ( ESI == NULL ) 02202 papi_return( PAPI_ENOEVST ); 02203 02204 cidx = valid_ESI_component( ESI ); 02205 if ( cidx < 0 ) 02206 papi_return( cidx ); 02207 02208 if ( !( ESI->state & PAPI_RUNNING ) ) 02209 papi_return( PAPI_ENOTRUN ); 02210 02211 /* If multiplexing is enabled for this eventset, turn if off */ 02212 02213 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02214 retval = MPX_stop( ESI->multiplex.mpx_evset, values ); 02215 if ( retval != PAPI_OK ) 02216 papi_return( retval ); 02217 02218 /* Update the state of this EventSet */ 02219 02220 ESI->state ^= PAPI_RUNNING; 02221 ESI->state |= PAPI_STOPPED; 02222 02223 return ( PAPI_OK ); 02224 } 02225 02226 /* get the context we should use for this event set */ 02227 context = _papi_hwi_get_context( ESI, NULL ); 02228 /* Read the current counter values into the EventSet */ 02229 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02230 if ( retval != PAPI_OK ) 02231 papi_return( retval ); 02232 02233 /* Remove the control bits from the active counter config. */ 02234 retval = _papi_hwd[cidx]->stop( context, ESI->ctl_state ); 02235 if ( retval != PAPI_OK ) 02236 papi_return( retval ); 02237 if ( values ) 02238 memcpy( values, ESI->sw_stop, 02239 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02240 02241 /* If kernel profiling is in use, flush and process the kernel buffer */ 02242 02243 if ( ESI->state & PAPI_PROFILING ) { 02244 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 02245 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02246 retval = _papi_hwd[cidx]->stop_profiling( ESI->master, ESI ); 02247 if ( retval < PAPI_OK ) 02248 papi_return( retval ); 02249 } 02250 } 02251 02252 /* If overflowing is enabled, turn it off */ 02253 02254 if ( ESI->state & PAPI_OVERFLOWING ) { 02255 if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) { 02256 retval = _papi_hwi_stop_timer( _papi_os_info.itimer_num, 02257 _papi_os_info.itimer_sig ); 02258 if ( retval != PAPI_OK ) 02259 papi_return( retval ); 02260 _papi_hwi_stop_signal( _papi_os_info.itimer_sig ); 02261 } 02262 } 02263 02264 /* Update the state of this EventSet */ 02265 02266 ESI->state ^= PAPI_RUNNING; 02267 ESI->state |= PAPI_STOPPED; 02268 02269 /* Update the running event set for this thread */ 02270 if ( !(ESI->state & PAPI_CPU_ATTACHED) ) { 02271 if ( !( ESI->state & PAPI_ATTACHED )) 02272 ESI->master->running_eventset[cidx] = NULL; 02273 } else { 02274 ESI->CpuInfo->running_eventset[cidx] = NULL; 02275 } 02276 02277 #if defined(DEBUG) 02278 if ( _papi_hwi_debug & DEBUG_API ) { 02279 int i; 02280 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02281 APIDBG( "PAPI_stop ESI->sw_stop[%d]:\t%llu\n", i, ESI->sw_stop[i] ); 02282 } 02283 } 02284 #endif 02285 02286 return ( PAPI_OK ); 02287 } 02288 02337 int 02338 PAPI_reset( int EventSet ) 02339 { 02340 int retval = PAPI_OK; 02341 EventSetInfo_t *ESI; 02342 hwd_context_t *context; 02343 int cidx; 02344 02345 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02346 if ( ESI == NULL ) 02347 papi_return( PAPI_ENOEVST ); 02348 02349 cidx = valid_ESI_component( ESI ); 02350 if ( cidx < 0 ) 02351 papi_return( cidx ); 02352 02353 if ( ESI->state & PAPI_RUNNING ) { 02354 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02355 retval = MPX_reset( ESI->multiplex.mpx_evset ); 02356 } else { 02357 /* If we're not the only one running, then just 02358 read the current values into the ESI->start 02359 array. This holds the starting value for counters 02360 that are shared. */ 02361 /* get the context we should use for this event set */ 02362 context = _papi_hwi_get_context( ESI, NULL ); 02363 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02364 } 02365 } else { 02366 #ifdef __bgp__ 02367 // For BG/P, we always want to reset the 'real' hardware counters. The counters 02368 // can be controlled via multiple interfaces, and we need to ensure that the values 02369 // are truly zero... 02370 /* get the context we should use for this event set */ 02371 context = _papi_hwi_get_context( ESI, NULL ); 02372 retval = _papi_hwd[cidx]->reset( context, ESI->ctl_state ); 02373 #endif 02374 memset( ESI->sw_stop, 0x00, 02375 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02376 } 02377 02378 APIDBG( "PAPI_reset returns %d\n", retval ); 02379 papi_return( retval ); 02380 } 02381 02438 int 02439 PAPI_read( int EventSet, long long *values ) 02440 { 02441 EventSetInfo_t *ESI; 02442 hwd_context_t *context; 02443 int cidx, retval = PAPI_OK; 02444 02445 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02446 if ( ESI == NULL ) 02447 papi_return( PAPI_ENOEVST ); 02448 02449 cidx = valid_ESI_component( ESI ); 02450 if ( cidx < 0 ) 02451 papi_return( cidx ); 02452 02453 if ( values == NULL ) 02454 papi_return( PAPI_EINVAL ); 02455 02456 if ( ESI->state & PAPI_RUNNING ) { 02457 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02458 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02459 } else { 02460 /* get the context we should use for this event set */ 02461 context = _papi_hwi_get_context( ESI, NULL ); 02462 retval = _papi_hwi_read( context, ESI, values ); 02463 } 02464 if ( retval != PAPI_OK ) 02465 papi_return( retval ); 02466 } else { 02467 memcpy( values, ESI->sw_stop, 02468 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02469 } 02470 02471 #if defined(DEBUG) 02472 if ( ISLEVEL( DEBUG_API ) ) { 02473 int i; 02474 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02475 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02476 } 02477 } 02478 #endif 02479 02480 APIDBG( "PAPI_read returns %d\n", retval ); 02481 return ( PAPI_OK ); 02482 } 02483 02528 int 02529 PAPI_read_ts( int EventSet, long long *values, long long *cycles ) 02530 { 02531 EventSetInfo_t *ESI; 02532 hwd_context_t *context; 02533 int cidx, retval = PAPI_OK; 02534 02535 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02536 if ( ESI == NULL ) 02537 papi_return( PAPI_ENOEVST ); 02538 02539 cidx = valid_ESI_component( ESI ); 02540 if ( cidx < 0 ) 02541 papi_return( cidx ); 02542 02543 if ( values == NULL ) 02544 papi_return( PAPI_EINVAL ); 02545 02546 if ( ESI->state & PAPI_RUNNING ) { 02547 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02548 retval = MPX_read( ESI->multiplex.mpx_evset, values, 0 ); 02549 } else { 02550 /* get the context we should use for this event set */ 02551 context = _papi_hwi_get_context( ESI, NULL ); 02552 retval = _papi_hwi_read( context, ESI, values ); 02553 } 02554 if ( retval != PAPI_OK ) 02555 papi_return( retval ); 02556 } else { 02557 memcpy( values, ESI->sw_stop, 02558 ( size_t ) ESI->NumberOfEvents * sizeof ( long long ) ); 02559 } 02560 02561 *cycles = _papi_os_vector.get_real_cycles( ); 02562 02563 #if defined(DEBUG) 02564 if ( ISLEVEL( DEBUG_API ) ) { 02565 int i; 02566 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02567 APIDBG( "PAPI_read values[%d]:\t%lld\n", i, values[i] ); 02568 } 02569 } 02570 #endif 02571 02572 APIDBG( "PAPI_read_ts returns %d\n", retval ); 02573 return PAPI_OK; 02574 } 02575 02624 int 02625 PAPI_accum( int EventSet, long long *values ) 02626 { 02627 EventSetInfo_t *ESI; 02628 hwd_context_t *context; 02629 int i, cidx, retval; 02630 long long a, b, c; 02631 02632 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02633 if ( ESI == NULL ) 02634 papi_return( PAPI_ENOEVST ); 02635 02636 cidx = valid_ESI_component( ESI ); 02637 if ( cidx < 0 ) 02638 papi_return( cidx ); 02639 02640 if ( values == NULL ) 02641 papi_return( PAPI_EINVAL ); 02642 02643 if ( ESI->state & PAPI_RUNNING ) { 02644 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02645 retval = MPX_read( ESI->multiplex.mpx_evset, ESI->sw_stop, 0 ); 02646 } else { 02647 /* get the context we should use for this event set */ 02648 context = _papi_hwi_get_context( ESI, NULL ); 02649 retval = _papi_hwi_read( context, ESI, ESI->sw_stop ); 02650 } 02651 if ( retval != PAPI_OK ) 02652 papi_return( retval ); 02653 } 02654 02655 for ( i = 0; i < ESI->NumberOfEvents; i++ ) { 02656 a = ESI->sw_stop[i]; 02657 b = values[i]; 02658 c = a + b; 02659 values[i] = c; 02660 } 02661 02662 papi_return( PAPI_reset( EventSet ) ); 02663 } 02664 02691 int 02692 PAPI_write( int EventSet, long long *values ) 02693 { 02694 int cidx, retval = PAPI_OK; 02695 EventSetInfo_t *ESI; 02696 hwd_context_t *context; 02697 02698 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02699 if ( ESI == NULL ) 02700 papi_return( PAPI_ENOEVST ); 02701 02702 cidx = valid_ESI_component( ESI ); 02703 if ( cidx < 0 ) 02704 papi_return( cidx ); 02705 02706 if ( values == NULL ) 02707 papi_return( PAPI_EINVAL ); 02708 02709 if ( ESI->state & PAPI_RUNNING ) { 02710 /* get the context we should use for this event set */ 02711 context = _papi_hwi_get_context( ESI, NULL ); 02712 retval = _papi_hwd[cidx]->write( context, ESI->ctl_state, values ); 02713 if ( retval != PAPI_OK ) 02714 return ( retval ); 02715 } 02716 02717 memcpy( ESI->hw_start, values, 02718 ( size_t ) _papi_hwd[cidx]->cmp_info.num_cntrs * 02719 sizeof ( long long ) ); 02720 02721 return ( retval ); 02722 } 02723 02766 int 02767 PAPI_cleanup_eventset( int EventSet ) 02768 { 02769 EventSetInfo_t *ESI; 02770 int i, cidx, total, retval; 02771 02772 APIDBG("Attempting to cleanup Eventset %d\n",EventSet); 02773 02774 /* Is the EventSet already in existence? */ 02775 02776 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02777 if ( ESI == NULL ) 02778 papi_return( PAPI_ENOEVST ); 02779 02780 /* if the eventset has no index and no events, return OK 02781 otherwise return NOCMP */ 02782 cidx = valid_ESI_component( ESI ); 02783 if ( cidx < 0 ) { 02784 if ( ESI->NumberOfEvents ) 02785 papi_return( cidx ); 02786 papi_return( PAPI_OK ); 02787 } 02788 02789 /* Of course, it must be stopped in order to modify it. */ 02790 02791 if ( ESI->state & PAPI_RUNNING ) 02792 papi_return( PAPI_EISRUN ); 02793 02794 /* clear overflow flag and turn off hardware overflow handler */ 02795 if ( ESI->state & PAPI_OVERFLOWING ) { 02796 total = ESI->overflow.event_counter; 02797 for ( i = 0; i < total; i++ ) { 02798 retval = PAPI_overflow( EventSet, 02799 ESI->overflow.EventCode[0], 0, 0, NULL ); 02800 if ( retval != PAPI_OK ) 02801 papi_return( retval ); 02802 } 02803 } 02804 02805 /* clear profile flag and turn off hardware profile handler */ 02806 if ( ( ESI->state & PAPI_PROFILING ) && 02807 _papi_hwd[cidx]->cmp_info.hardware_intr && 02808 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 02809 total = ESI->profile.event_counter; 02810 for ( i = 0; i < total; i++ ) { 02811 retval = 02812 PAPI_sprofil( NULL, 0, EventSet, ESI->profile.EventCode[0], 0, 02813 PAPI_PROFIL_POSIX ); 02814 if ( retval != PAPI_OK ) 02815 papi_return( retval ); 02816 } 02817 } 02818 02819 if ( _papi_hwi_is_sw_multiplex( ESI ) ) { 02820 retval = MPX_cleanup( &ESI->multiplex.mpx_evset ); 02821 if ( retval != PAPI_OK ) 02822 papi_return( retval ); 02823 } 02824 02825 retval = _papi_hwd[cidx]->cleanup_eventset( ESI->ctl_state ); 02826 if ( retval != PAPI_OK ) 02827 papi_return( retval ); 02828 02829 /* Now do the magic */ 02830 papi_return( _papi_hwi_cleanup_eventset( ESI ) ); 02831 } 02832 02860 int 02861 PAPI_multiplex_init( void ) 02862 { 02863 int retval; 02864 02865 retval = mpx_init( _papi_os_info.itimer_ns ); 02866 papi_return( retval ); 02867 } 02868 02929 int 02930 PAPI_state( int EventSet, int *status ) 02931 { 02932 EventSetInfo_t *ESI; 02933 02934 if ( status == NULL ) 02935 papi_return( PAPI_EINVAL ); 02936 02937 /* check for good EventSetIndex value */ 02938 02939 ESI = _papi_hwi_lookup_EventSet( EventSet ); 02940 if ( ESI == NULL ) 02941 papi_return( PAPI_ENOEVST ); 02942 02943 /*read status FROM ESI->state */ 02944 02945 *status = ESI->state; 02946 02947 return ( PAPI_OK ); 02948 } 02949 03000 int 03001 PAPI_set_debug( int level ) 03002 { 03003 PAPI_option_t option; 03004 03005 memset( &option, 0x0, sizeof ( option ) ); 03006 option.debug.level = level; 03007 option.debug.handler = _papi_hwi_debug_handler; 03008 return ( PAPI_set_opt( PAPI_DEBUG, &option ) ); 03009 } 03010 03011 /* Attaches to or detaches from the specified thread id */ 03012 inline_static int 03013 _papi_set_attach( int option, int EventSet, unsigned long tid ) 03014 { 03015 PAPI_option_t attach; 03016 03017 memset( &attach, 0x0, sizeof ( attach ) ); 03018 attach.attach.eventset = EventSet; 03019 attach.attach.tid = tid; 03020 return ( PAPI_set_opt( option, &attach ) ); 03021 } 03022 03076 int 03077 PAPI_attach( int EventSet, unsigned long tid ) 03078 { 03079 return ( _papi_set_attach( PAPI_ATTACH, EventSet, tid ) ); 03080 } 03081 03135 int 03136 PAPI_detach( int EventSet ) 03137 { 03138 return ( _papi_set_attach( PAPI_DETACH, EventSet, 0 ) ); 03139 } 03140 03209 int 03210 PAPI_set_multiplex( int EventSet ) 03211 { 03212 PAPI_option_t mpx; 03213 EventSetInfo_t *ESI; 03214 int cidx; 03215 int ret; 03216 03217 /* Is the EventSet already in existence? */ 03218 03219 ESI = _papi_hwi_lookup_EventSet( EventSet ); 03220 03221 if ( ESI == NULL ) 03222 papi_return( PAPI_ENOEVST ); 03223 03224 /* if the eventset has no index return NOCMP */ 03225 cidx = valid_ESI_component( ESI ); 03226 if ( cidx < 0 ) 03227 papi_return( cidx ); 03228 03229 if ( ( ret = mpx_check( EventSet ) ) != PAPI_OK ) 03230 papi_return( ret ); 03231 03232 memset( &mpx, 0x0, sizeof ( mpx ) ); 03233 mpx.multiplex.eventset = EventSet; 03234 mpx.multiplex.flags = PAPI_MULTIPLEX_DEFAULT; 03235 mpx.multiplex.ns = _papi_os_info.itimer_ns; 03236 return ( PAPI_set_opt( PAPI_MULTIPLEX, &mpx ) ); 03237 } 03238 03339 int 03340 PAPI_set_opt( int option, PAPI_option_t * ptr ) 03341 { 03342 APIDBG("Entry: option: %d, ptr: %p\n", option, ptr); 03343 03344 _papi_int_option_t internal; 03345 int retval = PAPI_OK; 03346 hwd_context_t *context; 03347 int cidx; 03348 03349 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 03350 papi_return( PAPI_ENOINIT ); 03351 if ( ptr == NULL ) 03352 papi_return( PAPI_EINVAL ); 03353 03354 memset( &internal, 0x0, sizeof ( _papi_int_option_t ) ); 03355 03356 switch ( option ) { 03357 case PAPI_DETACH: 03358 { 03359 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03360 if ( internal.attach.ESI == NULL ) 03361 papi_return( PAPI_ENOEVST ); 03362 03363 cidx = valid_ESI_component( internal.attach.ESI ); 03364 if ( cidx < 0 ) 03365 papi_return( cidx ); 03366 03367 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03368 papi_return( PAPI_ECMP ); 03369 03370 /* if attached to a cpu, return an error */ 03371 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03372 papi_return( PAPI_ECMP ); 03373 03374 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03375 papi_return( PAPI_EISRUN ); 03376 03377 if ( ( internal.attach.ESI->state & PAPI_ATTACHED ) == 0 ) 03378 papi_return( PAPI_EINVAL ); 03379 03380 internal.attach.tid = internal.attach.ESI->attach.tid; 03381 /* get the context we should use for this event set */ 03382 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03383 retval = _papi_hwd[cidx]->ctl( context, PAPI_DETACH, &internal ); 03384 if ( retval != PAPI_OK ) 03385 papi_return( retval ); 03386 03387 internal.attach.ESI->state ^= PAPI_ATTACHED; 03388 internal.attach.ESI->attach.tid = 0; 03389 return ( PAPI_OK ); 03390 } 03391 case PAPI_ATTACH: 03392 { 03393 internal.attach.ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 03394 if ( internal.attach.ESI == NULL ) 03395 papi_return( PAPI_ENOEVST ); 03396 03397 cidx = valid_ESI_component( internal.attach.ESI ); 03398 if ( cidx < 0 ) 03399 papi_return( cidx ); 03400 03401 if ( _papi_hwd[cidx]->cmp_info.attach == 0 ) 03402 papi_return( PAPI_ECMP ); 03403 03404 if ( ( internal.attach.ESI->state & PAPI_STOPPED ) == 0 ) 03405 papi_return( PAPI_EISRUN ); 03406 03407 if ( internal.attach.ESI->state & PAPI_ATTACHED ) 03408 papi_return( PAPI_EINVAL ); 03409 03410 /* if attached to a cpu, return an error */ 03411 if (internal.attach.ESI->state & PAPI_CPU_ATTACHED) 03412 papi_return( PAPI_ECMP ); 03413 03414 internal.attach.tid = ptr->attach.tid; 03415 /* get the context we should use for this event set */ 03416 context = _papi_hwi_get_context( internal.attach.ESI, NULL ); 03417 retval = _papi_hwd[cidx]->ctl( context, PAPI_ATTACH, &internal ); 03418 if ( retval != PAPI_OK ) 03419 papi_return( retval ); 03420 03421 internal.attach.ESI->state |= PAPI_ATTACHED; 03422 internal.attach.ESI->attach.tid = ptr->attach.tid; 03423 03424 _papi_hwi_lookup_or_create_thread( 03425 &(internal.attach.ESI->master), ptr->attach.tid ); 03426 03427 return ( PAPI_OK ); 03428 } 03429 case PAPI_CPU_ATTACH: 03430 { 03431 APIDBG("eventset: %d, cpu_num: %d\n", ptr->cpu.eventset, ptr->cpu.cpu_num); 03432 internal.cpu.ESI = _papi_hwi_lookup_EventSet( ptr->cpu.eventset ); 03433 if ( internal.cpu.ESI == NULL ) 03434 papi_return( PAPI_ENOEVST ); 03435 03436 internal.cpu.cpu_num = ptr->cpu.cpu_num; 03437 APIDBG("internal: %p, ESI: %p, cpu_num: %d\n", &internal, internal.cpu.ESI, internal.cpu.cpu_num); 03438 03439 cidx = valid_ESI_component( internal.cpu.ESI ); 03440 if ( cidx < 0 ) 03441 papi_return( cidx ); 03442 03443 if ( _papi_hwd[cidx]->cmp_info.cpu == 0 ) 03444 papi_return( PAPI_ECMP ); 03445 03446 // can not attach to a cpu if already attached to a process or 03447 // counters set to be inherited by child processes 03448 if ( internal.cpu.ESI->state & (PAPI_ATTACHED | PAPI_INHERIT) ) 03449 papi_return( PAPI_EINVAL ); 03450 03451 if ( ( internal.cpu.ESI->state & PAPI_STOPPED ) == 0 ) 03452 papi_return( PAPI_EISRUN ); 03453 03454 retval = _papi_hwi_lookup_or_create_cpu(&internal.cpu.ESI->CpuInfo, internal.cpu.cpu_num); 03455 if( retval != PAPI_OK) { 03456 papi_return( retval ); 03457 } 03458 03459 /* get the context we should use for this event set */ 03460 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03461 retval = _papi_hwd[cidx]->ctl( context, PAPI_CPU_ATTACH, &internal ); 03462 if ( retval != PAPI_OK ) 03463 papi_return( retval ); 03464 03465 /* set to show this event set is attached to a cpu not a thread */ 03466 internal.cpu.ESI->state |= PAPI_CPU_ATTACHED; 03467 return ( PAPI_OK ); 03468 } 03469 case PAPI_DEF_MPX_NS: 03470 { 03471 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03472 if ( ptr->multiplex.ns < 0 ) 03473 papi_return( PAPI_EINVAL ); 03474 /* We should check the resolution here with the system, either 03475 component if kernel multiplexing or PAPI if SW multiplexing. */ 03476 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03477 /* get the context we should use for this event set */ 03478 context = _papi_hwi_get_context( internal.cpu.ESI, NULL ); 03479 /* Low level just checks/adjusts the args for this component */ 03480 retval = _papi_hwd[cidx]->ctl( context, PAPI_DEF_MPX_NS, &internal ); 03481 if ( retval == PAPI_OK ) { 03482 _papi_os_info.itimer_ns = ( int ) internal.multiplex.ns; 03483 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03484 } 03485 papi_return( retval ); 03486 } 03487 case PAPI_DEF_ITIMER_NS: 03488 { 03489 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03490 if ( ptr->itimer.ns < 0 ) 03491 papi_return( PAPI_EINVAL ); 03492 internal.itimer.ns = ptr->itimer.ns; 03493 /* Low level just checks/adjusts the args for this component */ 03494 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER_NS, &internal ); 03495 if ( retval == PAPI_OK ) { 03496 _papi_os_info.itimer_ns = internal.itimer.ns; 03497 ptr->itimer.ns = internal.itimer.ns; 03498 } 03499 papi_return( retval ); 03500 } 03501 case PAPI_DEF_ITIMER: 03502 { 03503 cidx = 0; /* xxxx for now, assume we only check against cpu component */ 03504 if ( ptr->itimer.ns < 0 ) 03505 papi_return( PAPI_EINVAL ); 03506 memcpy( &internal.itimer, &ptr->itimer, 03507 sizeof ( PAPI_itimer_option_t ) ); 03508 /* Low level just checks/adjusts the args for this component */ 03509 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_DEF_ITIMER, &internal ); 03510 if ( retval == PAPI_OK ) { 03511 _papi_os_info.itimer_num = ptr->itimer.itimer_num; 03512 _papi_os_info.itimer_sig = ptr->itimer.itimer_sig; 03513 if ( ptr->itimer.ns > 0 ) 03514 _papi_os_info.itimer_ns = ptr->itimer.ns; 03515 /* flags are currently ignored, eventually the flags will be able 03516 to specify whether or not we use POSIX itimers (clock_gettimer) */ 03517 } 03518 papi_return( retval ); 03519 } 03520 case PAPI_MULTIPLEX: 03521 { 03522 EventSetInfo_t *ESI; 03523 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 03524 03525 if ( ESI == NULL ) 03526 papi_return( PAPI_ENOEVST ); 03527 03528 cidx = valid_ESI_component( ESI ); 03529 if ( cidx < 0 ) 03530 papi_return( cidx ); 03531 03532 if ( !( ESI->state & PAPI_STOPPED ) ) 03533 papi_return( PAPI_EISRUN ); 03534 if ( ESI->state & PAPI_MULTIPLEXING ) 03535 papi_return( PAPI_EINVAL ); 03536 03537 if ( ptr->multiplex.ns < 0 ) 03538 papi_return( PAPI_EINVAL ); 03539 internal.multiplex.ESI = ESI; 03540 internal.multiplex.ns = ( unsigned long ) ptr->multiplex.ns; 03541 internal.multiplex.flags = ptr->multiplex.flags; 03542 if ( ( _papi_hwd[cidx]->cmp_info.kernel_multiplex ) && 03543 ( ( ptr->multiplex.flags & PAPI_MULTIPLEX_FORCE_SW ) == 0 ) ) { 03544 /* get the context we should use for this event set */ 03545 context = _papi_hwi_get_context( ESI, NULL ); 03546 retval = _papi_hwd[cidx]->ctl( context, PAPI_MULTIPLEX, &internal ); 03547 } 03548 /* Kernel or PAPI may have changed this value so send it back out to the user */ 03549 ptr->multiplex.ns = ( int ) internal.multiplex.ns; 03550 if ( retval == PAPI_OK ) 03551 papi_return( _papi_hwi_convert_eventset_to_multiplex 03552 ( &internal.multiplex ) ); 03553 return ( retval ); 03554 } 03555 case PAPI_DEBUG: 03556 { 03557 int level = ptr->debug.level; 03558 switch ( level ) { 03559 case PAPI_QUIET: 03560 case PAPI_VERB_ESTOP: 03561 case PAPI_VERB_ECONT: 03562 _papi_hwi_error_level = level; 03563 break; 03564 default: 03565 papi_return( PAPI_EINVAL ); 03566 } 03567 _papi_hwi_debug_handler = ptr->debug.handler; 03568 return ( PAPI_OK ); 03569 } 03570 case PAPI_DEFDOM: 03571 { 03572 int dom = ptr->defdomain.domain; 03573 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03574 papi_return( PAPI_EINVAL ); 03575 03576 /* Change the global structure. The _papi_hwd_init_control_state function 03577 in the components gets information from the global structure instead of 03578 per-thread information. */ 03579 cidx = valid_component( ptr->defdomain.def_cidx ); 03580 if ( cidx < 0 ) 03581 papi_return( cidx ); 03582 03583 /* Check what the component supports */ 03584 03585 if ( dom == PAPI_DOM_ALL ) 03586 dom = _papi_hwd[cidx]->cmp_info.available_domains; 03587 03588 if ( dom & ~_papi_hwd[cidx]->cmp_info.available_domains ) 03589 papi_return( PAPI_EINVAL ); 03590 03591 _papi_hwd[cidx]->cmp_info.default_domain = dom; 03592 03593 return ( PAPI_OK ); 03594 } 03595 case PAPI_DOMAIN: 03596 { 03597 int dom = ptr->domain.domain; 03598 if ( ( dom < PAPI_DOM_MIN ) || ( dom > PAPI_DOM_MAX ) ) 03599 papi_return( PAPI_EINVAL_DOM ); 03600 03601 internal.domain.ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 03602 if ( internal.domain.ESI == NULL ) 03603 papi_return( PAPI_ENOEVST ); 03604 03605 cidx = valid_ESI_component( internal.domain.ESI ); 03606 if ( cidx < 0 ) 03607 papi_return( cidx ); 03608 03609 /* Check what the component supports */ 03610 03611 if ( dom == PAPI_DOM_ALL ) 03612 dom = _papi_hwd[cidx]->cmp_info.available_domains; 03613 03614 if ( dom & ~_papi_hwd[cidx]->cmp_info.available_domains ) 03615 papi_return( PAPI_EINVAL_DOM ); 03616 03617 if ( !( internal.domain.ESI->state & PAPI_STOPPED ) ) 03618 papi_return( PAPI_EISRUN ); 03619 03620 /* Try to change the domain of the eventset in the hardware */ 03621 internal.domain.domain = dom; 03622 internal.domain.eventset = ptr->domain.eventset; 03623 /* get the context we should use for this event set */ 03624 context = _papi_hwi_get_context( internal.domain.ESI, NULL ); 03625 retval = _papi_hwd[cidx]->ctl( context, PAPI_DOMAIN, &internal ); 03626 if ( retval < PAPI_OK ) 03627 papi_return( retval ); 03628 03629 /* Change the domain of the eventset in the library */ 03630 03631 internal.domain.ESI->domain.domain = dom; 03632 03633 return ( retval ); 03634 } 03635 case PAPI_DEFGRN: 03636 { 03637 int grn = ptr->defgranularity.granularity; 03638 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03639 papi_return( PAPI_EINVAL ); 03640 03641 cidx = valid_component( ptr->defgranularity.def_cidx ); 03642 if ( cidx < 0 ) 03643 papi_return( cidx ); 03644 03645 /* Change the component structure. The _papi_hwd_init_control_state function 03646 in the components gets information from the global structure instead of 03647 per-thread information. */ 03648 03649 /* Check what the component supports */ 03650 03651 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03652 papi_return( PAPI_EINVAL ); 03653 03654 /* Make sure there is only 1 set. */ 03655 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03656 papi_return( PAPI_EINVAL ); 03657 03658 _papi_hwd[cidx]->cmp_info.default_granularity = grn; 03659 03660 return ( PAPI_OK ); 03661 } 03662 case PAPI_GRANUL: 03663 { 03664 int grn = ptr->granularity.granularity; 03665 03666 if ( ( grn < PAPI_GRN_MIN ) || ( grn > PAPI_GRN_MAX ) ) 03667 papi_return( PAPI_EINVAL ); 03668 03669 internal.granularity.ESI = 03670 _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 03671 if ( internal.granularity.ESI == NULL ) 03672 papi_return( PAPI_ENOEVST ); 03673 03674 cidx = valid_ESI_component( internal.granularity.ESI ); 03675 if ( cidx < 0 ) 03676 papi_return( cidx ); 03677 03678 /* Check what the component supports */ 03679 03680 if ( grn & ~_papi_hwd[cidx]->cmp_info.available_granularities ) 03681 papi_return( PAPI_EINVAL ); 03682 03683 /* Make sure there is only 1 set. */ 03684 if ( grn ^ ( 1 << ( ffs( grn ) - 1 ) ) ) 03685 papi_return( PAPI_EINVAL ); 03686 03687 internal.granularity.granularity = grn; 03688 internal.granularity.eventset = ptr->granularity.eventset; 03689 retval = _papi_hwd[cidx]->ctl( NULL, PAPI_GRANUL, &internal ); 03690 if ( retval < PAPI_OK ) 03691 return ( retval ); 03692 03693 internal.granularity.ESI->granularity.granularity = grn; 03694 return ( retval ); 03695 } 03696 case PAPI_INHERIT: 03697 { 03698 if ( ptr == NULL ) 03699 papi_return( PAPI_EINVAL ); 03700 EventSetInfo_t *ESI; 03701 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 03702 if ( ESI == NULL ) 03703 papi_return( PAPI_ENOEVST ); 03704 03705 cidx = valid_ESI_component( ESI ); 03706 if ( cidx < 0 ) 03707 papi_return( cidx ); 03708 03709 if ( _papi_hwd[cidx]->cmp_info.inherit == 0 ) 03710 papi_return( PAPI_ECMP ); 03711 03712 if ( ( ESI->state & PAPI_STOPPED ) == 0 ) 03713 papi_return( PAPI_EISRUN ); 03714 03715 /* if attached to a cpu, return an error */ 03716 if (ESI->state & PAPI_CPU_ATTACHED) 03717 papi_return( PAPI_ECMP ); 03718 03719 internal.inherit.ESI = ESI; 03720 internal.inherit.inherit = ptr->inherit.inherit; 03721 03722 /* get the context we should use for this event set */ 03723 context = _papi_hwi_get_context( internal.inherit.ESI, NULL ); 03724 retval = _papi_hwd[cidx]->ctl( context, PAPI_INHERIT, &internal ); 03725 if ( retval < PAPI_OK ) 03726 return ( retval ); 03727 03728 ESI->inherit.inherit = ptr->inherit.inherit; 03729 return ( retval ); 03730 } 03731 case PAPI_DATA_ADDRESS: 03732 case PAPI_INSTR_ADDRESS: 03733 { 03734 03735 EventSetInfo_t *ESI; 03736 03737 ESI = _papi_hwi_lookup_EventSet( ptr->addr.eventset ); 03738 if ( ESI == NULL ) 03739 papi_return( PAPI_ENOEVST ); 03740 03741 cidx = valid_ESI_component( ESI ); 03742 if ( cidx < 0 ) 03743 papi_return( cidx ); 03744 03745 internal.address_range.ESI = ESI; 03746 03747 if ( !( internal.address_range.ESI->state & PAPI_STOPPED ) ) 03748 papi_return( PAPI_EISRUN ); 03749 03750 /*set domain to be PAPI_DOM_USER */ 03751 internal.address_range.domain = PAPI_DOM_USER; 03752 03753 internal.address_range.start = ptr->addr.start; 03754 internal.address_range.end = ptr->addr.end; 03755 /* get the context we should use for this event set */ 03756 context = _papi_hwi_get_context( internal.address_range.ESI, NULL ); 03757 retval = _papi_hwd[cidx]->ctl( context, option, &internal ); 03758 ptr->addr.start_off = internal.address_range.start_off; 03759 ptr->addr.end_off = internal.address_range.end_off; 03760 papi_return( retval ); 03761 } 03762 case PAPI_USER_EVENTS_FILE: 03763 { 03764 SUBDBG("Filename is -%s-\n", ptr->events_file); 03765 _papi_user_defined_events_setup(ptr->events_file); 03766 return( PAPI_OK ); 03767 } 03768 default: 03769 papi_return( PAPI_EINVAL ); 03770 } 03771 } 03772 03782 int 03783 PAPI_num_hwctrs( void ) 03784 { 03785 return ( PAPI_num_cmp_hwctrs( 0 ) ); 03786 } 03787 03837 int 03838 PAPI_num_cmp_hwctrs( int cidx ) 03839 { 03840 return ( PAPI_get_cmp_opt( PAPI_MAX_HWCTRS, NULL, cidx ) ); 03841 } 03842 03899 int 03900 PAPI_get_multiplex( int EventSet ) 03901 { 03902 PAPI_option_t popt; 03903 int retval; 03904 03905 popt.multiplex.eventset = EventSet; 03906 retval = PAPI_get_opt( PAPI_MULTIPLEX, &popt ); 03907 if ( retval < 0 ) 03908 retval = 0; 03909 return retval; 03910 } 03911 04013 int 04014 PAPI_get_opt( int option, PAPI_option_t * ptr ) 04015 { 04016 EventSetInfo_t *ESI; 04017 04018 if ( ( option != PAPI_DEBUG ) && ( init_level == PAPI_NOT_INITED ) ) 04019 papi_return( PAPI_ENOINIT ); 04020 04021 switch ( option ) { 04022 case PAPI_DETACH: 04023 { 04024 if ( ptr == NULL ) 04025 papi_return( PAPI_EINVAL ); 04026 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04027 if ( ESI == NULL ) 04028 papi_return( PAPI_ENOEVST ); 04029 ptr->attach.tid = ESI->attach.tid; 04030 return ( ( ESI->state & PAPI_ATTACHED ) == 0 ); 04031 } 04032 case PAPI_ATTACH: 04033 { 04034 if ( ptr == NULL ) 04035 papi_return( PAPI_EINVAL ); 04036 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04037 if ( ESI == NULL ) 04038 papi_return( PAPI_ENOEVST ); 04039 ptr->attach.tid = ESI->attach.tid; 04040 return ( ( ESI->state & PAPI_ATTACHED ) != 0 ); 04041 } 04042 case PAPI_CPU_ATTACH: 04043 { 04044 if ( ptr == NULL ) 04045 papi_return( PAPI_EINVAL ); 04046 ESI = _papi_hwi_lookup_EventSet( ptr->attach.eventset ); 04047 if ( ESI == NULL ) 04048 papi_return( PAPI_ENOEVST ); 04049 ptr->cpu.cpu_num = ESI->CpuInfo->cpu_num; 04050 return ( ( ESI->state & PAPI_CPU_ATTACHED ) != 0 ); 04051 } 04052 case PAPI_DEF_MPX_NS: 04053 { 04054 /* xxxx for now, assume we only check against cpu component */ 04055 if ( ptr == NULL ) 04056 papi_return( PAPI_EINVAL ); 04057 ptr->multiplex.ns = _papi_os_info.itimer_ns; 04058 return ( PAPI_OK ); 04059 } 04060 case PAPI_DEF_ITIMER_NS: 04061 { 04062 /* xxxx for now, assume we only check against cpu component */ 04063 if ( ptr == NULL ) 04064 papi_return( PAPI_EINVAL ); 04065 ptr->itimer.ns = _papi_os_info.itimer_ns; 04066 return ( PAPI_OK ); 04067 } 04068 case PAPI_DEF_ITIMER: 04069 { 04070 /* xxxx for now, assume we only check against cpu component */ 04071 if ( ptr == NULL ) 04072 papi_return( PAPI_EINVAL ); 04073 ptr->itimer.itimer_num = _papi_os_info.itimer_num; 04074 ptr->itimer.itimer_sig = _papi_os_info.itimer_sig; 04075 ptr->itimer.ns = _papi_os_info.itimer_ns; 04076 ptr->itimer.flags = 0; 04077 return ( PAPI_OK ); 04078 } 04079 case PAPI_MULTIPLEX: 04080 { 04081 if ( ptr == NULL ) 04082 papi_return( PAPI_EINVAL ); 04083 ESI = _papi_hwi_lookup_EventSet( ptr->multiplex.eventset ); 04084 if ( ESI == NULL ) 04085 papi_return( PAPI_ENOEVST ); 04086 ptr->multiplex.ns = ESI->multiplex.ns; 04087 ptr->multiplex.flags = ESI->multiplex.flags; 04088 return ( ESI->state & PAPI_MULTIPLEXING ) != 0; 04089 } 04090 case PAPI_PRELOAD: 04091 if ( ptr == NULL ) 04092 papi_return( PAPI_EINVAL ); 04093 memcpy( &ptr->preload, &_papi_hwi_system_info.preload_info, 04094 sizeof ( PAPI_preload_info_t ) ); 04095 break; 04096 case PAPI_DEBUG: 04097 if ( ptr == NULL ) 04098 papi_return( PAPI_EINVAL ); 04099 ptr->debug.level = _papi_hwi_error_level; 04100 ptr->debug.handler = _papi_hwi_debug_handler; 04101 break; 04102 case PAPI_CLOCKRATE: 04103 return ( ( int ) _papi_hwi_system_info.hw_info.cpu_max_mhz ); 04104 case PAPI_MAX_CPUS: 04105 return ( _papi_hwi_system_info.hw_info.ncpu ); 04106 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04107 At some future point, they may map onto different values. 04108 */ 04109 case PAPI_INHERIT: 04110 { 04111 if ( ptr == NULL ) 04112 papi_return( PAPI_EINVAL ); 04113 ESI = _papi_hwi_lookup_EventSet( ptr->inherit.eventset ); 04114 if ( ESI == NULL ) 04115 papi_return( PAPI_ENOEVST ); 04116 ptr->inherit.inherit = ESI->inherit.inherit; 04117 return ( PAPI_OK ); 04118 } 04119 case PAPI_GRANUL: 04120 if ( ptr == NULL ) 04121 papi_return( PAPI_EINVAL ); 04122 ESI = _papi_hwi_lookup_EventSet( ptr->granularity.eventset ); 04123 if ( ESI == NULL ) 04124 papi_return( PAPI_ENOEVST ); 04125 ptr->granularity.granularity = ESI->granularity.granularity; 04126 break; 04127 case PAPI_EXEINFO: 04128 if ( ptr == NULL ) 04129 papi_return( PAPI_EINVAL ); 04130 ptr->exe_info = &_papi_hwi_system_info.exe_info; 04131 break; 04132 case PAPI_HWINFO: 04133 if ( ptr == NULL ) 04134 papi_return( PAPI_EINVAL ); 04135 ptr->hw_info = &_papi_hwi_system_info.hw_info; 04136 break; 04137 04138 case PAPI_DOMAIN: 04139 if ( ptr == NULL ) 04140 papi_return( PAPI_EINVAL ); 04141 ESI = _papi_hwi_lookup_EventSet( ptr->domain.eventset ); 04142 if ( ESI == NULL ) 04143 papi_return( PAPI_ENOEVST ); 04144 ptr->domain.domain = ESI->domain.domain; 04145 return ( PAPI_OK ); 04146 case PAPI_LIB_VERSION: 04147 return ( PAPI_VERSION ); 04148 /* The following cases all require a component index 04149 and are handled by PAPI_get_cmp_opt() with cidx == 0*/ 04150 case PAPI_MAX_HWCTRS: 04151 case PAPI_MAX_MPX_CTRS: 04152 case PAPI_DEFDOM: 04153 case PAPI_DEFGRN: 04154 case PAPI_SHLIBINFO: 04155 case PAPI_COMPONENTINFO: 04156 return ( PAPI_get_cmp_opt( option, ptr, 0 ) ); 04157 default: 04158 papi_return( PAPI_EINVAL ); 04159 } 04160 return ( PAPI_OK ); 04161 } 04162 04204 int 04205 PAPI_get_cmp_opt( int option, PAPI_option_t * ptr, int cidx ) 04206 { 04207 04208 if (_papi_hwi_invalid_cmp(cidx)) { 04209 return PAPI_ECMP; 04210 } 04211 04212 switch ( option ) { 04213 /* For now, MAX_HWCTRS and MAX CTRS are identical. 04214 At some future point, they may map onto different values. 04215 */ 04216 case PAPI_MAX_HWCTRS: 04217 return ( _papi_hwd[cidx]->cmp_info.num_cntrs ); 04218 case PAPI_MAX_MPX_CTRS: 04219 return ( _papi_hwd[cidx]->cmp_info.num_mpx_cntrs ); 04220 case PAPI_DEFDOM: 04221 return ( _papi_hwd[cidx]->cmp_info.default_domain ); 04222 case PAPI_DEFGRN: 04223 return ( _papi_hwd[cidx]->cmp_info.default_granularity ); 04224 case PAPI_SHLIBINFO: 04225 { 04226 int retval; 04227 if ( ptr == NULL ) 04228 papi_return( PAPI_EINVAL ); 04229 retval = _papi_os_vector.update_shlib_info( &_papi_hwi_system_info ); 04230 ptr->shlib_info = &_papi_hwi_system_info.shlib_info; 04231 papi_return( retval ); 04232 } 04233 case PAPI_COMPONENTINFO: 04234 if ( ptr == NULL ) 04235 papi_return( PAPI_EINVAL ); 04236 ptr->cmp_info = &( _papi_hwd[cidx]->cmp_info ); 04237 return PAPI_OK; 04238 default: 04239 papi_return( PAPI_EINVAL ); 04240 } 04241 return PAPI_OK; 04242 } 04243 04255 int 04256 PAPI_num_components( void ) 04257 { 04258 return ( papi_num_components ); 04259 } 04260 04295 int 04296 PAPI_num_events( int EventSet ) 04297 { 04298 EventSetInfo_t *ESI; 04299 04300 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04301 if ( !ESI ) 04302 papi_return( PAPI_ENOEVST ); 04303 04304 #ifdef DEBUG 04305 /* Not necessary */ 04306 if ( ESI->NumberOfEvents == 0 ) 04307 papi_return( PAPI_EINVAL ); 04308 #endif 04309 04310 return ( ESI->NumberOfEvents ); 04311 } 04312 04313 04329 void 04330 PAPI_shutdown( void ) 04331 { 04332 EventSetInfo_t *ESI; 04333 ThreadInfo_t *master; 04334 DynamicArray_t *map = &_papi_hwi_system_info.global_eventset_map; 04335 int i, j = 0, retval; 04336 04337 04338 APIDBG( "Enter\n" ); 04339 if ( init_retval == DEADBEEF ) { 04340 PAPIERROR( PAPI_SHUTDOWN_str ); 04341 return; 04342 } 04343 04344 MPX_shutdown( ); 04345 04346 /* Free all EventSets for this thread */ 04347 04348 master = _papi_hwi_lookup_thread( 0 ); 04349 04350 /* Count number of running EventSets AND */ 04351 /* Stop any running EventSets in this thread */ 04352 04353 #ifdef DEBUG 04354 again: 04355 #endif 04356 for( i = 0; i < map->totalSlots; i++ ) { 04357 ESI = map->dataSlotArray[i]; 04358 if ( ESI ) { 04359 if ( ESI->master == master ) { 04360 if ( ESI->state & PAPI_RUNNING ) { 04361 retval=PAPI_stop( i, NULL ); 04362 } 04363 retval=PAPI_cleanup_eventset( i ); 04364 if (retval!=PAPI_OK) PAPIERROR("Error during cleanup.\n"); 04365 _papi_hwi_free_EventSet( ESI ); 04366 } 04367 else { 04368 if ( ESI->state & PAPI_RUNNING ) { 04369 j++; 04370 } 04371 } 04372 } 04373 } 04374 04375 /* No locking required, we're just waiting for the others 04376 to call shutdown or stop their eventsets. */ 04377 04378 #ifdef DEBUG 04379 if ( j != 0 ) { 04380 PAPIERROR( PAPI_SHUTDOWN_SYNC_str ); 04381 sleep( 1 ); 04382 j = 0; 04383 goto again; 04384 } 04385 #endif 04386 04387 /* Shutdown the entire component */ 04388 04389 _papi_cleanup_user_events(); 04390 04391 _papi_hwi_shutdown_highlevel( ); 04392 _papi_hwi_shutdown_global_internal( ); 04393 _papi_hwi_shutdown_global_threads( ); 04394 for( i = 0; i < papi_num_components; i++ ) { 04395 if (!_papi_hwd[i]->cmp_info.disabled) { 04396 _papi_hwd[i]->shutdown_component( ); 04397 } 04398 } 04399 04400 /* Now it is safe to call re-init */ 04401 04402 init_retval = DEADBEEF; 04403 init_level = PAPI_NOT_INITED; 04404 _papi_mem_cleanup_all( ); 04405 } 04406 04455 char * 04456 PAPI_strerror( int errorCode ) 04457 { 04458 if ( ( errorCode > 0 ) || ( -errorCode > _papi_hwi_num_errors ) ) 04459 return ( NULL ); 04460 04461 return ( _papi_errlist[-errorCode] ); 04462 } 04463 04505 void 04506 PAPI_perror( char *msg ) 04507 { 04508 char *foo; 04509 04510 foo = PAPI_strerror( _papi_hwi_errno ); 04511 if ( foo == NULL ) 04512 return; 04513 04514 if ( msg ) 04515 if ( *msg ) 04516 fprintf( stderr, "%s: ", msg ); 04517 04518 fprintf( stderr, "%s\n", foo ); 04519 } 04520 04647 int 04648 PAPI_overflow( int EventSet, int EventCode, int threshold, int flags, 04649 PAPI_overflow_handler_t handler ) 04650 { 04651 int retval, cidx, index, i; 04652 EventSetInfo_t *ESI; 04653 04654 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04655 if ( ESI == NULL ) { 04656 OVFDBG("No EventSet\n"); 04657 papi_return( PAPI_ENOEVST ); 04658 } 04659 04660 cidx = valid_ESI_component( ESI ); 04661 if ( cidx < 0 ) { 04662 OVFDBG("Component Error\n"); 04663 papi_return( cidx ); 04664 } 04665 04666 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04667 OVFDBG("Already running\n"); 04668 papi_return( PAPI_EISRUN ); 04669 } 04670 04671 if ( ESI->state & PAPI_ATTACHED ) { 04672 OVFDBG("Attached\n"); 04673 papi_return( PAPI_EINVAL ); 04674 } 04675 04676 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04677 OVFDBG("CPU attached\n"); 04678 papi_return( PAPI_EINVAL ); 04679 } 04680 04681 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04682 ( unsigned int ) EventCode ) ) < 0 ) { 04683 papi_return( PAPI_ENOEVNT ); 04684 } 04685 04686 if ( threshold < 0 ) { 04687 OVFDBG("Threshold below zero\n"); 04688 papi_return( PAPI_EINVAL ); 04689 } 04690 04691 /* We do not support derived events in overflow */ 04692 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04693 04694 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && threshold != 0 && 04695 ( ESI->EventInfoArray[index].derived ) && 04696 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) ) { 04697 OVFDBG("Derived event in overflow\n"); 04698 papi_return( PAPI_EINVAL ); 04699 } 04700 04701 /* the first time to call PAPI_overflow function */ 04702 04703 if ( !( ESI->state & PAPI_OVERFLOWING ) ) { 04704 if ( handler == NULL ) { 04705 OVFDBG("NULL handler\n"); 04706 papi_return( PAPI_EINVAL ); 04707 } 04708 if ( threshold == 0 ) { 04709 OVFDBG("Zero threshold\n"); 04710 papi_return( PAPI_EINVAL ); 04711 } 04712 } 04713 if ( threshold > 0 && 04714 ESI->overflow.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs ) 04715 papi_return( PAPI_ECNFLCT ); 04716 04717 if ( threshold == 0 ) { 04718 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04719 if ( ESI->overflow.EventCode[i] == EventCode ) 04720 break; 04721 } 04722 /* EventCode not found */ 04723 if ( i == ESI->overflow.event_counter ) 04724 papi_return( PAPI_EINVAL ); 04725 /* compact these arrays */ 04726 while ( i < ESI->overflow.event_counter - 1 ) { 04727 ESI->overflow.deadline[i] = ESI->overflow.deadline[i + 1]; 04728 ESI->overflow.threshold[i] = ESI->overflow.threshold[i + 1]; 04729 ESI->overflow.EventIndex[i] = ESI->overflow.EventIndex[i + 1]; 04730 ESI->overflow.EventCode[i] = ESI->overflow.EventCode[i + 1]; 04731 i++; 04732 } 04733 ESI->overflow.deadline[i] = 0; 04734 ESI->overflow.threshold[i] = 0; 04735 ESI->overflow.EventIndex[i] = 0; 04736 ESI->overflow.EventCode[i] = 0; 04737 ESI->overflow.event_counter--; 04738 } else { 04739 if ( ESI->overflow.event_counter > 0 ) { 04740 if ( ( flags & PAPI_OVERFLOW_FORCE_SW ) && 04741 ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) 04742 papi_return( PAPI_ECNFLCT ); 04743 if ( !( flags & PAPI_OVERFLOW_FORCE_SW ) && 04744 ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) 04745 papi_return( PAPI_ECNFLCT ); 04746 } 04747 for ( i = 0; i < ESI->overflow.event_counter; i++ ) { 04748 if ( ESI->overflow.EventCode[i] == EventCode ) 04749 break; 04750 } 04751 /* A new entry */ 04752 if ( i == ESI->overflow.event_counter ) { 04753 ESI->overflow.EventCode[i] = EventCode; 04754 ESI->overflow.event_counter++; 04755 } 04756 /* New or existing entry */ 04757 ESI->overflow.deadline[i] = threshold; 04758 ESI->overflow.threshold[i] = threshold; 04759 ESI->overflow.EventIndex[i] = index; 04760 ESI->overflow.flags = flags; 04761 04762 } 04763 04764 /* If overflowing is already active, we should check to 04765 make sure that we don't specify a different handler 04766 or different flags here. You can't mix them. */ 04767 04768 ESI->overflow.handler = handler; 04769 04770 /* Set up the option structure for the low level. 04771 If we have hardware interrupts and we are not using 04772 forced software emulated interrupts */ 04773 04774 if ( _papi_hwd[cidx]->cmp_info.hardware_intr && 04775 !( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) ) { 04776 retval = _papi_hwd[cidx]->set_overflow( ESI, index, threshold ); 04777 if ( retval == PAPI_OK ) 04778 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 04779 else { 04780 papi_return( retval ); /* We should undo stuff here */ 04781 } 04782 } else { 04783 /* Make sure hardware overflow is not set */ 04784 ESI->overflow.flags &= ~( PAPI_OVERFLOW_HARDWARE ); 04785 } 04786 04787 APIDBG( "Overflow using: %s\n", 04788 ( ESI->overflow. 04789 flags & PAPI_OVERFLOW_HARDWARE ? "[Hardware]" : ESI->overflow. 04790 flags & PAPI_OVERFLOW_FORCE_SW ? "[Forced Software]" : 04791 "[Software]" ) ); 04792 04793 /* Toggle the overflow flags and ESI state */ 04794 04795 if ( ESI->overflow.event_counter >= 1 ) 04796 ESI->state |= PAPI_OVERFLOWING; 04797 else { 04798 ESI->state ^= PAPI_OVERFLOWING; 04799 ESI->overflow.flags = 0; 04800 ESI->overflow.handler = NULL; 04801 } 04802 04803 return PAPI_OK; 04804 } 04805 04902 int 04903 PAPI_sprofil( PAPI_sprofil_t *prof, int profcnt, int EventSet, 04904 int EventCode, int threshold, int flags ) 04905 { 04906 EventSetInfo_t *ESI; 04907 int retval, index, i, buckets; 04908 int forceSW = 0; 04909 int cidx; 04910 04911 /* Check to make sure EventSet exists */ 04912 ESI = _papi_hwi_lookup_EventSet( EventSet ); 04913 if ( ESI == NULL ) { 04914 papi_return( PAPI_ENOEVST ); 04915 } 04916 04917 /* Check to make sure EventSet is stopped */ 04918 if ( ( ESI->state & PAPI_STOPPED ) != PAPI_STOPPED ) { 04919 papi_return( PAPI_EISRUN ); 04920 } 04921 04922 /* We cannot profile if attached */ 04923 if ( ESI->state & PAPI_ATTACHED ) { 04924 papi_return( PAPI_EINVAL ); 04925 } 04926 04927 /* We cannot profile if cpu attached */ 04928 if ( ESI->state & PAPI_CPU_ATTACHED ) { 04929 papi_return( PAPI_EINVAL ); 04930 } 04931 04932 /* Get component for EventSet */ 04933 cidx = valid_ESI_component( ESI ); 04934 if ( cidx < 0 ) { 04935 papi_return( cidx ); 04936 } 04937 04938 /* Get index of the Event we want to profile */ 04939 if ( ( index = _papi_hwi_lookup_EventCodeIndex( ESI, 04940 (unsigned int) EventCode ) ) < 0 ) { 04941 papi_return( PAPI_ENOEVNT ); 04942 } 04943 04944 /* We do not support derived events in overflow */ 04945 /* Unless it's DERIVED_CMPD in which no calculations are done */ 04946 if ( ( ESI->EventInfoArray[index].derived ) && 04947 ( ESI->EventInfoArray[index].derived != DERIVED_CMPD ) && 04948 !( flags & PAPI_PROFIL_FORCE_SW ) ) { 04949 papi_return( PAPI_EINVAL ); 04950 } 04951 04952 /* If no prof structures, then make sure count is 0 */ 04953 if ( prof == NULL ) { 04954 profcnt = 0; 04955 } 04956 04957 /* check all profile regions for valid scale factors of: 04958 2 (131072/65536), 04959 1 (65536/65536), 04960 or < 1 (65535 -> 2) as defined in unix profil() 04961 2/65536 is reserved for single bucket profiling 04962 {0,1}/65536 are traditionally used to terminate profiling 04963 but are unused here since PAPI uses threshold instead 04964 */ 04965 for( i = 0; i < profcnt; i++ ) { 04966 if ( !( ( prof[i].pr_scale == 131072 ) || 04967 ( ( prof[i].pr_scale <= 65536 && prof[i].pr_scale > 1 ) ) ) ) { 04968 APIDBG( "Improper scale factor: %d\n", prof[i].pr_scale ); 04969 papi_return( PAPI_EINVAL ); 04970 } 04971 } 04972 04973 /* Make sure threshold is valid */ 04974 if ( threshold < 0 ) { 04975 papi_return( PAPI_EINVAL ); 04976 } 04977 04978 /* the first time to call PAPI_sprofil */ 04979 if ( !( ESI->state & PAPI_PROFILING ) ) { 04980 if ( threshold == 0 ) { 04981 papi_return( PAPI_EINVAL ); 04982 } 04983 } 04984 04985 /* ??? */ 04986 if ( (threshold > 0) && 04987 (ESI->profile.event_counter >= _papi_hwd[cidx]->cmp_info.num_cntrs) ) { 04988 papi_return( PAPI_ECNFLCT ); 04989 } 04990 04991 if ( threshold == 0 ) { 04992 for( i = 0; i < ESI->profile.event_counter; i++ ) { 04993 if ( ESI->profile.EventCode[i] == EventCode ) { 04994 break; 04995 } 04996 } 04997 04998 /* EventCode not found */ 04999 if ( i == ESI->profile.event_counter ) { 05000 papi_return( PAPI_EINVAL ); 05001 } 05002 05003 /* compact these arrays */ 05004 while ( i < ESI->profile.event_counter - 1 ) { 05005 ESI->profile.prof[i] = ESI->profile.prof[i + 1]; 05006 ESI->profile.count[i] = ESI->profile.count[i + 1]; 05007 ESI->profile.threshold[i] = ESI->profile.threshold[i + 1]; 05008 ESI->profile.EventIndex[i] = ESI->profile.EventIndex[i + 1]; 05009 ESI->profile.EventCode[i] = ESI->profile.EventCode[i + 1]; 05010 i++; 05011 } 05012 ESI->profile.prof[i] = NULL; 05013 ESI->profile.count[i] = 0; 05014 ESI->profile.threshold[i] = 0; 05015 ESI->profile.EventIndex[i] = 0; 05016 ESI->profile.EventCode[i] = 0; 05017 ESI->profile.event_counter--; 05018 } else { 05019 if ( ESI->profile.event_counter > 0 ) { 05020 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05021 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05022 papi_return( PAPI_ECNFLCT ); 05023 } 05024 if ( !( flags & PAPI_PROFIL_FORCE_SW ) && 05025 ( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05026 papi_return( PAPI_ECNFLCT ); 05027 } 05028 } 05029 05030 for( i = 0; i < ESI->profile.event_counter; i++ ) { 05031 if ( ESI->profile.EventCode[i] == EventCode ) { 05032 break; 05033 } 05034 } 05035 05036 if ( i == ESI->profile.event_counter ) { 05037 i = ESI->profile.event_counter; 05038 ESI->profile.event_counter++; 05039 ESI->profile.EventCode[i] = EventCode; 05040 } 05041 ESI->profile.prof[i] = prof; 05042 ESI->profile.count[i] = profcnt; 05043 ESI->profile.threshold[i] = threshold; 05044 ESI->profile.EventIndex[i] = index; 05045 } 05046 05047 APIDBG( "Profile event counter is %d\n", ESI->profile.event_counter ); 05048 05049 /* Clear out old flags */ 05050 if ( threshold == 0 ) { 05051 flags |= ESI->profile.flags; 05052 } 05053 05054 /* make sure no invalid flags are set */ 05055 if ( flags & 05056 ~( PAPI_PROFIL_POSIX | PAPI_PROFIL_RANDOM | PAPI_PROFIL_WEIGHTED | 05057 PAPI_PROFIL_COMPRESS | PAPI_PROFIL_BUCKETS | PAPI_PROFIL_FORCE_SW | 05058 PAPI_PROFIL_INST_EAR | PAPI_PROFIL_DATA_EAR ) ) { 05059 papi_return( PAPI_EINVAL ); 05060 } 05061 05062 /* if we have kernel-based profiling, then we're just asking for 05063 signals on interrupt. */ 05064 /* if we don't have kernel-based profiling, then we're asking for 05065 emulated PMU interrupt */ 05066 if ( ( flags & PAPI_PROFIL_FORCE_SW ) && 05067 ( _papi_hwd[cidx]->cmp_info.kernel_profile == 0 ) ) { 05068 forceSW = PAPI_OVERFLOW_FORCE_SW; 05069 } 05070 05071 /* make sure one and only one bucket size is set */ 05072 buckets = flags & PAPI_PROFIL_BUCKETS; 05073 if ( !buckets ) { 05074 flags |= PAPI_PROFIL_BUCKET_16; /* default to 16 bit if nothing set */ 05075 } 05076 else { 05077 /* return error if more than one set */ 05078 if ( !( ( buckets == PAPI_PROFIL_BUCKET_16 ) || 05079 ( buckets == PAPI_PROFIL_BUCKET_32 ) || 05080 ( buckets == PAPI_PROFIL_BUCKET_64 ) ) ) { 05081 papi_return( PAPI_EINVAL ); 05082 } 05083 } 05084 05085 /* Set up the option structure for the low level */ 05086 ESI->profile.flags = flags; 05087 05088 if ( _papi_hwd[cidx]->cmp_info.kernel_profile && 05089 !( ESI->profile.flags & PAPI_PROFIL_FORCE_SW ) ) { 05090 retval = _papi_hwd[cidx]->set_profile( ESI, index, threshold ); 05091 if ( ( retval == PAPI_OK ) && ( threshold > 0 ) ) { 05092 /* We need overflowing because we use the overflow dispatch handler */ 05093 ESI->state |= PAPI_OVERFLOWING; 05094 ESI->overflow.flags |= PAPI_OVERFLOW_HARDWARE; 05095 } 05096 } else { 05097 retval = PAPI_overflow( EventSet, EventCode, threshold, forceSW, 05098 _papi_hwi_dummy_handler ); 05099 } 05100 05101 if ( retval < PAPI_OK ) { 05102 papi_return( retval ); /* We should undo stuff here */ 05103 } 05104 05105 /* Toggle the profiling flags and ESI state */ 05106 05107 if ( ESI->profile.event_counter >= 1 ) { 05108 ESI->state |= PAPI_PROFILING; 05109 } 05110 else { 05111 ESI->state ^= PAPI_PROFILING; 05112 ESI->profile.flags = 0; 05113 } 05114 05115 return PAPI_OK; 05116 } 05117 05295 int 05296 PAPI_profil( void *buf, unsigned bufsiz, caddr_t offset, 05297 unsigned scale, int EventSet, int EventCode, int threshold, 05298 int flags ) 05299 { 05300 EventSetInfo_t *ESI; 05301 int i; 05302 int retval; 05303 05304 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05305 if ( ESI == NULL ) 05306 papi_return( PAPI_ENOEVST ); 05307 05308 /* scale factors are checked for validity in PAPI_sprofil */ 05309 05310 if ( threshold > 0 ) { 05311 PAPI_sprofil_t *prof; 05312 05313 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05314 if ( ESI->profile.EventCode[i] == EventCode ) 05315 break; 05316 } 05317 05318 if ( i == ESI->profile.event_counter ) { 05319 prof = 05320 ( PAPI_sprofil_t * ) papi_malloc( sizeof ( PAPI_sprofil_t ) ); 05321 memset( prof, 0x0, sizeof ( PAPI_sprofil_t ) ); 05322 prof->pr_base = buf; 05323 prof->pr_size = bufsiz; 05324 prof->pr_off = offset; 05325 prof->pr_scale = scale; 05326 05327 retval = 05328 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05329 05330 if ( retval != PAPI_OK ) 05331 papi_free( prof ); 05332 } else { 05333 prof = ESI->profile.prof[i]; 05334 prof->pr_base = buf; 05335 prof->pr_size = bufsiz; 05336 prof->pr_off = offset; 05337 prof->pr_scale = scale; 05338 retval = 05339 PAPI_sprofil( prof, 1, EventSet, EventCode, threshold, flags ); 05340 } 05341 papi_return( retval ); 05342 } 05343 05344 for ( i = 0; i < ESI->profile.event_counter; i++ ) { 05345 if ( ESI->profile.EventCode[i] == EventCode ) 05346 break; 05347 } 05348 /* EventCode not found */ 05349 if ( i == ESI->profile.event_counter ) 05350 papi_return( PAPI_EINVAL ); 05351 05352 papi_free( ESI->profile.prof[i] ); 05353 ESI->profile.prof[i] = NULL; 05354 05355 papi_return( PAPI_sprofil( NULL, 0, EventSet, EventCode, 0, flags ) ); 05356 } 05357 05358 /* This function sets the low level default granularity 05359 for all newly manufactured eventsets. The first function 05360 preserves API compatibility and assumes component 0; 05361 The second function takes a component argument. */ 05362 05413 int 05414 PAPI_set_granularity( int granularity ) 05415 { 05416 return ( PAPI_set_cmp_granularity( granularity, 0 ) ); 05417 } 05418 05478 int 05479 PAPI_set_cmp_granularity( int granularity, int cidx ) 05480 { 05481 PAPI_option_t ptr; 05482 05483 memset( &ptr, 0, sizeof ( ptr ) ); 05484 ptr.defgranularity.def_cidx = cidx; 05485 ptr.defgranularity.granularity = granularity; 05486 papi_return( PAPI_set_opt( PAPI_DEFGRN, &ptr ) ); 05487 } 05488 05489 /* This function sets the low level default counting domain 05490 for all newly manufactured eventsets. The first function 05491 preserves API compatibility and assumes component 0; 05492 The second function takes a component argument. */ 05493 05544 int 05545 PAPI_set_domain( int domain ) 05546 { 05547 return ( PAPI_set_cmp_domain( domain, 0 ) ); 05548 } 05549 05614 int 05615 PAPI_set_cmp_domain( int domain, int cidx ) 05616 { 05617 PAPI_option_t ptr; 05618 05619 memset( &ptr, 0, sizeof ( ptr ) ); 05620 ptr.defdomain.def_cidx = cidx; 05621 ptr.defdomain.domain = domain; 05622 papi_return( PAPI_set_opt( PAPI_DEFDOM, &ptr ) ); 05623 } 05624 05699 int 05700 PAPI_add_events( int EventSet, int *Events, int number ) 05701 { 05702 int i, retval; 05703 05704 if ( ( Events == NULL ) || ( number <= 0 ) ) 05705 papi_return( PAPI_EINVAL ); 05706 05707 for ( i = 0; i < number; i++ ) { 05708 retval = PAPI_add_event( EventSet, Events[i] ); 05709 if ( retval != PAPI_OK ) { 05710 if ( i == 0 ) 05711 papi_return( retval ); 05712 else 05713 return ( i ); 05714 } 05715 } 05716 return ( PAPI_OK ); 05717 } 05718 05786 int 05787 PAPI_remove_events( int EventSet, int *Events, int number ) 05788 { 05789 int i, retval; 05790 05791 if ( ( Events == NULL ) || ( number <= 0 ) ) 05792 papi_return( PAPI_EINVAL ); 05793 05794 for ( i = 0; i < number; i++ ) { 05795 retval = PAPI_remove_event( EventSet, Events[i] ); 05796 if ( retval != PAPI_OK ) { 05797 if ( i == 0 ) 05798 papi_return( retval ); 05799 else 05800 return ( i ); 05801 } 05802 } 05803 return ( PAPI_OK ); 05804 } 05805 05846 int 05847 PAPI_list_events( int EventSet, int *Events, int *number ) 05848 { 05849 EventSetInfo_t *ESI; 05850 int i, j; 05851 05852 if ( ( Events == NULL ) || ( *number <= 0 ) ) 05853 papi_return( PAPI_EINVAL ); 05854 05855 ESI = _papi_hwi_lookup_EventSet( EventSet ); 05856 if ( !ESI ) 05857 papi_return( PAPI_ENOEVST ); 05858 05859 for ( i = 0, j = 0; j < ESI->NumberOfEvents; i++ ) { 05860 if ( ( int ) ESI->EventInfoArray[i].event_code != PAPI_NULL ) { 05861 Events[j] = ( int ) ESI->EventInfoArray[i].event_code; 05862 j++; 05863 if ( j == *number ) 05864 break; 05865 } 05866 } 05867 05868 *number = j; 05869 05870 return ( PAPI_OK ); 05871 } 05872 05873 /* xxx This is OS dependent, not component dependent, right? */ 05899 int 05900 PAPI_get_dmem_info( PAPI_dmem_info_t * dest ) 05901 { 05902 if ( dest == NULL ) 05903 return PAPI_EINVAL; 05904 05905 memset( ( void * ) dest, 0x0, sizeof ( PAPI_dmem_info_t ) ); 05906 return ( _papi_os_vector.get_dmem_info( dest ) ); 05907 } 05908 05909 05953 const PAPI_exe_info_t * 05954 PAPI_get_executable_info( void ) 05955 { 05956 PAPI_option_t ptr; 05957 int retval; 05958 05959 memset( &ptr, 0, sizeof ( ptr ) ); 05960 retval = PAPI_get_opt( PAPI_EXEINFO, &ptr ); 05961 if ( retval == PAPI_OK ) 05962 return ( ptr.exe_info ); 05963 else 05964 return ( NULL ); 05965 } 05966 05983 const PAPI_shlib_info_t * 05984 PAPI_get_shared_lib_info( void ) 05985 { 05986 PAPI_option_t ptr; 05987 int retval; 05988 05989 memset( &ptr, 0, sizeof ( ptr ) ); 05990 retval = PAPI_get_opt( PAPI_SHLIBINFO, &ptr ); 05991 if ( retval == PAPI_OK ) 05992 return ( ptr.shlib_info ); 05993 else 05994 return ( NULL ); 05995 } 06024 const PAPI_hw_info_t * 06025 PAPI_get_hardware_info( void ) 06026 { 06027 PAPI_option_t ptr; 06028 int retval; 06029 06030 memset( &ptr, 0, sizeof ( ptr ) ); 06031 retval = PAPI_get_opt( PAPI_HWINFO, &ptr ); 06032 if ( retval == PAPI_OK ) 06033 return ( ptr.hw_info ); 06034 else 06035 return ( NULL ); 06036 } 06037 06038 06039 /* The next 4 timing functions always use component 0 */ 06040 06056 long long 06057 PAPI_get_real_cyc( void ) 06058 { 06059 return ( _papi_os_vector.get_real_cycles( ) ); 06060 } 06061 06075 /* FIXME */ 06076 long long 06077 PAPI_get_real_nsec( void ) 06078 { 06079 return ( ( _papi_os_vector.get_real_nsec( ))); 06080 06081 } 06082 06103 long long 06104 PAPI_get_real_usec( void ) 06105 { 06106 return ( _papi_os_vector.get_real_usec( ) ); 06107 } 06108 06139 long long 06140 PAPI_get_virt_cyc( void ) 06141 { 06142 06143 return ( ( long long ) _papi_os_vector.get_virt_cycles( ) ); 06144 } 06145 06169 long long 06170 PAPI_get_virt_nsec( void ) 06171 { 06172 06173 return ( ( _papi_os_vector.get_virt_nsec())); 06174 06175 } 06176 06211 long long 06212 PAPI_get_virt_usec( void ) 06213 { 06214 06215 return ( ( long long ) _papi_os_vector.get_virt_usec() ); 06216 } 06217 06242 int 06243 PAPI_lock( int lck ) 06244 { 06245 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06246 papi_return( PAPI_EINVAL ); 06247 06248 papi_return( _papi_hwi_lock( lck ) ); 06249 } 06250 06262 int 06263 PAPI_unlock( int lck ) 06264 { 06265 if ( ( lck < 0 ) || ( lck >= PAPI_NUM_LOCK ) ) 06266 papi_return( PAPI_EINVAL ); 06267 06268 papi_return( _papi_hwi_unlock( lck ) ); 06269 } 06270 06304 int 06305 PAPI_is_initialized( void ) 06306 { 06307 return ( init_level ); 06308 } 06309 06310 /* This function maps the overflow_vector to event indexes in the event 06311 set, so that user can know which PAPI event overflowed. 06312 int *array---- an array of event indexes in eventset; the first index 06313 maps to the highest set bit in overflow_vector 06314 int *number--- this is an input/output parameter, user should put the 06315 size of the array into this parameter, after the function 06316 is executed, the number of indexes in *array is written 06317 to this parameter 06318 */ 06319 06358 int 06359 PAPI_get_overflow_event_index( int EventSet, long long overflow_vector, 06360 int *array, int *number ) 06361 { 06362 EventSetInfo_t *ESI; 06363 int set_bit, j, pos; 06364 int count = 0, k; 06365 06366 if ( overflow_vector == ( long long ) 0 ) 06367 papi_return( PAPI_EINVAL ); 06368 06369 if ( ( array == NULL ) || ( number == NULL ) ) 06370 papi_return( PAPI_EINVAL ); 06371 06372 if ( *number < 1 ) 06373 papi_return( PAPI_EINVAL ); 06374 06375 ESI = _papi_hwi_lookup_EventSet( EventSet ); 06376 if ( ESI == NULL ) 06377 papi_return( PAPI_ENOEVST ); 06378 06379 /* in case the eventset is empty */ 06380 if ( ESI->NumberOfEvents == 0 ) 06381 papi_return( PAPI_EINVAL ); 06382 06383 while ( ( set_bit = ffsll( overflow_vector ) ) ) { 06384 set_bit -= 1; 06385 overflow_vector ^= ( long long ) 1 << set_bit; 06386 for ( j = 0; j < ESI->NumberOfEvents; j++ ) { 06387 for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0; k++ ) { 06388 pos = ESI->EventInfoArray[j].pos[k]; 06389 if ( ( set_bit == pos ) && 06390 ( ( ESI->EventInfoArray[j].derived == NOT_DERIVED ) || 06391 ( ESI->EventInfoArray[j].derived == DERIVED_CMPD ) ) ) { 06392 array[count++] = j; 06393 if ( count == *number ) 06394 return PAPI_OK; 06395 06396 break; 06397 } 06398 } 06399 } 06400 } 06401 *number = count; 06402 return PAPI_OK; 06403 } 06404 06405 06423 int 06424 PAPI_get_event_component( int EventCode) 06425 { 06426 return _papi_hwi_component_index( EventCode); 06427 } 06428 06450 int PAPI_get_component_index(char *name) 06451 { 06452 int cidx; 06453 06454 const PAPI_component_info_t *cinfo; 06455 06456 for(cidx=0;cidx<papi_num_components;cidx++) { 06457 06458 cinfo=PAPI_get_component_info(cidx); 06459 if (cinfo==NULL) return PAPI_ENOCMP; 06460 06461 if (!strncmp(name,cinfo->name,strlen(cinfo->name))) { 06462 return cidx; 06463 } 06464 } 06465 06466 return PAPI_ENOCMP; 06467 } 06468 06469 06505 int 06506 PAPI_disable_component( int cidx ) 06507 { 06508 06509 const PAPI_component_info_t *cinfo; 06510 06511 /* Can only run before PAPI_library_init() is called */ 06512 if (init_level != PAPI_NOT_INITED) { 06513 return PAPI_ENOINIT; 06514 } 06515 06516 cinfo=PAPI_get_component_info(cidx); 06517 if (cinfo==NULL) return PAPI_ENOCMP; 06518 06519 ((PAPI_component_info_t *)cinfo)->disabled=1; 06520 strcpy(((PAPI_component_info_t *)cinfo)->disabled_reason, 06521 "Disabled by PAPI_disable_component()"); 06522 06523 return PAPI_OK; 06524 06525 } 06526 06555 int 06556 PAPI_disable_component_by_name( char *name ) 06557 { 06558 int cidx; 06559 06560 /* I can only be called before init time */ 06561 if (init_level!=PAPI_NOT_INITED) { 06562 return PAPI_ENOINIT; 06563 } 06564 06565 cidx = PAPI_get_component_index(name); 06566 if (cidx>=0) { 06567 return PAPI_disable_component(cidx); 06568 } 06569 06570 return PAPI_ENOCMP; 06571 }