|
PAPI
5.0.1.0
|
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