PAPI  5.3.2.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
example.c
Go to the documentation of this file.
1 
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <inttypes.h>
19 
20 /* Headers required by PAPI */
21 #include "papi.h"
22 #include "papi_internal.h"
23 #include "papi_vector.h"
24 #include "papi_memory.h" /* defines papi_malloc(), etc. */
25 
27 /* This is artificially low to allow testing of multiplexing */
28 #define EXAMPLE_MAX_SIMULTANEOUS_COUNTERS 3
29 #define EXAMPLE_MAX_MULTIPLEX_COUNTERS 4
30 
31 /* Declare our vector in advance */
32 /* This allows us to modify the component info */
34 
36 typedef struct example_register
37 {
38  unsigned int selector;
42 
44 /* The contents of this structure will vary based on */
45 /* your component, however having name and description */
46 /* fields are probably useful. */
47 typedef struct example_native_event_entry
48 {
51  char description[PAPI_MAX_STR_LEN];
52  int writable;
53  /* any other counter parameters go here */
55 
59 typedef struct example_reg_alloc
60 {
63 
69 typedef struct example_control_state
70 {
72  int domain;
74  int overflow;
75  int inherit;
76  int which_counter[EXAMPLE_MAX_SIMULTANEOUS_COUNTERS];
77  long long counter[EXAMPLE_MAX_MULTIPLEX_COUNTERS];
79 
81 typedef struct example_context
82 {
83  long long autoinc_value;
85 
88 
90 static int num_events = 0;
91 
92 
93 /*************************************************************************/
94 /* Below is the actual "hardware implementation" of our example counters */
95 /*************************************************************************/
96 
97 #define EXAMPLE_ZERO_REG 0
98 #define EXAMPLE_CONSTANT_REG 1
99 #define EXAMPLE_AUTOINC_REG 2
100 #define EXAMPLE_GLOBAL_AUTOINC_REG 3
101 
102 #define EXAMPLE_TOTAL_EVENTS 4
103 
104 static long long example_global_autoinc_value = 0;
105 
107 static void
109 {
110  /* reset per-thread count */
111  ctx->autoinc_value=0;
112  /* reset global count */
114 
115 }
116 
118 /* You might replace this with code that accesses */
119 /* hardware or reads values from the operatings system. */
120 static long long
122 {
123  long long old_value;
124 
125  switch ( which_one ) {
126  case EXAMPLE_ZERO_REG:
127  return 0;
129  return 42;
130  case EXAMPLE_AUTOINC_REG:
131  old_value = ctx->autoinc_value;
132  ctx->autoinc_value++;
133  return old_value;
135  old_value = example_global_autoinc_value;
137  return old_value;
138  default:
139  fprintf(stderr,"Invalid counter read %#x\n",which_one );
140  return -1;
141  }
142 
143  return 0;
144 }
145 
147 static int
148 example_hardware_write( int which_one,
149  example_context_t *ctx,
150  long long value)
151 {
152 
153  switch ( which_one ) {
154  case EXAMPLE_ZERO_REG:
156  return PAPI_OK; /* can't be written */
157  case EXAMPLE_AUTOINC_REG:
158  ctx->autoinc_value=value;
159  return PAPI_OK;
162  return PAPI_OK;
163  default:
164  perror( "Invalid counter write" );
165  return -1;
166  }
167 
168  return 0;
169 }
170 
171 static int
173 
174  return PAPI_OK;
175 }
176 
177 /********************************************************************/
178 /* Below are the functions required by the PAPI component interface */
179 /********************************************************************/
180 
181 
186 int
188 {
189 
190  SUBDBG( "_example_init_component..." );
191 
192 
193  /* First, detect that our hardware is available */
194  if (detect_example()!=PAPI_OK) {
195  return PAPI_ECMP;
196  }
197 
198  /* we know in advance how many events we want */
199  /* for actual hardware this might have to be determined dynamically */
201 
202  /* Allocate memory for the our native event table */
203  example_native_table =
206  if ( example_native_table == NULL ) {
207  PAPIERROR( "malloc():Could not get memory for events table" );
208  return PAPI_ENOMEM;
209  }
210 
211  /* fill in the event table parameters */
212  /* for complicated components this will be done dynamically */
213  /* or by using an external library */
214 
215  strcpy( example_native_table[0].name, "EXAMPLE_ZERO" );
216  strcpy( example_native_table[0].description,
217  "This is an example counter, that always returns 0" );
218  example_native_table[0].writable = 0;
219 
220  strcpy( example_native_table[1].name, "EXAMPLE_CONSTANT" );
221  strcpy( example_native_table[1].description,
222  "This is an example counter, that always returns a constant value of 42" );
223  example_native_table[1].writable = 0;
224 
225  strcpy( example_native_table[2].name, "EXAMPLE_AUTOINC" );
226  strcpy( example_native_table[2].description,
227  "This is an example counter, that reports a per-thread auto-incrementing value" );
228  example_native_table[2].writable = 1;
229 
230  strcpy( example_native_table[3].name, "EXAMPLE_GLOBAL_AUTOINC" );
231  strcpy( example_native_table[3].description,
232  "This is an example counter, that reports a global auto-incrementing value" );
233  example_native_table[3].writable = 1;
234 
235  /* Export the total number of events available */
236  _example_vector.cmp_info.num_native_events = num_events;
237 
238  /* Export the component id */
239  _example_vector.cmp_info.CmpIdx = cidx;
240 
241 
242 
243  return PAPI_OK;
244 }
245 
247 int
249 {
250 
251  example_context_t *example_context = (example_context_t *)ctx;
252 
253  example_context->autoinc_value=0;
254 
255  SUBDBG( "_example_init_thread %p...", ctx );
256 
257  return PAPI_OK;
258 }
259 
260 
261 
267 int
269 {
270  SUBDBG( "example_init_control_state... %p\n", ctl );
271 
272  example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
273  memset( example_ctl, 0, sizeof ( example_control_state_t ) );
274 
275  return PAPI_OK;
276 }
277 
278 
280 int
283  int count,
284  hwd_context_t *ctx )
285 {
286 
287  (void) ctx;
288  int i, index;
289 
290  example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
291 
292  SUBDBG( "_example_update_control_state %p %p...", ctl, ctx );
293 
294  /* if no events, return */
295  if (count==0) return PAPI_OK;
296 
297  for( i = 0; i < count; i++ ) {
298  index = native[i].ni_event;
299 
300  /* Map counter #i to Measure Event "index" */
301  example_ctl->which_counter[i]=index;
302 
303  /* We have no constraints on event position, so any event */
304  /* can be in any slot. */
305  native[i].ni_position = i;
306  }
307 
308  example_ctl->num_events=count;
309 
310  return PAPI_OK;
311 }
312 
314 int
316 {
317 
318  (void) ctx;
319  (void) ctl;
320 
321  SUBDBG( "example_start %p %p...", ctx, ctl );
322 
323  /* anything that would need to be set at counter start time */
324 
325  /* reset counters? */
326  /* For hardware that cannot reset counters, store initial */
327  /* counter state to the ctl and subtract it off at read time */
328 
329  /* start the counting ?*/
330 
331  return PAPI_OK;
332 }
333 
334 
336 int
338 {
339 
340  (void) ctx;
341  (void) ctl;
342 
343  SUBDBG( "example_stop %p %p...", ctx, ctl );
344 
345  /* anything that would need to be done at counter stop time */
346 
347 
348 
349  return PAPI_OK;
350 }
351 
352 
354 /* flags field is never set? */
355 int
357  long long **events, int flags )
358 {
359 
360  (void) flags;
361 
362  example_context_t *example_ctx = (example_context_t *) ctx;
363  example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
364 
365  SUBDBG( "example_read... %p %d", ctx, flags );
366 
367  int i;
368 
369  /* Read counters into expected slot */
370  for(i=0;i<example_ctl->num_events;i++) {
371  example_ctl->counter[i] =
372  example_hardware_read( example_ctl->which_counter[i],
373  example_ctx );
374  }
375 
376  /* return pointer to the values we read */
377  *events = example_ctl->counter;
378 
379  return PAPI_OK;
380 }
381 
383 /* otherwise, the updated state is written to ESI->hw_start */
384 int
386  long long *events )
387 {
388 
389  example_context_t *example_ctx = (example_context_t *) ctx;
390  example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
391 
392  int i;
393 
394  SUBDBG( "example_write... %p %p", ctx, ctl );
395 
396  /* Write counters into expected slot */
397  for(i=0;i<example_ctl->num_events;i++) {
398  example_hardware_write( example_ctl->which_counter[i],
399  example_ctx,
400  events[i] );
401  }
402 
403  return PAPI_OK;
404 }
405 
406 
408 /* If the eventset is not currently running, then the saved value in the */
409 /* EventSet is set to zero without calling this routine. */
410 int
412 {
413  example_context_t *event_ctx = (example_context_t *)ctx;
414  (void) ctl;
415 
416  SUBDBG( "example_reset ctx=%p ctrl=%p...", ctx, ctl );
417 
418  /* Reset the hardware */
419  example_hardware_reset( event_ctx );
420 
421  return PAPI_OK;
422 }
423 
425 int
427 {
428 
429  SUBDBG( "example_shutdown_component..." );
430 
431  /* Free anything we allocated */
432 
433  papi_free(example_native_table);
434 
435  return PAPI_OK;
436 }
437 
439 int
441 {
442 
443  (void) ctx;
444 
445  SUBDBG( "example_shutdown_thread... %p", ctx );
446 
447  /* Last chance to clean up thread */
448 
449  return PAPI_OK;
450 }
451 
452 
453 
460 int
462 {
463 
464  (void) ctx;
465  (void) code;
466  (void) option;
467 
468  SUBDBG( "example_ctl..." );
469 
470  return PAPI_OK;
471 }
472 
482 int
484 {
485  (void) cntrl;
486 
487  int found = 0;
488  SUBDBG( "example_set_domain..." );
489 
490  if ( PAPI_DOM_USER & domain ) {
491  SUBDBG( " PAPI_DOM_USER " );
492  found = 1;
493  }
494  if ( PAPI_DOM_KERNEL & domain ) {
495  SUBDBG( " PAPI_DOM_KERNEL " );
496  found = 1;
497  }
498  if ( PAPI_DOM_OTHER & domain ) {
499  SUBDBG( " PAPI_DOM_OTHER " );
500  found = 1;
501  }
502  if ( PAPI_DOM_ALL & domain ) {
503  SUBDBG( " PAPI_DOM_ALL " );
504  found = 1;
505  }
506  if ( !found )
507  return ( PAPI_EINVAL );
508 
509  return PAPI_OK;
510 }
511 
512 
513 /**************************************************************/
514 /* Naming functions, used to translate event numbers to names */
515 /**************************************************************/
516 
517 
524 int
525 _example_ntv_enum_events( unsigned int *EventCode, int modifier )
526 {
527  int index;
528 
529 
530  switch ( modifier ) {
531 
532  /* return EventCode of first event */
533  case PAPI_ENUM_FIRST:
534  /* return the first event that we support */
535 
536  *EventCode = 0;
537  return PAPI_OK;
538 
539  /* return EventCode of next available event */
540  case PAPI_ENUM_EVENTS:
541  index = *EventCode;
542 
543  /* Make sure we have at least 1 more event after us */
544  if ( index < num_events - 1 ) {
545 
546  /* This assumes a non-sparse mapping of the events */
547  *EventCode = *EventCode + 1;
548  return PAPI_OK;
549  } else {
550  return PAPI_ENOEVNT;
551  }
552  break;
553 
554  default:
555  return PAPI_EINVAL;
556  }
557 
558  return PAPI_EINVAL;
559 }
560 
566 int
567 _example_ntv_code_to_name( unsigned int EventCode, char *name, int len )
568 {
569  int index;
570 
571  index = EventCode;
572 
573  /* Make sure we are in range */
574  if (index >= 0 && index < num_events) {
575  strncpy( name, example_native_table[index].name, len );
576  return PAPI_OK;
577  }
578 
579  return PAPI_ENOEVNT;
580 }
581 
587 int
588 _example_ntv_code_to_descr( unsigned int EventCode, char *descr, int len )
589 {
590  int index;
591  index = EventCode;
592 
593  /* make sure event is in range */
594  if (index >= 0 && index < num_events) {
595  strncpy( descr, example_native_table[index].description, len );
596  return PAPI_OK;
597  }
598 
599  return PAPI_ENOEVNT;
600 }
601 
603 papi_vector_t _example_vector = {
604  .cmp_info = {
605  /* default component information */
606  /* (unspecified values are initialized to 0) */
607  /* we explicitly set them to zero in this example */
608  /* to show what settings are available */
609 
610  .name = "example",
611  .short_name = "example",
612  .description = "A simple example component",
613  .version = "1.15",
614  .support_version = "n/a",
615  .kernel_version = "n/a",
616  .num_cntrs = EXAMPLE_MAX_SIMULTANEOUS_COUNTERS,
617  .num_mpx_cntrs = EXAMPLE_MAX_SIMULTANEOUS_COUNTERS,
618  .default_domain = PAPI_DOM_USER,
619  .available_domains = PAPI_DOM_USER,
620  .default_granularity = PAPI_GRN_THR,
621  .available_granularities = PAPI_GRN_THR,
622  .hardware_intr_sig = PAPI_INT_SIGNAL,
623 
624  /* component specific cmp_info initializations */
625  },
626 
627  /* sizes of framework-opaque component-private structures */
628  .size = {
629  /* once per thread */
630  .context = sizeof ( example_context_t ),
631  /* once per eventset */
632  .control_state = sizeof ( example_control_state_t ),
633  /* ?? */
634  .reg_value = sizeof ( example_register_t ),
635  /* ?? */
636  .reg_alloc = sizeof ( example_reg_alloc_t ),
637  },
638 
639  /* function pointers */
640  /* by default they are set to NULL */
641 
642  /* Used for general PAPI interactions */
643  .start = _example_start,
644  .stop = _example_stop,
645  .read = _example_read,
646  .reset = _example_reset,
647  .write = _example_write,
648  .init_component = _example_init_component,
649  .init_thread = _example_init_thread,
650  .init_control_state = _example_init_control_state,
651  .update_control_state = _example_update_control_state,
652  .ctl = _example_ctl,
653  .shutdown_thread = _example_shutdown_thread,
654  .shutdown_component = _example_shutdown_component,
655  .set_domain = _example_set_domain,
656  /* .cleanup_eventset = NULL, */
657  /* called in add_native_events() */
658  /* .allocate_registers = NULL, */
659 
660  /* Used for overflow/profiling */
661  /* .dispatch_timer = NULL, */
662  /* .get_overflow_address = NULL, */
663  /* .stop_profiling = NULL, */
664  /* .set_overflow = NULL, */
665  /* .set_profile = NULL, */
666 
667  /* ??? */
668  /* .user = NULL, */
669 
670  /* Name Mapping Functions */
671  .ntv_enum_events = _example_ntv_enum_events,
672  .ntv_code_to_name = _example_ntv_code_to_name,
673  .ntv_code_to_descr = _example_ntv_code_to_descr,
674  /* if .ntv_name_to_code not available, PAPI emulates */
675  /* it by enumerating all events and looking manually */
676  .ntv_name_to_code = NULL,
677 
678 
679  /* These are only used by _papi_hwi_get_native_event_info() */
680  /* Which currently only uses the info for printing native */
681  /* event info, not for any sort of internal use. */
682  /* .ntv_code_to_bits = NULL, */
683 
684 };
685 
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:625
memset(eventId, 0, size)
#define PAPI_ENOMEM
Definition: fpapi.h:107
static long long example_global_autoinc_value
Definition: example.c:104
long long flags
Definition: iozone.c:12330
static int detect_example(void)
Definition: example.c:172
#define papi_free(a)
Definition: papi_memory.h:35
int _example_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:315
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
#define PAPI_DOM_ALL
Definition: fpapi.h:25
#define PAPI_ENOEVNT
Definition: fpapi.h:112
static int num_events
example_register_t ra_bits
Definition: example.c:61
int _example_shutdown_component(void)
Definition: example.c:426
return PAPI_OK
Definition: linux-nvml.c:458
int count
Definition: iozone.c:22422
#define PAPI_DOM_OTHER
Definition: fpapi.h:23
Definition: example.c:47
int writable
Definition: example.c:52
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
int _example_init_component(int cidx)
Definition: example.c:187
void
Definition: iozone.c:18627
return PAPI_EINVAL
Definition: linux-nvml.c:408
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
papi_vector_t _example_vector
Definition: example.c:33
void double value
Definition: iozone.c:18781
int which_counter[EXAMPLE_MAX_SIMULTANEOUS_COUNTERS]
Definition: example.c:76
static int example_hardware_write(int which_one, example_context_t *ctx, long long value)
Definition: example.c:148
Return codes and api definitions.
static long long example_hardware_read(int which_one, example_context_t *ctx)
Definition: example.c:121
example_register_t resources
Definition: example.c:49
int _example_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: example.c:356
int _example_ntv_code_to_descr(unsigned int EventCode, char *descr, int len)
Definition: example.c:588
int i
Definition: fileop.c:140
#define EXAMPLE_TOTAL_EVENTS
Definition: example.c:102
int _example_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:411
long long counter[EXAMPLE_MAX_MULTIPLEX_COUNTERS]
Definition: example.c:77
long long found
Definition: libasync.c:735
#define EXAMPLE_MAX_SIMULTANEOUS_COUNTERS
Definition: example.c:28
static int cidx
Definition: event_info.c:40
#define PAPI_ECMP
Definition: fpapi.h:109
int _example_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *events)
Definition: example.c:385
static int native
Definition: event_info.c:39
int _example_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:337
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
#define EXAMPLE_GLOBAL_AUTOINC_REG
Definition: example.c:100
void PAPIERROR(char *format,...)
char events[MAX_EVENTS][BUFSIZ]
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static example_native_event_entry_t * example_native_table
Definition: example.c:87
int _example_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: example.c:281
strcpy(filename, default_filename)
int _example_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: example.c:461
static void example_hardware_reset(example_context_t *ctx)
Definition: example.c:108
unsigned int selector
Definition: example.c:38
int _example_init_control_state(hwd_control_state_t *ctl)
Definition: example.c:268
#define EXAMPLE_AUTOINC_REG
Definition: example.c:99
#define EXAMPLE_MAX_MULTIPLEX_COUNTERS
Definition: example.c:29
char * name
Definition: iozone.c:23648
int _example_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: example.c:525
int _example_init_thread(hwd_context_t *ctx)
Definition: example.c:248
int _example_shutdown_thread(hwd_context_t *ctx)
Definition: example.c:440
int _example_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: example.c:567
long long autoinc_value
Definition: example.c:83
#define EXAMPLE_ZERO_REG
Definition: example.c:97
int _example_set_domain(hwd_control_state_t *cntrl, int domain)
Definition: example.c:483
#define EXAMPLE_CONSTANT_REG
Definition: example.c:98
#define PAPI_DOM_USER
Definition: fpapi.h:21
#define PAPI_GRN_THR
Definition: fpapi.h:67
#define papi_calloc(a, b)
Definition: papi_memory.h:37