PAPI  5.7.0.0
linux-stealtime.c
Go to the documentation of this file.
1 
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <dirent.h>
13 #include <stdint.h>
14 #include <ctype.h>
15 
16 #include "papi.h"
17 #include "papi_internal.h"
18 #include "papi_vector.h"
19 #include "papi_memory.h"
20 
21 struct counter_info
22 {
23  char *name;
24  char *description;
25  char *units;
26  unsigned long long value;
27 };
28 
29 typedef struct counter_info STEALTIME_register_t;
30 typedef struct counter_info STEALTIME_native_event_entry_t;
31 typedef struct counter_info STEALTIME_reg_alloc_t;
32 
33 
35 {
36  long long *values;
39 };
40 
41 
43 {
44  long long *start_count;
45  long long *current_count;
46  long long *value;
47 };
48 
49 
50 static int num_events = 0;
51 
52 static struct counter_info *event_info=NULL;
53 
54 /* Advance declaration of buffer */
56 
57 /******************************************************************************
58  ******** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ********
59  *****************************************************************************/
60 
61 struct statinfo {
62  long long user;
63  long long nice;
64  long long system;
65  long long idle;
66  long long iowait;
67  long long irq;
68  long long softirq;
69  long long steal;
70  long long guest;
71 };
72 
73 static int
74 read_stealtime( struct STEALTIME_context *context, int starting) {
75 
76  FILE *fff;
77  char buffer[BUFSIZ],*result;
78  int i,count;
79  struct statinfo our_stat;
80 
81  int hz=sysconf(_SC_CLK_TCK);
82 
83 
84  fff=fopen("/proc/stat","r");
85  if (fff==NULL) {
86  return PAPI_ESYS;
87  }
88 
89  for(i=0;i<num_events;i++) {
90  result=fgets(buffer,BUFSIZ,fff);
91  if (result==NULL) break;
92 
93  count=sscanf(buffer,"%*s %lld %lld %lld %lld %lld %lld %lld %lld %lld",
94  &our_stat.user,
95  &our_stat.nice,
96  &our_stat.system,
97  &our_stat.idle,
98  &our_stat.iowait,
99  &our_stat.irq,
100  &our_stat.softirq,
101  &our_stat.steal,
102  &our_stat.guest);
103  if (count<=7) {
104  fclose(fff);
105  return PAPI_ESYS;
106  }
107 
108  if (starting) {
109  context->start_count[i]=our_stat.steal;
110  }
111  context->current_count[i]=our_stat.steal;
112 
113  /* convert to us */
114  context->value[i]=(context->current_count[i]-context->start_count[i])*
115  (1000000/hz);
116  }
117 
118 
119  fclose(fff);
120 
121  return PAPI_OK;
122 
123 }
124 
125 
126 
127 /*****************************************************************************
128  ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *************
129  *****************************************************************************/
130 
131 /*
132  * Component setup and shutdown
133  */
134 static int _stealtime_shutdown_component( void ); // prototype for later routine.
135 
136 static int
138 {
139 
140  (void)cidx;
141 
142  FILE *fff;
143  char buffer[BUFSIZ],*result,string[BUFSIZ];
144  int i;
145 
146  /* Make sure /proc/stat exists */
147  fff=fopen("/proc/stat","r");
148  if (fff==NULL) {
150  "Cannot open /proc/stat",PAPI_MAX_STR_LEN);
152  return PAPI_ESYS;
153  }
154 
155  num_events=0;
156  while(1) {
157  result=fgets(buffer,BUFSIZ,fff);
158  if (result==NULL) break;
159 
160  /* /proc/stat line with cpu stats always starts with "cpu" */
161 
162  if (!strncmp(buffer,"cpu",3)) {
163  num_events++;
164  }
165  else {
166  break;
167  }
168 
169  }
170 
171  fclose(fff);
172 
173  if (num_events<1) {
175  "Cannot find enough CPU lines in /proc/stat",
178  return PAPI_ESYS;
179  }
180 
181  event_info=calloc(num_events,sizeof(struct counter_info));
182  if (event_info==NULL) {
184  return PAPI_ENOMEM;
185  }
186 
187 
188  sysconf(_SC_CLK_TCK);
189  event_info[0].name=strdup("TOTAL");
190  event_info[0].description=strdup("Total amount of steal time");
191  event_info[0].units=strdup("us");
192 
193  for(i=1;i<num_events;i++) {
194  sprintf(string,"CPU%d",i);
195  event_info[i].name=strdup(string);
196  sprintf(string,"Steal time for CPU %d",i);
197  event_info[i].description=strdup(string);
198  event_info[i].units=strdup("us");
199  }
200 
201  // printf("Found %d CPUs\n",num_events-1);
202 
206 
207  return PAPI_OK;
208 }
209 
210 
211 
212 
213 
214 /*
215  * This is called whenever a thread is initialized
216  */
217 static int
219 {
220  struct STEALTIME_context *context=(struct STEALTIME_context *)ctx;
221 
222  context->start_count=calloc(num_events,sizeof(long long));
223  if (context->start_count==NULL) return PAPI_ENOMEM;
224 
225  context->current_count=calloc(num_events,sizeof(long long));
226  if (context->current_count==NULL) return PAPI_ENOMEM;
227 
228  context->value=calloc(num_events,sizeof(long long));
229  if (context->value==NULL) return PAPI_ENOMEM;
230 
231  return PAPI_OK;
232 }
233 
234 
235 /*
236  *
237  */
238 static int
240 {
241  int i;
243  if (event_info!=NULL) {
244  for (i=0; i<num_events; i++){
245  free(event_info[i].name);
246  free(event_info[i].description);
247  free(event_info[i].units);
248  }
249  free(event_info);
250  }
251 
252  return PAPI_OK;
253 }
254 
255 /*
256  *
257  */
258 static int
260 {
261 
262  struct STEALTIME_context *context=(struct STEALTIME_context *)ctx;
263 
264  if (context->start_count!=NULL) free(context->start_count);
265  if (context->current_count!=NULL) free(context->current_count);
266  if (context->value!=NULL) free(context->value);
267 
268  return PAPI_OK;
269 }
270 
271 
272 
273 /*
274  * Control of counters (Reading/Writing/Starting/Stopping/Setup) functions
275  */
276 static int
278 {
279 
280  struct STEALTIME_control_state *control =
281  (struct STEALTIME_control_state *)ctl;
282 
283  control->values=NULL;
284  control->which_counter=NULL;
285  control->num_events=0;
286 
287  return PAPI_OK;
288 }
289 
290 
291 /*
292  *
293  */
294 static int
297  int count,
298  hwd_context_t *ctx )
299 {
300 
301  struct STEALTIME_control_state *control;
302 
303  ( void ) ctx;
304  int i, index;
305 
306  control= (struct STEALTIME_control_state *)ctl;
307 
308  if (count!=control->num_events) {
309  // printf("Resizing %d to %d\n",control->num_events,count);
310  control->which_counter=realloc(control->which_counter,
311  count*sizeof(int));
312  control->values=realloc(control->values,
313  count*sizeof(long long));
314 
315  }
316 
317 
318  for ( i = 0; i < count; i++ ) {
319  index = native[i].ni_event;
320  control->which_counter[i]=index;
321  native[i].ni_position = i;
322  }
323 
324  control->num_events=count;
325 
326  return PAPI_OK;
327 }
328 
329 
330 /*
331  *
332  */
333 static int
335 {
336 
337  (void)ctl;
338 
339  // struct STEALTIME_control_state *control;
340  struct STEALTIME_context *context;
341 
342  //control = (struct STEALTIME_control_state *)ctl;
343  context = (struct STEALTIME_context *)ctx;
344 
345  read_stealtime( context, 1 );
346 
347  /* no need to update control, as we assume only one EventSet */
348  /* is active at once, so starting things at the context level */
349  /* is fine, since stealtime is system-wide */
350 
351  return PAPI_OK;
352 }
353 
354 
355 /*
356  *
357  */
358 static int
360 {
361 
362  (void) ctl;
363 
364  // struct STEALTIME_control_state *control;
365  struct STEALTIME_context *context;
366 
367  //control = (struct STEALTIME_control_state *)ctl;
368  context = (struct STEALTIME_context *)ctx;
369 
370  read_stealtime( context, 0 );
371 
372  return PAPI_OK;
373 
374 }
375 
376 
377 
378 /*
379  *
380  */
381 static int
383  long long **events, int flags )
384 {
385  ( void ) flags;
386 
387  struct STEALTIME_control_state *control;
388  struct STEALTIME_context *context;
389 
390  int i;
391 
392  control = (struct STEALTIME_control_state *)ctl;
393  context = (struct STEALTIME_context *)ctx;
394 
395  read_stealtime( context, 0 );
396 
397  for(i=0;i<control->num_events;i++) {
398  control->values[i]=
399  context->value[control->which_counter[i]];
400  }
401 
402  *events = control->values;
403 
404  return PAPI_OK;
405 
406 }
407 
408 
409 
410 
411 /*
412  *
413  */
414 static int
416 {
417 
418  /* re-initializes counter_start values to current */
419 
420  _stealtime_start(ctx,ctrl);
421 
422  return PAPI_OK;
423 }
424 
425 
426 /*
427  * Unused stealtime write function
428  */
429 /* static int */
430 /* _stealtime_write( hwd_context_t * ctx, hwd_control_state_t * ctrl, long long *from ) */
431 /* { */
432 /* ( void ) ctx; */
433 /* ( void ) ctrl; */
434 /* ( void ) from; */
435 
436 /* return PAPI_OK; */
437 /* } */
438 
439 
440 /*
441  * Functions for setting up various options
442  */
443 
444 /* This function sets various options in the component
445  * The valid codes being passed in are PAPI_SET_DEFDOM,
446  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
447  */
448 static int
449 _stealtime_ctl( hwd_context_t * ctx, int code, _papi_int_option_t * option )
450 {
451  ( void ) ctx;
452  ( void ) code;
453  ( void ) option;
454 
455  return PAPI_OK;
456 }
457 
458 
459 /*
460  * This function has to set the bits needed to count different domains
461  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
462  * By default return PAPI_EINVAL if none of those are specified
463  * and PAPI_OK with success
464  * PAPI_DOM_USER is only user context is counted
465  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
466  * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
467  * PAPI_DOM_ALL is all of the domains
468  */
469 static int
471 {
472  ( void ) cntrl;
473  int found = 0;
474  if ( PAPI_DOM_USER & domain ) {
475  found = 1;
476  }
477  if ( PAPI_DOM_KERNEL & domain ) {
478  found = 1;
479  }
480  if ( PAPI_DOM_OTHER & domain ) {
481  found = 1;
482  }
483  if ( !found )
484  return PAPI_EINVAL;
485 
486  return PAPI_OK;
487 }
488 
489 
490 /*
491  *
492  */
493 static int
494 _stealtime_ntv_code_to_name( unsigned int EventCode, char *name, int len )
495 {
496 
497  int event=EventCode;
498 
499  if (event >=0 && event < num_events) {
500  strncpy( name, event_info[event].name, len );
501  return PAPI_OK;
502  }
503 
504  return PAPI_ENOEVNT;
505 }
506 
507 
508 /*
509  *
510  */
511 static int
512 _stealtime_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
513 {
514 
515  int event=EventCode;
516 
517  if (event >=0 && event < num_events) {
518  strncpy( name, event_info[event].description, len );
519  return PAPI_OK;
520  }
521 
522  return PAPI_ENOEVNT;
523 }
524 
525 
526 
527 static int
528 _stealtime_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
529 {
530 
531  int index = EventCode;
532 
533  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
534 
535  strncpy( info->symbol, event_info[index].name,sizeof(info->symbol));
536  info->symbol[sizeof(info->symbol)-1] = '\0';
537 
538  strncpy( info->long_descr, event_info[index].description,sizeof(info->symbol));
539  info->long_descr[sizeof(info->symbol)-1] = '\0';
540 
541  strncpy( info->units, event_info[index].units,sizeof(info->units));
542  info->units[sizeof(info->units)-1] = '\0';
543 
544  return PAPI_OK;
545 
546 }
547 
548 
549 
550 
551 /*
552  *
553  */
554 static int
555 _stealtime_ntv_enum_events( unsigned int *EventCode, int modifier )
556 {
557 
558  if ( modifier == PAPI_ENUM_FIRST ) {
559  if (num_events==0) return PAPI_ENOEVNT;
560  *EventCode = 0;
561  return PAPI_OK;
562  }
563 
564  if ( modifier == PAPI_ENUM_EVENTS ) {
565  int index;
566 
567  index = *EventCode;
568 
569  if ( (index+1) < num_events ) {
570  *EventCode = *EventCode + 1;
571  return PAPI_OK;
572  } else {
573  return PAPI_ENOEVNT;
574  }
575  }
576 
577  return PAPI_EINVAL;
578 }
579 
580 
581 /*
582  *
583  */
585  .cmp_info = {
586  /* component information (unspecified values initialized to 0) */
587  .name = "stealtime",
588  .short_name="stealtime",
589  .version = "5.0",
590  .description = "Stealtime filesystem statistics",
591  .default_domain = PAPI_DOM_USER,
592  .default_granularity = PAPI_GRN_THR,
593  .available_granularities = PAPI_GRN_THR,
594  .hardware_intr_sig = PAPI_INT_SIGNAL,
595 
596  /* component specific cmp_info initializations */
597  .fast_real_timer = 0,
598  .fast_virtual_timer = 0,
599  .attach = 0,
600  .attach_must_ptrace = 0,
601  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
602  },
603 
604  /* sizes of framework-opaque component-private structures */
605  .size = {
606  .context = sizeof ( struct STEALTIME_context ),
607  .control_state = sizeof ( struct STEALTIME_control_state ),
608  .reg_value = sizeof ( STEALTIME_register_t ),
609  .reg_alloc = sizeof ( STEALTIME_reg_alloc_t ),
610  },
611 
612  /* function pointers in this component */
613  .init_thread = _stealtime_init_thread,
614  .init_component = _stealtime_init_component,
615  .init_control_state = _stealtime_init_control_state,
616  .start = _stealtime_start,
617  .stop = _stealtime_stop,
618  .read = _stealtime_read,
619  .shutdown_thread = _stealtime_shutdown_thread,
620  .shutdown_component = _stealtime_shutdown_component,
621  .ctl = _stealtime_ctl,
622  .update_control_state = _stealtime_update_control_state,
623  .set_domain = _stealtime_set_domain,
624  .reset = _stealtime_reset,
625 
626  .ntv_enum_events = _stealtime_ntv_enum_events,
627  .ntv_code_to_name = _stealtime_ntv_code_to_name,
628  .ntv_code_to_descr = _stealtime_ntv_code_to_descr,
629  .ntv_code_to_info = _stealtime_ntv_code_to_info,
630 };
631 
632 
633 
634 
#define PAPI_OK
Definition: fpapi.h:105
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:637
static int _stealtime_shutdown_component(void)
long long nice
#define PAPI_ENOMEM
Definition: fpapi.h:107
static const char * name
Definition: fork_overflow.c:31
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
#define PAPI_EINVAL
Definition: fpapi.h:106
#define PAPI_GRN_THR
Definition: fpapi.h:67
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:976
long long guest
static int _stealtime_reset(hwd_context_t *ctx, hwd_control_state_t *ctrl)
static int _stealtime_shutdown_thread(hwd_context_t *ctx)
static int _stealtime_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
long long system
static int read_stealtime(struct STEALTIME_context *context, int starting)
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
static int _stealtime_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
long long idle
static int _stealtime_ntv_enum_events(unsigned int *EventCode, int modifier)
Return codes and api definitions.
FILE * fff[MAX_EVENTS]
#define PAPI_DOM_OTHER
Definition: fpapi.h:23
char events[MAX_EVENTS][BUFSIZ]
#define PAPI_ESYS
Definition: fpapi.h:108
static struct counter_info * event_info
static int cidx
long long irq
long long softirq
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
#define PAPI_DOM_USER
Definition: fpapi.h:21
static int native
long long * current_count
static int _stealtime_init_thread(hwd_context_t *ctx)
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:630
static int num_events
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static int _stealtime_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
static int _stealtime_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
char * buffer
Definition: iozone.c:1366
static int _stealtime_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
static int _stealtime_set_domain(hwd_control_state_t *cntrl, int domain)
long long iowait
long long user
#define PAPI_ENOEVNT
Definition: fpapi.h:112
papi_vector_t _stealtime_vector
static int _stealtime_init_control_state(hwd_control_state_t *ctl)
static int _stealtime_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
static int _stealtime_init_component(int cidx)
static int _stealtime_ntv_code_to_name(unsigned int EventCode, char *name, int len)
long long * start_count
static long count
int i
Definition: fileop.c:140
static int _stealtime_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
long long steal