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