PAPI  5.1.0.2
linux-IOunit.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00020 #include "linux-IOunit.h"
00021 
00022 /* Declare our vector in advance */
00023 papi_vector_t _IOunit_vector;
00024 
00025 /* prototypes */
00026 void user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext );
00027 
00028 /*****************************************************************************
00029  *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
00030  *****************************************************************************/
00031 
00032 /*
00033  * This is called whenever a thread is initialized
00034  */
00035 int
00036 IOUNIT_init_thread( hwd_context_t * ctx )
00037 {
00038 #ifdef DEBUG_BGQ
00039     printf( "IOUNIT_init_thread\n" );
00040 #endif
00041     
00042     ( void ) ctx;
00043     return PAPI_OK;
00044 }
00045 
00046 
00047 /* Initialize hardware counters, setup the function vector table
00048  * and get hardware information, this routine is called when the 
00049  * PAPI process is initialized (IE PAPI_library_init)
00050  */
00051 int
00052 IOUNIT_init_component( int cidx )
00053 {  
00054 #ifdef DEBUG_BGQ
00055     printf( "IOUNIT_init_component\n" );
00056 #endif
00057 
00058     _IOunit_vector.cmp_info.CmpIdx = cidx;
00059 #ifdef DEBUG_BGQ
00060     printf( "IOUNIT_init_component cidx = %d\n", cidx );
00061 #endif
00062     
00063     return ( PAPI_OK );
00064 }
00065 
00066 
00067 /*
00068  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
00069  * functions
00070  */
00071 int
00072 IOUNIT_init_control_state( hwd_control_state_t * ptr )
00073 {
00074 #ifdef DEBUG_BGQ
00075     printf( "IOUNIT_init_control_state\n" );
00076 #endif
00077 
00078     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00079     
00080     this_state->EventGroup = Bgpm_CreateEventSet();
00081     CHECK_BGPM_ERROR( this_state->EventGroup, "Bgpm_CreateEventSet" );
00082     
00083     // initialize overflow flag to OFF (0)
00084     this_state->overflow = 0;
00085     this_state->overflow_threshold = 0;
00086     this_state->overflow_EventIndex = 0;    
00087     
00088     return PAPI_OK;
00089 }
00090 
00091 
00092 /*
00093  *
00094  */
00095 int
00096 IOUNIT_start( hwd_context_t * ctx, hwd_control_state_t * ptr )
00097 {
00098 #ifdef DEBUG_BGQ
00099     printf( "IOUNIT_start\n" );
00100 #endif
00101     ( void ) ctx;
00102     int retval;
00103     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00104     
00105     retval = Bgpm_ResetStart( this_state->EventGroup );
00106     CHECK_BGPM_ERROR( retval, "Bgpm_ResetStart" );
00107     
00108     return ( PAPI_OK );
00109 }
00110 
00111 
00112 /*
00113  *
00114  */
00115 int
00116 IOUNIT_stop( hwd_context_t * ctx, hwd_control_state_t * ptr )
00117 {
00118 #ifdef DEBUG_BGQ
00119     printf( "IOUNIT_stop\n" );
00120 #endif
00121     ( void ) ctx;
00122     int retval;
00123     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00124     
00125     retval = Bgpm_Stop( this_state->EventGroup );
00126     CHECK_BGPM_ERROR( retval, "Bgpm_Stop" );
00127     
00128     return ( PAPI_OK );
00129 }
00130 
00131 
00132 /*
00133  *
00134  */
00135 int
00136 IOUNIT_read( hwd_context_t * ctx, hwd_control_state_t * ptr,
00137            long_long ** events, int flags )
00138 {
00139 #ifdef DEBUG_BGQ
00140     printf( "IOUNIT_read\n" );
00141 #endif
00142     ( void ) ctx;
00143     ( void ) flags;
00144     int i, numEvts;
00145     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00146 
00147     numEvts = Bgpm_NumEvents( this_state->EventGroup );
00148     if ( numEvts == 0 ) {
00149 #ifdef DEBUG_BGPM
00150         printf ("Error: ret value is %d for BGPM API function Bgpm_NumEvents.\n", numEvts );
00151 #endif
00152         //return ( EXIT_FAILURE );
00153     }
00154         
00155     for ( i = 0; i < numEvts; i++ )
00156         this_state->counts[i] = _common_getEventValue( i, this_state->EventGroup );
00157 
00158     *events = this_state->counts;
00159     
00160     return ( PAPI_OK );
00161 }
00162 
00163 
00164 /*
00165  *
00166  */
00167 int
00168 IOUNIT_shutdown_thread( hwd_context_t * ctx )
00169 {
00170 #ifdef DEBUG_BGQ
00171     printf( "IOUNIT_shutdown_thread\n" );
00172 #endif
00173     
00174     ( void ) ctx;
00175     return ( PAPI_OK );
00176 }
00177 
00178 
00179 /*
00180  * user_signal_handler
00181  *
00182  * This function is used when hardware overflows are working or when
00183  * software overflows are forced
00184  */
00185 void
00186 user_signal_handler_IOUNIT( int hEvtSet, uint64_t address, uint64_t ovfVector, const ucontext_t *pContext )
00187 {
00188 #ifdef DEBUG_BGQ
00189     printf( "user_signal_handler_IOUNIT\n" );
00190 #endif
00191     ( void ) address;
00192     int retval;
00193     unsigned i;
00194     int isHardware = 1;
00195     int cidx = _IOunit_vector.cmp_info.CmpIdx;
00196     long_long overflow_bit = 0;
00197     caddr_t address1;
00198     _papi_hwi_context_t ctx;
00199     ctx.ucontext = ( hwd_ucontext_t * ) pContext;
00200     ThreadInfo_t *thread = _papi_hwi_lookup_thread( 0 );
00201     EventSetInfo_t *ESI;
00202     ESI = thread->running_eventset[cidx];
00203     // Get the indices of all events which have overflowed.
00204     unsigned ovfIdxs[BGPM_MAX_OVERFLOW_EVENTS];
00205     unsigned len = BGPM_MAX_OVERFLOW_EVENTS;
00206     
00207     retval = Bgpm_GetOverflowEventIndices( hEvtSet, ovfVector, ovfIdxs, &len );
00208     if ( retval < 0 ) {
00209 #ifdef DEBUG_BGPM
00210         printf ( "Error: ret value is %d for BGPM API function Bgpm_GetOverflowEventIndices.\n", 
00211                 retval ); 
00212 #endif
00213         return;
00214     }
00215     
00216     if ( thread == NULL ) {
00217         PAPIERROR( "thread == NULL in user_signal_handler!" );
00218         return;
00219     }
00220     
00221     if ( ESI == NULL ) {
00222         PAPIERROR( "ESI == NULL in user_signal_handler!");
00223         return;
00224     }
00225     
00226     if ( ESI->overflow.flags == 0 ) {
00227         PAPIERROR( "ESI->overflow.flags == 0 in user_signal_handler!");
00228         return;
00229     }
00230     
00231     for ( i = 0; i < len; i++ ) {
00232         uint64_t hProf;
00233         Bgpm_GetEventUser1( hEvtSet, ovfIdxs[i], &hProf );
00234         if ( hProf ) {
00235             overflow_bit ^= 1 << ovfIdxs[i];
00236             break;
00237         }
00238         
00239     }
00240     
00241     if ( ESI->overflow.flags & PAPI_OVERFLOW_FORCE_SW ) {
00242 #ifdef DEBUG_BGQ
00243         printf("OVERFLOW_SOFTWARE\n");
00244 #endif
00245         address1 = GET_OVERFLOW_ADDRESS( ctx );
00246         _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, NULL, 0, 0, &thread, cidx );
00247         return;
00248     }
00249     else if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
00250 #ifdef DEBUG_BGQ
00251         printf("OVERFLOW_HARDWARE\n");
00252 #endif
00253         address1 = GET_OVERFLOW_ADDRESS( ctx );
00254         _papi_hwi_dispatch_overflow_signal( ( void * ) &ctx, address1, &isHardware, overflow_bit, 0, &thread, cidx );
00255     }
00256     else {
00257 #ifdef DEBUG_BGQ
00258         printf("OVERFLOW_NONE\n");
00259 #endif
00260         PAPIERROR( "ESI->overflow.flags is set to something other than PAPI_OVERFLOW_HARDWARE or PAPI_OVERFLOW_FORCE_SW (%x)", thread->running_eventset[cidx]->overflow.flags);
00261     }
00262 }
00263 
00264 
00265 /*
00266  * Set Overflow
00267  *
00268  * This is commented out in BG/L/P - need to explore and complete...
00269  * However, with true 64-bit counters in BG/Q and all counters for PAPI
00270  * always starting from a true zero (we don't allow write...), the possibility
00271  * for overflow is remote at best...
00272  */
00273 int
00274 IOUNIT_set_overflow( EventSetInfo_t * ESI, int EventIndex, int threshold )
00275 {
00276 #ifdef DEBUG_BGQ
00277     printf("BEGIN IOUNIT_set_overflow\n");
00278 #endif
00279     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ESI->ctl_state;
00280     int retval;
00281     int evt_idx;
00282         
00283     evt_idx = ESI->EventInfoArray[EventIndex].pos[0];
00284     SUBDBG( "Hardware counter %d (vs %d) used in overflow, threshold %d\n",
00285            evt_idx, EventIndex, threshold );
00286 #ifdef DEBUG_BGQ
00287     printf( "Hardware counter %d (vs %d) used in overflow, threshold %d\n",
00288            evt_idx, EventIndex, threshold );
00289 #endif
00290     /* If this counter isn't set to overflow, it's an error */
00291     if ( threshold == 0 ) {
00292         /* Remove the signal handler */
00293         retval = _papi_hwi_stop_signal( _IOunit_vector.cmp_info.hardware_intr_sig );
00294         if ( retval != PAPI_OK )
00295             return ( retval );
00296     }
00297     else {
00298         this_state->overflow = 1;
00299         this_state->overflow_threshold = threshold;
00300         this_state->overflow_EventIndex = evt_idx;
00301         
00302 #ifdef DEBUG_BGQ
00303         printf( "IOUNIT_set_overflow: Enable the signal handler\n" );
00304 #endif
00305         /* Enable the signal handler */
00306         retval = _papi_hwi_start_signal( _IOunit_vector.cmp_info.hardware_intr_sig, 
00307                                         NEED_CONTEXT, 
00308                                         _IOunit_vector.cmp_info.CmpIdx );
00309         if ( retval != PAPI_OK )
00310             return ( retval );
00311 
00312         _common_set_overflow_BGPM( this_state->EventGroup, 
00313                                   this_state->overflow_EventIndex, 
00314                                   this_state->overflow_threshold,
00315                                   user_signal_handler_IOUNIT );
00316     }
00317     
00318     return ( PAPI_OK );
00319 }
00320 
00321 
00322 /* This function sets various options in the component
00323  * The valid codes being passed in are PAPI_SET_DEFDOM,
00324  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00325  */
00326 int
00327 IOUNIT_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00328 {
00329 #ifdef DEBUG_BGQ
00330     printf( "IOUNIT_ctl\n" );
00331 #endif
00332     
00333     ( void ) ctx;
00334     ( void ) code;
00335     ( void ) option;
00336     return ( PAPI_OK );
00337 }
00338 
00339 
00340 /*
00341  *
00342  */
00343 int
00344 IOUNIT_update_control_state( hwd_control_state_t * ptr,
00345                            NativeInfo_t * native, int count,
00346                            hwd_context_t * ctx )
00347 {
00348 #ifdef DEBUG_BGQ
00349     printf( "IOUNIT_update_control_state: count = %d\n", count );
00350 #endif
00351     ( void ) ctx;
00352     int retval, index, i;
00353     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00354     
00355     // Delete and re-create BGPM eventset
00356     _common_deleteRecreate( &this_state->EventGroup );
00357 
00358 #ifdef DEBUG_BGQ
00359     printf( "IOUNIT_update_control_state: EventGroup=%d, overflow = %d\n",
00360            this_state->EventGroup, this_state->overflow );
00361 #endif
00362         
00363     // otherwise, add the events to the eventset
00364     for ( i = 0; i < count; i++ ) {
00365         index = ( native[i].ni_event ) + OFFSET;
00366         
00367         native[i].ni_position = i;
00368 
00369 #ifdef DEBUG_BGQ
00370         printf("IOUNIT_update_control_state: ADD event: i = %d, index = %d\n", i, index );
00371 #endif
00372                 
00373         /* Add events to the BGPM eventGroup */
00374         retval = Bgpm_AddEvent( this_state->EventGroup, index );
00375         CHECK_BGPM_ERROR( retval, "Bgpm_AddEvent" );
00376     }
00377 
00378     
00379     // since update_control_state trashes overflow settings, this puts things
00380     // back into balance for BGPM 
00381     if ( 1 == this_state->overflow ) {
00382         _common_set_overflow_BGPM( this_state->EventGroup, 
00383                                   this_state->overflow_EventIndex, 
00384                                   this_state->overflow_threshold,
00385                                   user_signal_handler_IOUNIT );
00386     }
00387     
00388     return ( PAPI_OK );
00389 }
00390 
00391 
00392 /*
00393  * This function has to set the bits needed to count different domains
00394  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00395  * By default return PAPI_EINVAL if none of those are specified
00396  * and PAPI_OK with success
00397  * PAPI_DOM_USER is only user context is counted
00398  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00399  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00400  * PAPI_DOM_ALL   is all of the domains
00401  */
00402 int
00403 IOUNIT_set_domain( hwd_control_state_t * cntrl, int domain )
00404 {
00405 #ifdef DEBUG_BGQ
00406     printf( "IOUNIT_set_domain\n" );
00407 #endif
00408     int found = 0;
00409     ( void ) cntrl;
00410 
00411     if ( PAPI_DOM_USER & domain )
00412         found = 1;
00413 
00414     if ( PAPI_DOM_KERNEL & domain )
00415         found = 1;
00416 
00417     if ( PAPI_DOM_OTHER & domain )
00418         found = 1;
00419 
00420     if ( !found )
00421         return ( PAPI_EINVAL );
00422 
00423     return ( PAPI_OK );
00424 }
00425 
00426 
00427 /*
00428  *
00429  */
00430 int
00431 IOUNIT_reset( hwd_context_t * ctx, hwd_control_state_t * ptr )
00432 {
00433 #ifdef DEBUG_BGQ
00434     printf( "IOUNIT_reset\n" );
00435 #endif
00436     ( void ) ctx;
00437     int retval;
00438     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ptr;
00439 
00440     /* we can't simply call Bgpm_Reset() since PAPI doesn't have the 
00441      restriction that an EventSet has to be stopped before resetting is
00442      possible. However, BGPM does have this restriction. 
00443      Hence we need to stop, reset and start */
00444     retval = Bgpm_Stop( this_state->EventGroup );
00445     CHECK_BGPM_ERROR( retval, "Bgpm_Stop" );
00446     
00447     retval = Bgpm_ResetStart( this_state->EventGroup );
00448     CHECK_BGPM_ERROR( retval, "Bgpm_ResetStart" );
00449     
00450     return ( PAPI_OK );
00451 }
00452 
00453 
00454 /*
00455  * PAPI Cleanup Eventset
00456  *
00457  * Destroy and re-create the BGPM / IOunit EventSet
00458  */
00459 int
00460 IOUNIT_cleanup_eventset( hwd_control_state_t * ctrl )
00461 {
00462 #ifdef DEBUG_BGQ
00463     printf( "IOUNIT_cleanup_eventset\n" );
00464 #endif
00465     
00466     IOUNIT_control_state_t * this_state = ( IOUNIT_control_state_t * ) ctrl;
00467         
00468     // create a new empty bgpm eventset
00469     // reason: bgpm doesn't permit to remove events from an eventset; 
00470     // hence we delete the old eventset and create a new one
00471     _common_deleteRecreate( &this_state->EventGroup ); // HJ try to use delete() only
00472 
00473     // set overflow flag to OFF (0)
00474     this_state->overflow = 0;
00475     this_state->overflow_threshold = 0;
00476     this_state->overflow_EventIndex = 0;    
00477     
00478     return ( PAPI_OK );
00479 }
00480 
00481 
00482 /*
00483  * Native Event functions
00484  */
00485 int
00486 IOUNIT_ntv_enum_events( unsigned int *EventCode, int modifier )
00487 {
00488 #ifdef DEBUG_BGQ
00489     //printf( "IOUNIT_ntv_enum_events\n" );
00490 #endif
00491 
00492     switch ( modifier ) {
00493     case PAPI_ENUM_FIRST:
00494         *EventCode = 0;
00495 
00496         return ( PAPI_OK );
00497         break;
00498 
00499     case PAPI_ENUM_EVENTS:
00500     {
00501         int index = ( *EventCode ) + OFFSET;
00502 
00503         if ( index < IOUNIT_MAX_COUNTERS ) {
00504             *EventCode = *EventCode + 1;
00505             return ( PAPI_OK );
00506         } else
00507             return ( PAPI_ENOEVNT );
00508 
00509         break;
00510     }
00511     default:
00512         return ( PAPI_EINVAL );
00513     }
00514     return ( PAPI_EINVAL );
00515 }
00516 
00517 
00518 /*
00519  *
00520  */
00521 int
00522 IOUNIT_ntv_name_to_code( char *name, unsigned int *event_code )
00523 {
00524 #ifdef DEBUG_BGQ
00525     printf( "IOUNIT_ntv_name_to_code\n" );
00526 #endif
00527     int ret;
00528     
00529     /* Return event id matching a given event label string */
00530     ret = Bgpm_GetEventIdFromLabel ( name );
00531     
00532     if ( ret <= 0 ) {
00533 #ifdef DEBUG_BGPM
00534         printf ("Error: ret value is %d for BGPM API function '%s'.\n",
00535                 ret, "Bgpm_GetEventIdFromLabel" );
00536 #endif
00537         return PAPI_ENOEVNT;
00538     }
00539     else if ( ret < OFFSET || ret > IOUNIT_MAX_COUNTERS ) // not an IOUnit event
00540         return PAPI_ENOEVNT;
00541     else
00542         *event_code = ( ret - OFFSET ) ;
00543     
00544     return PAPI_OK;
00545 }
00546 
00547 
00548 /*
00549  *
00550  */
00551 int
00552 IOUNIT_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00553 {
00554 #ifdef DEBUG_BGQ
00555     //printf( "IOUNIT_ntv_code_to_name\n" );
00556 #endif
00557     int index;
00558     
00559     index = ( EventCode ) + OFFSET;
00560 
00561     if ( index >= MAX_COUNTERS )
00562         return PAPI_ENOEVNT;
00563 
00564     strncpy( name, Bgpm_GetEventIdLabel( index ), len );
00565     
00566     if ( name == NULL ) {
00567 #ifdef DEBUG_BGPM
00568         printf ("Error: ret value is NULL for BGPM API function Bgpm_GetEventIdLabel.\n" );
00569 #endif
00570         return PAPI_ENOEVNT;
00571     }
00572     
00573     return ( PAPI_OK );
00574 }
00575 
00576 
00577 /*
00578  *
00579  */
00580 int
00581 IOUNIT_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00582 {
00583 #ifdef DEBUG_BGQ
00584     //printf( "IOUNIT_ntv_code_to_descr\n" );
00585 #endif  
00586     int retval, index;
00587     
00588     index = ( EventCode ) + OFFSET;
00589     
00590     retval = Bgpm_GetLongDesc( index, name, &len );
00591     CHECK_BGPM_ERROR( retval, "Bgpm_GetLongDesc" );                      
00592     
00593     return ( PAPI_OK );
00594 }
00595 
00596 
00597 /*
00598  *
00599  */
00600 int
00601 IOUNIT_ntv_code_to_bits( unsigned int EventCode, hwd_register_t * bits )
00602 {
00603 #ifdef DEBUG_BGQ
00604     printf( "IOUNIT_ntv_code_to_bits\n" );
00605 #endif
00606     ( void ) EventCode;
00607     ( void ) bits;
00608     return ( PAPI_OK );
00609 }
00610 
00611 
00612 /*
00613  *
00614  */
00615 papi_vector_t _IOunit_vector = {
00616     .cmp_info = {
00617                  /* default component information (unspecified values are initialized to 0) */
00618                  .name = "bgpm/IOUnit",
00619                  .short_name = "IOUnit",
00620                  .description = "Blue Gene/Q IOUnit component",
00621                  .num_cntrs = IOUNIT_MAX_COUNTERS,
00622                  .num_mpx_cntrs = IOUNIT_MAX_COUNTERS,
00623                  .default_domain = PAPI_DOM_USER,
00624                  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00625                  .default_granularity = PAPI_GRN_THR,
00626                  .available_granularities = PAPI_GRN_THR,
00627 
00628                  .hardware_intr_sig = PAPI_INT_SIGNAL,
00629                  .hardware_intr = 1,
00630         
00631                  .kernel_multiplex = 0,
00632 
00633                  /* component specific cmp_info initializations */
00634                  .fast_real_timer = 0,
00635                  .fast_virtual_timer = 0,
00636                  .attach = 0,
00637                  .attach_must_ptrace = 0,
00638                  }
00639     ,
00640 
00641     /* sizes of framework-opaque component-private structures */
00642     .size = {
00643              .context = sizeof ( IOUNIT_context_t ),
00644              .control_state = sizeof ( IOUNIT_control_state_t ),
00645              .reg_value = sizeof ( IOUNIT_register_t ),
00646              .reg_alloc = sizeof ( IOUNIT_reg_alloc_t ),
00647              }
00648     ,
00649     /* function pointers in this component */
00650     .init_thread = IOUNIT_init_thread,
00651     .init_component = IOUNIT_init_component,
00652     .init_control_state = IOUNIT_init_control_state,
00653     .start = IOUNIT_start,
00654     .stop = IOUNIT_stop,
00655     .read = IOUNIT_read,
00656     .shutdown_thread = IOUNIT_shutdown_thread,
00657     .set_overflow = IOUNIT_set_overflow,
00658     .cleanup_eventset = IOUNIT_cleanup_eventset,
00659     .ctl = IOUNIT_ctl,
00660     
00661     .update_control_state = IOUNIT_update_control_state,
00662     .set_domain = IOUNIT_set_domain,
00663     .reset = IOUNIT_reset,
00664 
00665     .ntv_name_to_code = IOUNIT_ntv_name_to_code,
00666     .ntv_enum_events = IOUNIT_ntv_enum_events,
00667     .ntv_code_to_name = IOUNIT_ntv_code_to_name,
00668     .ntv_code_to_descr = IOUNIT_ntv_code_to_descr,
00669     .ntv_code_to_bits = IOUNIT_ntv_code_to_bits
00670 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines