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