PAPI  5.0.1.0
linux-stealtime.c
Go to the documentation of this file.
00001 
00008 #include <string.h>
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 #include <fcntl.h>
00012 #include <dirent.h>
00013 #include <stdint.h>
00014 #include <ctype.h>
00015 
00016 #include "papi.h"
00017 #include "papi_internal.h"
00018 #include "papi_vector.h"
00019 #include "papi_memory.h"
00020 
00021 struct counter_info
00022 {
00023     char *name;
00024     char *description;
00025         char *units;
00026     unsigned long long value;
00027 };
00028 
00029 typedef struct counter_info STEALTIME_register_t;
00030 typedef struct counter_info STEALTIME_native_event_entry_t;
00031 typedef struct counter_info STEALTIME_reg_alloc_t;
00032 
00033 
00034 struct STEALTIME_control_state
00035 {
00036   long long *values;
00037   int *which_counter;
00038   int num_events;
00039 };
00040 
00041 
00042 struct STEALTIME_context
00043 {
00044   long long *start_count;
00045   long long *current_count;
00046   long long *value;
00047 };
00048 
00049 
00050 static int num_events = 0;
00051 
00052 static struct counter_info *event_info=NULL;
00053 
00054 /* Advance declaration of buffer */
00055 papi_vector_t _stealtime_vector;
00056 
00057 /******************************************************************************
00058  ********  BEGIN FUNCTIONS  USED INTERNALLY SPECIFIC TO THIS COMPONENT ********
00059  *****************************************************************************/
00060 
00061 struct statinfo {
00062   long long user;
00063   long long nice;
00064   long long system;
00065   long long idle;
00066   long long iowait;
00067   long long irq;
00068   long long softirq;
00069   long long steal;
00070   long long guest;
00071 };
00072 
00073 int read_stealtime( struct STEALTIME_context *context, int starting) {
00074 
00075   FILE *fff;
00076   char buffer[BUFSIZ],*result;
00077   int i,count;
00078   struct statinfo our_stat;
00079 
00080   int hz=sysconf(_SC_CLK_TCK);
00081 
00082 
00083   fff=fopen("/proc/stat","r");
00084   if (fff==NULL) {
00085      return PAPI_ESYS; 
00086   }
00087 
00088   for(i=0;i<num_events;i++) {
00089     result=fgets(buffer,BUFSIZ,fff);
00090     if (result==NULL) break;
00091 
00092     count=sscanf(buffer,"%*s %lld %lld %lld %lld %lld %lld %lld %lld %lld",
00093          &our_stat.user,
00094          &our_stat.nice,
00095          &our_stat.system,
00096          &our_stat.idle,
00097          &our_stat.iowait,
00098          &our_stat.irq,
00099          &our_stat.softirq,
00100          &our_stat.steal,
00101          &our_stat.guest);
00102     if (count<=7) {
00103        fclose(fff);
00104        return PAPI_ESYS;
00105     }
00106 
00107     if (starting) {
00108        context->start_count[i]=our_stat.steal;
00109     }
00110     context->current_count[i]=our_stat.steal;
00111 
00112     /* convert to us */
00113     context->value[i]=(context->current_count[i]-context->start_count[i])*
00114       (1000000/hz);
00115   }
00116   
00117 
00118   fclose(fff);
00119 
00120   return PAPI_OK;
00121 
00122 }
00123 
00124 
00125 
00126 /*****************************************************************************
00127  *******************  BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS  *************
00128  *****************************************************************************/
00129 
00130 /*
00131  * Component setup and shutdown
00132  */
00133 
00134 int
00135 _stealtime_init_component( int cidx )
00136 {
00137 
00138   (void)cidx;
00139 
00140     FILE *fff;
00141     char buffer[BUFSIZ],*result,string[BUFSIZ];
00142     int i;
00143 
00144     /* Make sure /proc/stat exists */
00145     fff=fopen("/proc/stat","r");
00146     if (fff==NULL) {
00147        strncpy(_stealtime_vector.cmp_info.disabled_reason,
00148            "Cannot open /proc/stat",PAPI_MAX_STR_LEN);
00149        return PAPI_ESYS;
00150     }
00151 
00152     num_events=0;
00153     while(1) {
00154       result=fgets(buffer,BUFSIZ,fff);
00155       if (result==NULL) break;
00156 
00157       /* /proc/stat line with cpu stats always starts with "cpu" */
00158 
00159       if (!strncmp(buffer,"cpu",3)) {
00160          num_events++;
00161       }
00162       else {
00163         break;
00164       }
00165 
00166     }
00167 
00168     fclose(fff);
00169 
00170     if (num_events<1) {
00171        strncpy(_stealtime_vector.cmp_info.disabled_reason,
00172            "Cannot find enough CPU lines in /proc/stat",
00173            PAPI_MAX_STR_LEN);
00174        return PAPI_ESYS;
00175     }
00176 
00177     event_info=calloc(num_events,sizeof(struct counter_info));
00178     if (event_info==NULL) {
00179        return PAPI_ENOMEM;
00180     }
00181 
00182     
00183     sysconf(_SC_CLK_TCK);
00184     event_info[0].name=strdup("TOTAL");
00185     event_info[0].description=strdup("Total amount of steal time");
00186     event_info[0].units=strdup("us");
00187 
00188     for(i=1;i<num_events;i++) {
00189        sprintf(string,"CPU%d",i);
00190        event_info[i].name=strdup(string);
00191        sprintf(string,"Steal time for CPU %d",i);
00192        event_info[i].description=strdup(string);
00193        event_info[i].units=strdup("us");
00194         }
00195 
00196     //  printf("Found %d CPUs\n",num_events-1);
00197 
00198     _stealtime_vector.cmp_info.num_native_events=num_events;
00199     _stealtime_vector.cmp_info.num_cntrs=num_events;
00200     _stealtime_vector.cmp_info.num_mpx_cntrs=num_events;
00201 
00202     return PAPI_OK;
00203 }
00204 
00205 
00206 
00207 
00208 
00209 /*
00210  * This is called whenever a thread is initialized
00211  */
00212 int
00213 _stealtime_init_thread( hwd_context_t * ctx )
00214 {
00215   struct STEALTIME_context *context=(struct STEALTIME_context *)ctx;
00216 
00217   context->start_count=calloc(num_events,sizeof(long long));
00218   if (context->start_count==NULL) return PAPI_ENOMEM;
00219 
00220   context->current_count=calloc(num_events,sizeof(long long));
00221   if (context->current_count==NULL) return PAPI_ENOMEM;
00222 
00223   context->value=calloc(num_events,sizeof(long long));
00224   if (context->value==NULL) return PAPI_ENOMEM;
00225 
00226   return PAPI_OK;
00227 }
00228 
00229 
00230 /*
00231  *
00232  */
00233 int
00234 _stealtime_shutdown_component( void )
00235 {
00236 
00237    if (event_info!=NULL) free(event_info);
00238 
00239    return PAPI_OK;
00240 }
00241 
00242 /*
00243  *
00244  */
00245 int
00246 _stealtime_shutdown_thread( hwd_context_t * ctx )
00247 {
00248 
00249   struct STEALTIME_context *context=(struct STEALTIME_context *)ctx;
00250 
00251   if (context->start_count!=NULL) free(context->start_count);
00252   if (context->current_count!=NULL) free(context->current_count);
00253 
00254   return PAPI_OK;
00255 }
00256 
00257 
00258 
00259 /*
00260  * Control of counters (Reading/Writing/Starting/Stopping/Setup) functions
00261  */
00262 int
00263 _stealtime_init_control_state( hwd_control_state_t *ctl )
00264 {
00265 
00266     struct STEALTIME_control_state *control = 
00267       (struct STEALTIME_control_state *)ctl;
00268 
00269     control->values=NULL;
00270     control->which_counter=NULL;
00271     control->num_events=0;
00272 
00273     return PAPI_OK;
00274 }
00275 
00276 
00277 /*
00278  *
00279  */
00280 int
00281 _stealtime_update_control_state( hwd_control_state_t *ctl, 
00282                   NativeInfo_t *native,
00283                   int count, 
00284                   hwd_context_t *ctx )
00285 {
00286 
00287     struct STEALTIME_control_state *control;
00288 
00289     ( void ) ctx;
00290     int i, index;
00291 
00292     control= (struct STEALTIME_control_state *)ctl;
00293 
00294     if (count!=control->num_events) {
00295       //       printf("Resizing %d to %d\n",control->num_events,count);
00296        control->which_counter=realloc(control->which_counter,
00297                       count*sizeof(int));
00298        control->values=realloc(control->values,
00299                    count*sizeof(long long));
00300        
00301     }
00302 
00303 
00304     for ( i = 0; i < count; i++ ) {
00305        index = native[i].ni_event;
00306        control->which_counter[i]=index;
00307        native[i].ni_position = i;
00308     }
00309 
00310     control->num_events=count;
00311 
00312     return PAPI_OK;
00313 }
00314 
00315 
00316 /*
00317  *
00318  */
00319 int
00320 _stealtime_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
00321 {
00322 
00323   (void)ctl;
00324 
00325   //    struct STEALTIME_control_state *control;
00326     struct STEALTIME_context *context;
00327     
00328     //control = (struct STEALTIME_control_state *)ctl;
00329     context = (struct STEALTIME_context *)ctx;
00330 
00331     read_stealtime( context, 1 );
00332 
00333     /* no need to update control, as we assume only one EventSet  */
00334     /* is active at once, so starting things at the context level */
00335     /* is fine, since stealtime is system-wide                    */
00336 
00337     return PAPI_OK;
00338 }
00339 
00340 
00341 /*
00342  *
00343  */
00344 int
00345 _stealtime_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
00346 {
00347 
00348   (void) ctl;
00349 
00350   //    struct STEALTIME_control_state *control;
00351     struct STEALTIME_context *context;
00352     
00353     //control = (struct STEALTIME_control_state *)ctl;
00354     context = (struct STEALTIME_context *)ctx;
00355 
00356     read_stealtime( context, 0 );
00357 
00358     return PAPI_OK;
00359 
00360 }
00361 
00362 
00363 
00364 /*
00365  *
00366  */
00367 int
00368 _stealtime_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
00369              long long **events, int flags )
00370 {
00371     ( void ) flags;
00372 
00373     struct STEALTIME_control_state *control;
00374     struct STEALTIME_context *context;
00375 
00376     int i;
00377     
00378     control = (struct STEALTIME_control_state *)ctl;
00379     context = (struct STEALTIME_context *)ctx;
00380 
00381     read_stealtime( context, 0 );
00382 
00383     for(i=0;i<control->num_events;i++) {
00384        control->values[i]=
00385                  context->value[control->which_counter[i]];
00386     }
00387 
00388     *events = control->values;
00389 
00390     return PAPI_OK;
00391 
00392 }
00393 
00394 
00395 
00396 
00397 /*
00398  *
00399  */
00400 int
00401 _stealtime_reset( hwd_context_t * ctx, hwd_control_state_t * ctrl )
00402 {
00403 
00404   /* re-initializes counter_start values to current */
00405 
00406   _stealtime_start(ctx,ctrl);
00407 
00408   return PAPI_OK;
00409 }
00410 
00411 
00412 /*
00413  *
00414  */
00415 int
00416 _stealtime_write( hwd_context_t * ctx, hwd_control_state_t * ctrl, long long *from )
00417 {
00418     ( void ) ctx;
00419     ( void ) ctrl;
00420     ( void ) from;
00421 
00422     return PAPI_OK;
00423 }
00424 
00425 
00426 /*
00427  * Functions for setting up various options
00428  */
00429 
00430 /* This function sets various options in the component
00431  * The valid codes being passed in are PAPI_SET_DEFDOM,
00432  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
00433  */
00434 int
00435 _stealtime_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
00436 {
00437     ( void ) ctx;
00438     ( void ) code;
00439     ( void ) option;
00440 
00441     return PAPI_OK;
00442 }
00443 
00444 
00445 /*
00446  * This function has to set the bits needed to count different domains
00447  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
00448  * By default return PAPI_EINVAL if none of those are specified
00449  * and PAPI_OK with success
00450  * PAPI_DOM_USER is only user context is counted
00451  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
00452  * PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
00453  * PAPI_DOM_ALL   is all of the domains
00454  */
00455 int
00456 _stealtime_set_domain( hwd_control_state_t * cntrl, int domain )
00457 {
00458     ( void ) cntrl;
00459     int found = 0;
00460     if ( PAPI_DOM_USER & domain ) {
00461         found = 1;
00462     }
00463     if ( PAPI_DOM_KERNEL & domain ) {
00464         found = 1;
00465     }
00466     if ( PAPI_DOM_OTHER & domain ) {
00467         found = 1;
00468     }
00469     if ( !found )
00470         return PAPI_EINVAL;
00471 
00472     return PAPI_OK;
00473 }
00474 
00475 
00476 /*
00477  *
00478  */
00479 int
00480 _stealtime_ntv_code_to_name( unsigned int EventCode, char *name, int len )
00481 {
00482 
00483   int event=EventCode;
00484 
00485   if (event >=0 && event < num_events) {
00486      strncpy( name, event_info[event].name, len );
00487      return PAPI_OK;
00488   }
00489 
00490   return PAPI_ENOEVNT;
00491 }
00492 
00493 
00494 /*
00495  *
00496  */
00497 int
00498 _stealtime_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
00499 {
00500 
00501   int event=EventCode;
00502 
00503   if (event >=0 && event < num_events) {
00504     strncpy( name, event_info[event].description, len );
00505     return PAPI_OK;
00506   }
00507 
00508   return PAPI_ENOEVNT;
00509 }
00510 
00511 
00512 
00513 int
00514 _stealtime_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
00515 {
00516 
00517   int index = EventCode;
00518 
00519   if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
00520 
00521   strncpy( info->symbol, event_info[index].name,
00522            sizeof(info->symbol));
00523 
00524   strncpy( info->long_descr, event_info[index].description,
00525            sizeof(info->symbol));
00526 
00527   strncpy( info->units, event_info[index].units,
00528            sizeof(info->units));
00529 
00530   return PAPI_OK;
00531 
00532 }
00533 
00534 
00535 
00536 
00537 /*
00538  *
00539  */
00540 int
00541 _stealtime_ntv_enum_events( unsigned int *EventCode, int modifier )
00542 {
00543 
00544      if ( modifier == PAPI_ENUM_FIRST ) {
00545     if (num_events==0) return PAPI_ENOEVNT;
00546     *EventCode = 0;
00547     return PAPI_OK;
00548      }
00549 
00550      if ( modifier == PAPI_ENUM_EVENTS ) {
00551         int index;
00552 
00553         index = *EventCode;
00554 
00555     if ( (index+1) < num_events ) {
00556        *EventCode = *EventCode + 1;
00557        return PAPI_OK;
00558     } else {
00559        return PAPI_ENOEVNT;
00560     }
00561      } 
00562         
00563      return PAPI_EINVAL;
00564 }
00565 
00566 
00567 /*
00568  *
00569  */
00570 papi_vector_t _stealtime_vector = {
00571    .cmp_info = {
00572         /* component information (unspecified values initialized to 0) */
00573        .name = "stealtime",
00574        .short_name="stealtime",
00575        .version = "5.0",
00576        .description = "Stealtime filesystem statistics",
00577        .default_domain = PAPI_DOM_USER,
00578        .default_granularity = PAPI_GRN_THR,
00579        .available_granularities = PAPI_GRN_THR,
00580        .hardware_intr_sig = PAPI_INT_SIGNAL,
00581 
00582        /* component specific cmp_info initializations */
00583        .fast_real_timer = 0,
00584        .fast_virtual_timer = 0,
00585        .attach = 0,
00586        .attach_must_ptrace = 0,
00587        .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
00588   },
00589 
00590      /* sizes of framework-opaque component-private structures */
00591   .size = {
00592        .context = sizeof ( struct STEALTIME_context ),
00593        .control_state = sizeof ( struct STEALTIME_control_state ),
00594        .reg_value = sizeof ( STEALTIME_register_t ),
00595        .reg_alloc = sizeof ( STEALTIME_reg_alloc_t ),
00596   },
00597 
00598      /* function pointers in this component */
00599   .init_thread =           _stealtime_init_thread,
00600   .init_component =        _stealtime_init_component,
00601   .init_control_state =    _stealtime_init_control_state,
00602   .start =                 _stealtime_start,
00603   .stop =                  _stealtime_stop,
00604   .read =                  _stealtime_read,
00605   .shutdown_thread =       _stealtime_shutdown_thread,
00606   .shutdown_component =    _stealtime_shutdown_component,
00607   .ctl =                   _stealtime_ctl,
00608   .update_control_state =  _stealtime_update_control_state,
00609   .set_domain =            _stealtime_set_domain,
00610   .reset =                 _stealtime_reset,
00611 
00612   .ntv_enum_events =   _stealtime_ntv_enum_events,
00613   .ntv_code_to_name =  _stealtime_ntv_code_to_name,
00614   .ntv_code_to_descr = _stealtime_ntv_code_to_descr,
00615   .ntv_code_to_info = _stealtime_ntv_code_to_info,
00616 };
00617 
00618 
00619 
00620 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines