PAPI  5.0.1.0
example.c
Go to the documentation of this file.
00001 
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <stdlib.h>
00018 #include <inttypes.h>
00019 
00020 /* Headers required by PAPI */
00021 #include "papi.h"
00022 #include "papi_internal.h"
00023 #include "papi_vector.h"
00024 #include "papi_memory.h"    /* defines papi_malloc(), etc. */
00025 
00027 /*  This is artificially low to allow testing of multiplexing */
00028 #define EXAMPLE_MAX_SIMULTANEOUS_COUNTERS 3
00029 #define EXAMPLE_MAX_MULTIPLEX_COUNTERS 4
00030 
00031 /* Declare our vector in advance */
00032 /* This allows us to modify the component info */
00033 papi_vector_t _example_vector;
00034 
00036 typedef struct example_register
00037 {
00038    unsigned int selector;
00041 } example_register_t;
00042 
00044 /*   The contents of this structure will vary based on   */
00045 /*   your component, however having name and description */
00046 /*   fields are probably useful.                         */
00047 typedef struct example_native_event_entry
00048 {
00049     example_register_t resources;       
00050     char name[PAPI_MAX_STR_LEN];        
00051     char description[PAPI_MAX_STR_LEN]; 
00052     int writable;               
00053     /* any other counter parameters go here */
00054 } example_native_event_entry_t;
00055 
00059 typedef struct example_reg_alloc
00060 {
00061     example_register_t ra_bits;
00062 } example_reg_alloc_t;
00063 
00069 typedef struct example_control_state
00070 {
00071   int num_events;
00072   int domain;
00073   int multiplexed;
00074   int overflow;
00075   int inherit;
00076   int which_counter[EXAMPLE_MAX_SIMULTANEOUS_COUNTERS]; 
00077   long long counter[EXAMPLE_MAX_MULTIPLEX_COUNTERS];   
00078 } example_control_state_t;
00079 
00081 typedef struct example_context
00082 {
00083      long long autoinc_value;
00084 } example_context_t;
00085 
00087 static example_native_event_entry_t *example_native_table;
00088 
00090 static int num_events = 0;
00091 
00092 
00093 /*************************************************************************/
00094 /* Below is the actual "hardware implementation" of our example counters */
00095 /*************************************************************************/
00096 
00097 #define EXAMPLE_ZERO_REG             0
00098 #define EXAMPLE_CONSTANT_REG         1
00099 #define EXAMPLE_AUTOINC_REG          2
00100 #define EXAMPLE_GLOBAL_AUTOINC_REG   3
00101 
00102 #define EXAMPLE_TOTAL_EVENTS         4
00103 
00104 static long long example_global_autoinc_value = 0;
00105 
00107 static void
00108 example_hardware_reset( example_context_t *ctx )
00109 {
00110    /* reset per-thread count */
00111    ctx->autoinc_value=0;
00112    /* reset global count */
00113    example_global_autoinc_value = 0;
00114 
00115 }
00116 
00118 /*   You might replace this with code that accesses       */
00119 /*   hardware or reads values from the operatings system. */
00120 static long long
00121 example_hardware_read( int which_one, example_context_t *ctx )
00122 {
00123     long long old_value;
00124 
00125     switch ( which_one ) {
00126     case EXAMPLE_ZERO_REG:
00127         return 0;
00128     case EXAMPLE_CONSTANT_REG:
00129         return 42;
00130     case EXAMPLE_AUTOINC_REG:
00131         old_value = ctx->autoinc_value;
00132         ctx->autoinc_value++;
00133         return old_value;
00134     case EXAMPLE_GLOBAL_AUTOINC_REG:
00135         old_value = example_global_autoinc_value;
00136         example_global_autoinc_value++;
00137         return old_value;
00138     default:
00139             fprintf(stderr,"Invalid counter read %x\n",which_one );
00140         return -1;
00141     }
00142 
00143     return 0;
00144 }
00145 
00147 static int
00148 example_hardware_write( int which_one, 
00149             example_context_t *ctx,
00150             long long value)
00151 {
00152 
00153     switch ( which_one ) {
00154     case EXAMPLE_ZERO_REG:
00155     case EXAMPLE_CONSTANT_REG:
00156         return PAPI_OK; /* can't be written */
00157     case EXAMPLE_AUTOINC_REG:
00158         ctx->autoinc_value=value;
00159         return PAPI_OK;
00160     case EXAMPLE_GLOBAL_AUTOINC_REG:
00161             example_global_autoinc_value=value;
00162         return PAPI_OK;
00163     default:
00164         perror( "Invalid counter write" );
00165         return -1;
00166     }
00167 
00168     return 0;
00169 }
00170 
00171 static int
00172 detect_example(void) {
00173  
00174    return PAPI_OK;
00175 }
00176 
00177 /********************************************************************/
00178 /* Below are the functions required by the PAPI component interface */
00179 /********************************************************************/
00180 
00181 
00186 int
00187 _example_init_component( int cidx )
00188 {
00189 
00190     SUBDBG( "_example_init_component..." );
00191 
00192    
00193         /* First, detect that our hardware is available */
00194         if (detect_example()!=PAPI_OK) {
00195        return PAPI_ECMP;
00196     }
00197    
00198     /* we know in advance how many events we want                       */
00199     /* for actual hardware this might have to be determined dynamically */
00200     num_events = EXAMPLE_TOTAL_EVENTS;
00201 
00202     /* Allocate memory for the our native event table */
00203     example_native_table =
00204         ( example_native_event_entry_t * )
00205         papi_calloc( sizeof(example_native_event_entry_t),num_events);
00206     if ( example_native_table == NULL ) {
00207         PAPIERROR( "malloc():Could not get memory for events table" );
00208         return PAPI_ENOMEM;
00209     }
00210 
00211     /* fill in the event table parameters */
00212     /* for complicated components this will be done dynamically */
00213     /* or by using an external library                          */
00214 
00215     strcpy( example_native_table[0].name, "EXAMPLE_ZERO" );
00216     strcpy( example_native_table[0].description,
00217             "This is an example counter, that always returns 0" );
00218     example_native_table[0].writable = 0;
00219 
00220     strcpy( example_native_table[1].name, "EXAMPLE_CONSTANT" );
00221     strcpy( example_native_table[1].description,
00222             "This is an example counter, that always returns a constant value of 42" );
00223     example_native_table[1].writable = 0;
00224 
00225     strcpy( example_native_table[2].name, "EXAMPLE_AUTOINC" );
00226     strcpy( example_native_table[2].description,
00227             "This is an example counter, that reports a per-thread  auto-incrementing value" );
00228     example_native_table[2].writable = 1;
00229 
00230     strcpy( example_native_table[3].name, "EXAMPLE_GLOBAL_AUTOINC" );
00231     strcpy( example_native_table[3].description,
00232             "This is an example counter, that reports a global auto-incrementing value" );
00233     example_native_table[3].writable = 1;
00234 
00235     /* Export the total number of events available */
00236     _example_vector.cmp_info.num_native_events = num_events;
00237 
00238     /* Export the component id */
00239     _example_vector.cmp_info.CmpIdx = cidx;
00240 
00241     
00242 
00243     return PAPI_OK;
00244 }
00245 
00247 int
00248 _example_init_thread( hwd_context_t *ctx )
00249 {
00250 
00251         example_context_t *example_context = (example_context_t *)ctx;
00252 
00253         example_context->autoinc_value=0;
00254    
00255     SUBDBG( "_example_init_thread %p...", ctx );
00256 
00257     return PAPI_OK;
00258 }
00259 
00260 
00261 
00267 int
00268 _example_init_control_state( hwd_control_state_t * ctl )
00269 {
00270    SUBDBG( "example_init_control_state... %p\n", ctl );
00271 
00272    example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
00273    memset( example_ctl, 0, sizeof ( example_control_state_t ) );
00274 
00275    return PAPI_OK;
00276 }
00277 
00278 
00280 int
00281 _example_update_control_state( hwd_control_state_t *ctl, 
00282                     NativeInfo_t *native,
00283                     int count, 
00284                     hwd_context_t *ctx )
00285 {
00286    
00287    (void) ctx;
00288    int i, index;
00289 
00290    example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;   
00291 
00292    SUBDBG( "_example_update_control_state %p %p...", ctl, ctx );
00293 
00294    /* if no events, return */
00295    if (count==0) return PAPI_OK;
00296 
00297    for( i = 0; i < count; i++ ) {
00298       index = native[i].ni_event;
00299       
00300       /* Map counter #i to Measure Event "index" */
00301       example_ctl->which_counter[i]=index;
00302 
00303       /* We have no constraints on event position, so any event */
00304       /* can be in any slot.                                    */
00305       native[i].ni_position = i;
00306    }
00307 
00308    example_ctl->num_events=count;
00309 
00310    return PAPI_OK;
00311 }
00312 
00314 int
00315 _example_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
00316 {
00317 
00318         (void) ctx;
00319         (void) ctl;
00320 
00321     SUBDBG( "example_start %p %p...", ctx, ctl );
00322 
00323     /* anything that would need to be set at counter start time */
00324 
00325     /* reset counters? */
00326         /* For hardware that cannot reset counters, store initial        */
00327         /*     counter state to the ctl and subtract it off at read time */
00328      
00329     /* start the counting ?*/
00330 
00331     return PAPI_OK;
00332 }
00333 
00334 
00336 int
00337 _example_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00338 {
00339 
00340         (void) ctx;
00341         (void) ctl;
00342 
00343     SUBDBG( "example_stop %p %p...", ctx, ctl );
00344 
00345     /* anything that would need to be done at counter stop time */
00346 
00347     
00348 
00349     return PAPI_OK;
00350 }
00351 
00352 
00354 /*     flags field is never set? */
00355 int
00356 _example_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00357               long long **events, int flags )
00358 {
00359 
00360    (void) flags;
00361 
00362    example_context_t *example_ctx = (example_context_t *) ctx;
00363    example_control_state_t *example_ctl = ( example_control_state_t *) ctl;   
00364 
00365    SUBDBG( "example_read... %p %d", ctx, flags );
00366 
00367    int i;
00368 
00369    /* Read counters into expected slot */
00370    for(i=0;i<example_ctl->num_events;i++) {
00371       example_ctl->counter[i] =
00372         example_hardware_read( example_ctl->which_counter[i], 
00373                        example_ctx );
00374    }
00375 
00376    /* return pointer to the values we read */
00377    *events = example_ctl->counter;
00378 
00379    return PAPI_OK;
00380 }
00381 
00383 /*    otherwise, the updated state is written to ESI->hw_start      */
00384 int
00385 _example_write( hwd_context_t *ctx, hwd_control_state_t *ctl,
00386                long long *events )
00387 {
00388 
00389         example_context_t *example_ctx = (example_context_t *) ctx;
00390         example_control_state_t *example_ctl = ( example_control_state_t *) ctl;   
00391    
00392         int i;
00393    
00394     SUBDBG( "example_write... %p %p", ctx, ctl );
00395 
00396         /* Write counters into expected slot */
00397         for(i=0;i<example_ctl->num_events;i++) {
00398        example_hardware_write( example_ctl->which_counter[i],
00399                    example_ctx,
00400                    events[i] );
00401     }
00402    
00403     return PAPI_OK;
00404 }
00405 
00406 
00408 /*  If the eventset is not currently running, then the saved value in the   */
00409 /*  EventSet is set to zero without calling this routine.                   */
00410 int
00411 _example_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
00412 {
00413         example_context_t *event_ctx = (example_context_t *)ctx;
00414     (void) ctl;
00415 
00416     SUBDBG( "example_reset ctx=%p ctrl=%p...", ctx, ctl );
00417 
00418     /* Reset the hardware */
00419     example_hardware_reset( event_ctx );
00420 
00421     return PAPI_OK;
00422 }
00423 
00425 int
00426 _example_shutdown_component(void)
00427 {
00428 
00429     SUBDBG( "example_shutdown_component..." );
00430 
00431         /* Free anything we allocated */
00432    
00433     papi_free(example_native_table);
00434 
00435     return PAPI_OK;
00436 }
00437 
00439 int
00440 _example_shutdown_thread( hwd_context_t *ctx )
00441 {
00442 
00443         (void) ctx;
00444 
00445     SUBDBG( "example_shutdown_thread... %p", ctx );
00446 
00447     /* Last chance to clean up thread */
00448 
00449     return PAPI_OK;
00450 }
00451 
00452 
00453 
00460 int
00461 _example_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
00462 {
00463 
00464         (void) ctx;
00465     (void) code;
00466     (void) option;
00467 
00468     SUBDBG( "example_ctl..." );
00469 
00470     return PAPI_OK;
00471 }
00472 
00482 int
00483 _example_set_domain( hwd_control_state_t * cntrl, int domain )
00484 {
00485         (void) cntrl;
00486 
00487     int found = 0;
00488     SUBDBG( "example_set_domain..." );
00489 
00490     if ( PAPI_DOM_USER & domain ) {
00491         SUBDBG( " PAPI_DOM_USER " );
00492         found = 1;
00493     }
00494     if ( PAPI_DOM_KERNEL & domain ) {
00495         SUBDBG( " PAPI_DOM_KERNEL " );
00496         found = 1;
00497     }
00498     if ( PAPI_DOM_OTHER & domain ) {
00499         SUBDBG( " PAPI_DOM_OTHER " );
00500         found = 1;
00501     }
00502     if ( PAPI_DOM_ALL & domain ) {
00503         SUBDBG( " PAPI_DOM_ALL " );
00504         found = 1;
00505     }
00506     if ( !found )
00507         return ( PAPI_EINVAL );
00508 
00509     return PAPI_OK;
00510 }
00511 
00512 
00513 /**************************************************************/
00514 /* Naming functions, used to translate event numbers to names */
00515 /**************************************************************/
00516 
00517 
00524 int
00525 _example_ntv_enum_events( unsigned int *EventCode, int modifier )
00526 {
00527   int index;
00528 
00529 
00530   switch ( modifier ) {
00531 
00532         /* return EventCode of first event */
00533     case PAPI_ENUM_FIRST:
00534        /* return the first event that we support */
00535 
00536        *EventCode = 0;
00537        return PAPI_OK;
00538 
00539         /* return EventCode of next available event */
00540     case PAPI_ENUM_EVENTS:
00541        index = *EventCode;
00542 
00543        /* Make sure we have at least 1 more event after us */
00544        if ( index < num_events - 1 ) {
00545 
00546           /* This assumes a non-sparse mapping of the events */
00547           *EventCode = *EventCode + 1;
00548           return PAPI_OK;
00549        } else {
00550           return PAPI_ENOEVNT;
00551        }
00552        break;
00553     
00554     default:
00555        return PAPI_EINVAL;
00556   }
00557 
00558   return PAPI_EINVAL;
00559 }
00560 
00566 int
00567 _example_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00568 {
00569   int index;
00570 
00571   index = EventCode;
00572 
00573   /* Make sure we are in range */
00574   if (index >= 0 && index < num_events) {
00575      strncpy( name, example_native_table[index].name, len );  
00576      return PAPI_OK;
00577   }
00578    
00579   return PAPI_ENOEVNT;
00580 }
00581 
00587 int
00588 _example_ntv_code_to_descr( unsigned int EventCode, char *descr, int len )
00589 {
00590   int index;
00591   index = EventCode;
00592 
00593   /* make sure event is in range */
00594   if (index >= 0 && index < num_events) {
00595      strncpy( descr, example_native_table[index].description, len );
00596      return PAPI_OK;
00597   }
00598   
00599   return PAPI_ENOEVNT;
00600 }
00601 
00603 papi_vector_t _example_vector = {
00604     .cmp_info = {
00605         /* default component information */
00606         /* (unspecified values are initialized to 0) */
00607                 /* we explicitly set them to zero in this example */
00608                 /* to show what settings are available            */
00609 
00610         .name = "example",
00611         .short_name = "example",
00612         .description = "A simple example component",
00613         .version = "1.15",
00614         .support_version = "n/a",
00615         .kernel_version = "n/a",
00616         .num_cntrs =               EXAMPLE_MAX_SIMULTANEOUS_COUNTERS, 
00617         .num_mpx_cntrs =           EXAMPLE_MAX_SIMULTANEOUS_COUNTERS,
00618         .default_domain =          PAPI_DOM_USER,
00619         .available_domains =       PAPI_DOM_USER,
00620         .default_granularity =     PAPI_GRN_THR,
00621         .available_granularities = PAPI_GRN_THR,
00622         .hardware_intr_sig =       PAPI_INT_SIGNAL,
00623 
00624         /* component specific cmp_info initializations */
00625     },
00626 
00627     /* sizes of framework-opaque component-private structures */
00628     .size = {
00629             /* once per thread */
00630         .context = sizeof ( example_context_t ),
00631             /* once per eventset */
00632         .control_state = sizeof ( example_control_state_t ),
00633             /* ?? */
00634         .reg_value = sizeof ( example_register_t ),
00635             /* ?? */
00636         .reg_alloc = sizeof ( example_reg_alloc_t ),
00637     },
00638 
00639     /* function pointers */
00640         /* by default they are set to NULL */
00641    
00642     /* Used for general PAPI interactions */
00643     .start =                _example_start,
00644     .stop =                 _example_stop,
00645     .read =                 _example_read,
00646     .reset =                _example_reset, 
00647     .write =                _example_write,
00648     .init_component =       _example_init_component,    
00649     .init_thread =          _example_init_thread,
00650     .init_control_state =   _example_init_control_state,
00651     .update_control_state = _example_update_control_state,  
00652     .ctl =                  _example_ctl,   
00653     .shutdown_thread =      _example_shutdown_thread,
00654     .shutdown_component =   _example_shutdown_component,
00655     .set_domain =           _example_set_domain,
00656     /* .cleanup_eventset =     NULL, */
00657     /* called in add_native_events() */
00658     /* .allocate_registers =   NULL, */
00659 
00660     /* Used for overflow/profiling */
00661     /* .dispatch_timer =       NULL, */
00662     /* .get_overflow_address = NULL, */
00663     /* .stop_profiling =       NULL, */
00664     /* .set_overflow =         NULL, */
00665     /* .set_profile =          NULL, */
00666 
00667     /* ??? */
00668     /* .user =                 NULL, */
00669 
00670     /* Name Mapping Functions */
00671     .ntv_enum_events =   _example_ntv_enum_events,
00672     .ntv_code_to_name =  _example_ntv_code_to_name,
00673     .ntv_code_to_descr = _example_ntv_code_to_descr,
00674         /* if .ntv_name_to_code not available, PAPI emulates  */
00675         /* it by enumerating all events and looking manually  */
00676     .ntv_name_to_code  = NULL,
00677 
00678    
00679     /* These are only used by _papi_hwi_get_native_event_info() */
00680     /* Which currently only uses the info for printing native   */
00681     /* event info, not for any sort of internal use.            */
00682     /* .ntv_code_to_bits =  NULL, */
00683 
00684 };
00685 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines