PAPI 7.1.0.0
Loading...
Searching...
No Matches
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// The following macro follows if a string function has an error. It should
32// never happen; but it is necessary to prevent compiler warnings. We print
33// something just in case there is programmer error in invoking the function.
34#define HANDLE_STRING_ERROR {fprintf(stderr,"%s:%i unexpected string function error.\n",__FILE__,__LINE__); exit(-1);}
35
36/* Declare our vector in advance */
37/* This allows us to modify the component info */
39
41typedef struct example_register
42{
43 unsigned int selector;
47
49/* The contents of this structure will vary based on */
50/* your component, however having name and description */
51/* fields are probably useful. */
52typedef struct example_native_event_entry
53{
56 char description[PAPI_MAX_STR_LEN];
58 /* any other counter parameters go here */
60
64typedef struct example_reg_alloc
65{
68
74typedef struct example_control_state
75{
77 int domain;
82 long long counter[EXAMPLE_MAX_MULTIPLEX_COUNTERS];
84
86typedef struct example_context
87{
88 long long autoinc_value;
90
93
95static int num_events = 0;
96
97
98/*************************************************************************/
99/* Below is the actual "hardware implementation" of our example counters */
100/*************************************************************************/
101
102#define EXAMPLE_ZERO_REG 0
103#define EXAMPLE_CONSTANT_REG 1
104#define EXAMPLE_AUTOINC_REG 2
105#define EXAMPLE_GLOBAL_AUTOINC_REG 3
106
107#define EXAMPLE_TOTAL_EVENTS 4
108
109static long long example_global_autoinc_value = 0;
110
112static void
114{
115 /* reset per-thread count */
116 ctx->autoinc_value=0;
117 /* reset global count */
119
120}
121
123/* You might replace this with code that accesses */
124/* hardware or reads values from the operatings system. */
125static long long
127{
128 long long old_value;
129
130 switch ( which_one ) {
131 case EXAMPLE_ZERO_REG:
132 return 0;
134 return 42;
136 old_value = ctx->autoinc_value;
137 ctx->autoinc_value++;
138 return old_value;
142 return old_value;
143 default:
144 fprintf(stderr,"Invalid counter read %#x\n",which_one );
145 return -1;
146 }
147
148 return 0;
149}
150
152static int
155 long long value)
156{
157
158 switch ( which_one ) {
159 case EXAMPLE_ZERO_REG:
161 return PAPI_OK; /* can't be written */
163 ctx->autoinc_value=value;
164 return PAPI_OK;
167 return PAPI_OK;
168 default:
169 perror( "Invalid counter write" );
170 return -1;
171 }
172
173 return 0;
174}
175
176static int
178
179 return PAPI_OK;
180}
181
182/********************************************************************/
183/* Below are the functions required by the PAPI component interface */
184/********************************************************************/
185
186
191static int
193{
194 int retval = PAPI_OK;
195
196 SUBDBG( "_example_init_component..." );
197
198 /* First, detect that our hardware is available */
199 if (detect_example()!=PAPI_OK) {
201 "Example Hardware not present.");
202 _example_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
205 goto fn_fail;
206 }
207
208 /* we know in advance how many events we want */
209 /* for actual hardware this might have to be determined dynamically */
211
212 /* Allocate memory for the our native event table */
216 if ( example_native_table == NULL ) {
218 "Could not allocate %lu bytes of memory for EXAMPLE device structure.", num_events*sizeof(example_native_event_entry_t));
219 _example_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
222 goto fn_fail;
223 }
224
225 /* fill in the event table parameters */
226 /* for complicated components this will be done dynamically */
227 /* or by using an external library */
228
229 strcpy( example_native_table[0].name, "EXAMPLE_ZERO" );
230 strcpy( example_native_table[0].description,
231 "This is an example counter, that always returns 0" );
233
234 strcpy( example_native_table[1].name, "EXAMPLE_CONSTANT" );
235 strcpy( example_native_table[1].description,
236 "This is an example counter, that always returns a constant value of 42" );
238
239 strcpy( example_native_table[2].name, "EXAMPLE_AUTOINC" );
240 strcpy( example_native_table[2].description,
241 "This is an example counter, that reports a per-thread auto-incrementing value" );
243
244 strcpy( example_native_table[3].name, "EXAMPLE_GLOBAL_AUTOINC" );
245 strcpy( example_native_table[3].description,
246 "This is an example counter, that reports a global auto-incrementing value" );
248
249 /* Export the total number of events available */
251
252 /* Export the component id */
254
255 fn_exit:
256 _papi_hwd[cidx]->cmp_info.disabled = retval;
257 return retval;
258 fn_fail:
259 goto fn_exit;
260}
261
263static int
265{
266
267 example_context_t *example_context = (example_context_t *)ctx;
268
269 example_context->autoinc_value=0;
270
271 SUBDBG( "_example_init_thread %p...", ctx );
272
273 return PAPI_OK;
274}
275
276
277
283static int
285{
286 SUBDBG( "example_init_control_state... %p\n", ctl );
287
288 example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
289 memset( example_ctl, 0, sizeof ( example_control_state_t ) );
290
291 return PAPI_OK;
292}
293
294
296static int
299 int count,
300 hwd_context_t *ctx )
301{
302
303 (void) ctx;
304 int i, index;
305
306 example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
307
308 SUBDBG( "_example_update_control_state %p %p...", ctl, ctx );
309
310 /* if no events, return */
311 if (count==0) return PAPI_OK;
312
313 for( i = 0; i < count; i++ ) {
314 index = native[i].ni_event;
315
316 /* Map counter #i to Measure Event "index" */
317 example_ctl->which_counter[i]=index;
318
319 /* We have no constraints on event position, so any event */
320 /* can be in any slot. */
321 native[i].ni_position = i;
322 }
323
324 example_ctl->num_events=count;
325
326 return PAPI_OK;
327}
328
330static int
332{
333
334 (void) ctx;
335 (void) ctl;
336
337 SUBDBG( "example_start %p %p...", ctx, ctl );
338
339 /* anything that would need to be set at counter start time */
340
341 /* reset counters? */
342 /* For hardware that cannot reset counters, store initial */
343 /* counter state to the ctl and subtract it off at read time */
344
345 /* start the counting ?*/
346
347 return PAPI_OK;
348}
349
350
352static int
354{
355
356 (void) ctx;
357 (void) ctl;
358
359 SUBDBG( "example_stop %p %p...", ctx, ctl );
360
361 /* anything that would need to be done at counter stop time */
362
363
364
365 return PAPI_OK;
366}
367
368
370/* flags field is never set? */
371static int
373 long long **events, int flags )
374{
375
376 (void) flags;
377
378 example_context_t *example_ctx = (example_context_t *) ctx;
379 example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
380
381 SUBDBG( "example_read... %p %d", ctx, flags );
382
383 int i;
384
385 /* Read counters into expected slot */
386 for(i=0;i<example_ctl->num_events;i++) {
387 example_ctl->counter[i] =
388 example_hardware_read( example_ctl->which_counter[i],
389 example_ctx );
390 }
391
392 /* return pointer to the values we read */
393 *events = example_ctl->counter;
394
395 return PAPI_OK;
396}
397
399/* otherwise, the updated state is written to ESI->hw_start */
400static int
402 long long *events )
403{
404
405 example_context_t *example_ctx = (example_context_t *) ctx;
406 example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
407
408 int i;
409
410 SUBDBG( "example_write... %p %p", ctx, ctl );
411
412 /* Write counters into expected slot */
413 for(i=0;i<example_ctl->num_events;i++) {
415 example_ctx,
416 events[i] );
417 }
418
419 return PAPI_OK;
420}
421
422
424/* If the eventset is not currently running, then the saved value in the */
425/* EventSet is set to zero without calling this routine. */
426static int
428{
429 example_context_t *event_ctx = (example_context_t *)ctx;
430 (void) ctl;
431
432 SUBDBG( "example_reset ctx=%p ctrl=%p...", ctx, ctl );
433
434 /* Reset the hardware */
435 example_hardware_reset( event_ctx );
436
437 return PAPI_OK;
438}
439
441static int
443{
444
445 SUBDBG( "example_shutdown_component..." );
446
447 /* Free anything we allocated */
448
450
451 return PAPI_OK;
452}
453
455static int
457{
458
459 (void) ctx;
460
461 SUBDBG( "example_shutdown_thread... %p", ctx );
462
463 /* Last chance to clean up thread */
464
465 return PAPI_OK;
466}
467
468
469
476static int
478{
479
480 (void) ctx;
481 (void) code;
482 (void) option;
483
484 SUBDBG( "example_ctl..." );
485
486 return PAPI_OK;
487}
488
498static int
500{
501 (void) cntrl;
502
503 int found = 0;
504 SUBDBG( "example_set_domain..." );
505
506 if ( PAPI_DOM_USER & domain ) {
507 SUBDBG( " PAPI_DOM_USER " );
508 found = 1;
509 }
510 if ( PAPI_DOM_KERNEL & domain ) {
511 SUBDBG( " PAPI_DOM_KERNEL " );
512 found = 1;
513 }
514 if ( PAPI_DOM_OTHER & domain ) {
515 SUBDBG( " PAPI_DOM_OTHER " );
516 found = 1;
517 }
518 if ( PAPI_DOM_ALL & domain ) {
519 SUBDBG( " PAPI_DOM_ALL " );
520 found = 1;
521 }
522 if ( !found )
523 return ( PAPI_EINVAL );
524
525 return PAPI_OK;
526}
527
528
529/**************************************************************/
530/* Naming functions, used to translate event numbers to names */
531/**************************************************************/
532
533
540static int
541_example_ntv_enum_events( unsigned int *EventCode, int modifier )
542{
543 int index;
544
545
546 switch ( modifier ) {
547
548 /* return EventCode of first event */
549 case PAPI_ENUM_FIRST:
550 /* return the first event that we support */
551
552 *EventCode = 0;
553 return PAPI_OK;
554
555 /* return EventCode of next available event */
556 case PAPI_ENUM_EVENTS:
557 index = *EventCode;
558
559 /* Make sure we have at least 1 more event after us */
560 if ( index < num_events - 1 ) {
561
562 /* This assumes a non-sparse mapping of the events */
563 *EventCode = *EventCode + 1;
564 return PAPI_OK;
565 } else {
566 return PAPI_ENOEVNT;
567 }
568 break;
569
570 default:
571 return PAPI_EINVAL;
572 }
573
574 return PAPI_EINVAL;
575}
576
582static int
583_example_ntv_code_to_name( unsigned int EventCode, char *name, int len )
584{
585 int index;
586
587 index = EventCode;
588
589 /* Make sure we are in range */
590 if (index >= 0 && index < num_events) {
591 strncpy( name, example_native_table[index].name, len );
592 return PAPI_OK;
593 }
594
595 return PAPI_ENOEVNT;
596}
597
603static int
604_example_ntv_code_to_descr( unsigned int EventCode, char *descr, int len )
605{
606 int index;
607 index = EventCode;
608
609 /* make sure event is in range */
610 if (index >= 0 && index < num_events) {
611 strncpy( descr, example_native_table[index].description, len );
612 return PAPI_OK;
613 }
614
615 return PAPI_ENOEVNT;
616}
617
620 .cmp_info = {
621 /* default component information */
622 /* (unspecified values are initialized to 0) */
623 /* we explicitly set them to zero in this example */
624 /* to show what settings are available */
625
626 .name = "example",
627 .short_name = "example",
628 .description = "A simple example component",
629 .version = "1.15",
630 .support_version = "n/a",
631 .kernel_version = "n/a",
633 .num_mpx_cntrs = EXAMPLE_MAX_SIMULTANEOUS_COUNTERS,
634 .default_domain = PAPI_DOM_USER,
635 .available_domains = PAPI_DOM_USER,
636 .default_granularity = PAPI_GRN_THR,
637 .available_granularities = PAPI_GRN_THR,
638 .hardware_intr_sig = PAPI_INT_SIGNAL,
639
640 /* component specific cmp_info initializations */
641 },
642
643 /* sizes of framework-opaque component-private structures */
644 .size = {
645 /* once per thread */
646 .context = sizeof ( example_context_t ),
647 /* once per eventset */
648 .control_state = sizeof ( example_control_state_t ),
649 /* ?? */
650 .reg_value = sizeof ( example_register_t ),
651 /* ?? */
652 .reg_alloc = sizeof ( example_reg_alloc_t ),
653 },
654
655 /* function pointers */
656 /* by default they are set to NULL */
657
658 /* Used for general PAPI interactions */
659 .start = _example_start,
660 .stop = _example_stop,
661 .read = _example_read,
662 .reset = _example_reset,
663 .write = _example_write,
664 .init_component = _example_init_component,
665 .init_thread = _example_init_thread,
666 .init_control_state = _example_init_control_state,
667 .update_control_state = _example_update_control_state,
668 .ctl = _example_ctl,
669 .shutdown_thread = _example_shutdown_thread,
670 .shutdown_component = _example_shutdown_component,
671 .set_domain = _example_set_domain,
672 /* .cleanup_eventset = NULL, */
673 /* called in add_native_events() */
674 /* .allocate_registers = NULL, */
675
676 /* Used for overflow/profiling */
677 /* .dispatch_timer = NULL, */
678 /* .get_overflow_address = NULL, */
679 /* .stop_profiling = NULL, */
680 /* .set_overflow = NULL, */
681 /* .set_profile = NULL, */
682
683 /* ??? */
684 /* .user = NULL, */
685
686 /* Name Mapping Functions */
687 .ntv_enum_events = _example_ntv_enum_events,
688 .ntv_code_to_name = _example_ntv_code_to_name,
689 .ntv_code_to_descr = _example_ntv_code_to_descr,
690 /* if .ntv_name_to_code not available, PAPI emulates */
691 /* it by enumerating all events and looking manually */
692 .ntv_name_to_code = NULL,
693
694
695 /* These are only used by _papi_hwi_get_native_event_info() */
696 /* Which currently only uses the info for printing native */
697 /* event info, not for any sort of internal use. */
698 /* .ntv_code_to_bits = NULL, */
699
700};
701
int i
static long count
struct papi_vectors * _papi_hwd[]
#define EXAMPLE_ZERO_REG
Definition: example.c:102
static int detect_example(void)
Definition: example.c:177
static int _example_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: example.c:583
static example_native_event_entry_t * example_native_table
Definition: example.c:92
papi_vector_t _example_vector
Definition: example.c:38
#define EXAMPLE_GLOBAL_AUTOINC_REG
Definition: example.c:105
static int num_events
Definition: example.c:95
#define EXAMPLE_MAX_SIMULTANEOUS_COUNTERS
Definition: example.c:28
static int _example_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: example.c:297
static int example_hardware_write(int which_one, example_context_t *ctx, long long value)
Definition: example.c:153
static int _example_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:353
static int _example_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: example.c:541
#define EXAMPLE_TOTAL_EVENTS
Definition: example.c:107
static int _example_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:427
static long long example_hardware_read(int which_one, example_context_t *ctx)
Definition: example.c:126
#define EXAMPLE_CONSTANT_REG
Definition: example.c:103
static void example_hardware_reset(example_context_t *ctx)
Definition: example.c:113
#define EXAMPLE_AUTOINC_REG
Definition: example.c:104
static int _example_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: example.c:372
static int _example_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: example.c:331
#define EXAMPLE_MAX_MULTIPLEX_COUNTERS
Definition: example.c:29
static int _example_shutdown_thread(hwd_context_t *ctx)
Definition: example.c:456
static int _example_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *events)
Definition: example.c:401
static int _example_set_domain(hwd_control_state_t *cntrl, int domain)
Definition: example.c:499
static int _example_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: example.c:477
static int _example_init_component(int cidx)
Definition: example.c:192
static long long example_global_autoinc_value
Definition: example.c:109
static int _example_ntv_code_to_descr(unsigned int EventCode, char *descr, int len)
Definition: example.c:604
static int _example_init_control_state(hwd_control_state_t *ctl)
Definition: example.c:284
static int _example_init_thread(hwd_context_t *ctx)
Definition: example.c:264
static int _example_shutdown_component(void)
Definition: example.c:442
#define HANDLE_STRING_ERROR
Definition: example.c:34
#define PAPI_DOM_USER
Definition: f90papi.h:174
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_DOM_OTHER
Definition: f90papi.h:21
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_DOM_KERNEL
Definition: f90papi.h:254
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_GRN_THR
Definition: f90papi.h:265
#define PAPI_DOM_ALL
Definition: f90papi.h:261
char events[MAX_EVENTS][BUFSIZ]
Return codes and api definitions.
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
FILE * stderr
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define papi_free(a)
Definition: papi_memory.h:35
static int native
static int cidx
const char * name
Definition: rocs.c:225
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
long long autoinc_value
Definition: example.c:88
long long counter[EXAMPLE_MAX_MULTIPLEX_COUNTERS]
Definition: example.c:82
int which_counter[EXAMPLE_MAX_SIMULTANEOUS_COUNTERS]
Definition: example.c:81
Definition: example.c:53
int writable
Definition: example.c:57
example_register_t resources
Definition: example.c:54
example_register_t ra_bits
Definition: example.c:66
unsigned int selector
Definition: example.c:43
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
char * descr
int retval
Definition: zero_fork.c:53