|
PAPI
5.0.1.0
|
This is an example component, it demos the component interface and implements three example counters. More...

Go to the source code of this file.
Definition in file example.c.
| #define EXAMPLE_AUTOINC_REG 2 |
| #define EXAMPLE_CONSTANT_REG 1 |
| #define EXAMPLE_GLOBAL_AUTOINC_REG 3 |
| #define EXAMPLE_MAX_MULTIPLEX_COUNTERS 4 |
| #define EXAMPLE_MAX_SIMULTANEOUS_COUNTERS 3 |
| #define EXAMPLE_TOTAL_EVENTS 4 |
| #define EXAMPLE_ZERO_REG 0 |
| int _example_ctl | ( | hwd_context_t * | ctx, |
| int | code, | ||
| _papi_int_option_t * | option | ||
| ) |
This function sets various options in the component
| [in] | ctx | -- hardware context |
| [in] | code | valid are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT |
| [in] | option | -- options to be set |
| int _example_init_component | ( | int | cidx | ) |
Initialize hardware counters, setup the function vector table and get hardware information, this routine is called when the PAPI process is initialized (IE PAPI_library_init)
Definition at line 187 of file example.c.
{
SUBDBG( "_example_init_component..." );
/* First, detect that our hardware is available */
if (detect_example()!=PAPI_OK) {
return PAPI_ECMP;
}
/* we know in advance how many events we want */
/* for actual hardware this might have to be determined dynamically */
num_events = EXAMPLE_TOTAL_EVENTS;
/* Allocate memory for the our native event table */
example_native_table =
( example_native_event_entry_t * )
papi_calloc( sizeof(example_native_event_entry_t),num_events);
if ( example_native_table == NULL ) {
PAPIERROR( "malloc():Could not get memory for events table" );
return PAPI_ENOMEM;
}
/* fill in the event table parameters */
/* for complicated components this will be done dynamically */
/* or by using an external library */
strcpy( example_native_table[0].name, "EXAMPLE_ZERO" );
strcpy( example_native_table[0].description,
"This is an example counter, that always returns 0" );
example_native_table[0].writable = 0;
strcpy( example_native_table[1].name, "EXAMPLE_CONSTANT" );
strcpy( example_native_table[1].description,
"This is an example counter, that always returns a constant value of 42" );
example_native_table[1].writable = 0;
strcpy( example_native_table[2].name, "EXAMPLE_AUTOINC" );
strcpy( example_native_table[2].description,
"This is an example counter, that reports a per-thread auto-incrementing value" );
example_native_table[2].writable = 1;
strcpy( example_native_table[3].name, "EXAMPLE_GLOBAL_AUTOINC" );
strcpy( example_native_table[3].description,
"This is an example counter, that reports a global auto-incrementing value" );
example_native_table[3].writable = 1;
/* Export the total number of events available */
_example_vector.cmp_info.num_native_events = num_events;
/* Export the component id */
_example_vector.cmp_info.CmpIdx = cidx;
return PAPI_OK;
}

| int _example_init_control_state | ( | hwd_control_state_t * | ctl | ) |
Setup a counter control state. In general a control state holds the hardware info for an EventSet.
Definition at line 268 of file example.c.
{
SUBDBG( "example_init_control_state... %p\n", ctl );
example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
memset( example_ctl, 0, sizeof ( example_control_state_t ) );
return PAPI_OK;
}
| int _example_init_thread | ( | hwd_context_t * | ctx | ) |
This is called whenever a thread is initialized
Definition at line 248 of file example.c.
{
example_context_t *example_context = (example_context_t *)ctx;
example_context->autoinc_value=0;
SUBDBG( "_example_init_thread %p...", ctx );
return PAPI_OK;
}
| int _example_ntv_code_to_descr | ( | unsigned int | EventCode, |
| char * | descr, | ||
| int | len | ||
| ) |
Takes a native event code and passes back the event description
| EventCode | is the native event code |
| descr | is a pointer for the description to be copied to |
| len | is the size of the descr string |
Definition at line 588 of file example.c.
{
int index;
index = EventCode;
/* make sure event is in range */
if (index >= 0 && index < num_events) {
strncpy( descr, example_native_table[index].description, len );
return PAPI_OK;
}
return PAPI_ENOEVNT;
}
| int _example_ntv_code_to_name | ( | unsigned int | EventCode, |
| char * | name, | ||
| int | len | ||
| ) |
Takes a native event code and passes back the name
| EventCode | is the native event code |
| name | is a pointer for the name to be copied to |
| len | is the size of the name string |
Definition at line 567 of file example.c.
{
int index;
index = EventCode;
/* Make sure we are in range */
if (index >= 0 && index < num_events) {
strncpy( name, example_native_table[index].name, len );
return PAPI_OK;
}
return PAPI_ENOEVNT;
}
| int _example_ntv_enum_events | ( | unsigned int * | EventCode, |
| int | modifier | ||
| ) |
Enumerate Native Events
| EventCode | is the event of interest |
| modifier | is one of PAPI_ENUM_FIRST, PAPI_ENUM_EVENTS If your component has attribute masks then these need to be handled here as well. |
Definition at line 525 of file example.c.
{
int index;
switch ( modifier ) {
/* return EventCode of first event */
case PAPI_ENUM_FIRST:
/* return the first event that we support */
*EventCode = 0;
return PAPI_OK;
/* return EventCode of next available event */
case PAPI_ENUM_EVENTS:
index = *EventCode;
/* Make sure we have at least 1 more event after us */
if ( index < num_events - 1 ) {
/* This assumes a non-sparse mapping of the events */
*EventCode = *EventCode + 1;
return PAPI_OK;
} else {
return PAPI_ENOEVNT;
}
break;
default:
return PAPI_EINVAL;
}
return PAPI_EINVAL;
}
| int _example_read | ( | hwd_context_t * | ctx, |
| hwd_control_state_t * | ctl, | ||
| long long ** | events, | ||
| int | flags | ||
| ) |
Triggered by PAPI_read()
Definition at line 356 of file example.c.
{
(void) flags;
example_context_t *example_ctx = (example_context_t *) ctx;
example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
SUBDBG( "example_read... %p %d", ctx, flags );
int i;
/* Read counters into expected slot */
for(i=0;i<example_ctl->num_events;i++) {
example_ctl->counter[i] =
example_hardware_read( example_ctl->which_counter[i],
example_ctx );
}
/* return pointer to the values we read */
*events = example_ctl->counter;
return PAPI_OK;
}

| int _example_reset | ( | hwd_context_t * | ctx, |
| hwd_control_state_t * | ctl | ||
| ) |
Triggered by PAPI_reset() but only if the EventSet is currently running
Definition at line 411 of file example.c.
{
example_context_t *event_ctx = (example_context_t *)ctx;
(void) ctl;
SUBDBG( "example_reset ctx=%p ctrl=%p...", ctx, ctl );
/* Reset the hardware */
example_hardware_reset( event_ctx );
return PAPI_OK;
}

| int _example_set_domain | ( | hwd_control_state_t * | cntrl, |
| int | domain | ||
| ) |
This function has to set the bits needed to count different domains In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER By default return PAPI_EINVAL if none of those are specified and PAPI_OK with success PAPI_DOM_USER is only user context is counted PAPI_DOM_KERNEL is only the Kernel/OS context is counted PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) PAPI_DOM_ALL is all of the domains
Definition at line 483 of file example.c.
{
(void) cntrl;
int found = 0;
SUBDBG( "example_set_domain..." );
if ( PAPI_DOM_USER & domain ) {
SUBDBG( " PAPI_DOM_USER " );
found = 1;
}
if ( PAPI_DOM_KERNEL & domain ) {
SUBDBG( " PAPI_DOM_KERNEL " );
found = 1;
}
if ( PAPI_DOM_OTHER & domain ) {
SUBDBG( " PAPI_DOM_OTHER " );
found = 1;
}
if ( PAPI_DOM_ALL & domain ) {
SUBDBG( " PAPI_DOM_ALL " );
found = 1;
}
if ( !found )
return ( PAPI_EINVAL );
return PAPI_OK;
}
| int _example_shutdown_component | ( | void | ) |
Triggered by PAPI_shutdown()
Definition at line 426 of file example.c.
{
SUBDBG( "example_shutdown_component..." );
/* Free anything we allocated */
papi_free(example_native_table);
return PAPI_OK;
}
| int _example_shutdown_thread | ( | hwd_context_t * | ctx | ) |
| int _example_start | ( | hwd_context_t * | ctx, |
| hwd_control_state_t * | ctl | ||
| ) |
Triggered by PAPI_start()
Definition at line 315 of file example.c.
{
(void) ctx;
(void) ctl;
SUBDBG( "example_start %p %p...", ctx, ctl );
/* anything that would need to be set at counter start time */
/* reset counters? */
/* For hardware that cannot reset counters, store initial */
/* counter state to the ctl and subtract it off at read time */
/* start the counting ?*/
return PAPI_OK;
}
| int _example_stop | ( | hwd_context_t * | ctx, |
| hwd_control_state_t * | ctl | ||
| ) |
Triggered by PAPI_stop()
| int _example_update_control_state | ( | hwd_control_state_t * | ctl, |
| NativeInfo_t * | native, | ||
| int | count, | ||
| hwd_context_t * | ctx | ||
| ) |
Triggered by eventset operations like add or remove
Definition at line 281 of file example.c.
{
(void) ctx;
int i, index;
example_control_state_t *example_ctl = ( example_control_state_t * ) ctl;
SUBDBG( "_example_update_control_state %p %p...", ctl, ctx );
/* if no events, return */
if (count==0) return PAPI_OK;
for( i = 0; i < count; i++ ) {
index = native[i].ni_event;
/* Map counter #i to Measure Event "index" */
example_ctl->which_counter[i]=index;
/* We have no constraints on event position, so any event */
/* can be in any slot. */
native[i].ni_position = i;
}
example_ctl->num_events=count;
return PAPI_OK;
}
| int _example_write | ( | hwd_context_t * | ctx, |
| hwd_control_state_t * | ctl, | ||
| long long * | events | ||
| ) |
Triggered by PAPI_write(), but only if the counters are running
Definition at line 385 of file example.c.
{
example_context_t *example_ctx = (example_context_t *) ctx;
example_control_state_t *example_ctl = ( example_control_state_t *) ctl;
int i;
SUBDBG( "example_write... %p %p", ctx, ctl );
/* Write counters into expected slot */
for(i=0;i<example_ctl->num_events;i++) {
example_hardware_write( example_ctl->which_counter[i],
example_ctx,
events[i] );
}
return PAPI_OK;
}

| static int detect_example | ( | void | ) | [static] |
| static long long example_hardware_read | ( | int | which_one, |
| example_context_t * | ctx | ||
| ) | [static] |
Code that reads event values.
Definition at line 121 of file example.c.
{
long long old_value;
switch ( which_one ) {
case EXAMPLE_ZERO_REG:
return 0;
case EXAMPLE_CONSTANT_REG:
return 42;
case EXAMPLE_AUTOINC_REG:
old_value = ctx->autoinc_value;
ctx->autoinc_value++;
return old_value;
case EXAMPLE_GLOBAL_AUTOINC_REG:
old_value = example_global_autoinc_value;
example_global_autoinc_value++;
return old_value;
default:
fprintf(stderr,"Invalid counter read %x\n",which_one );
return -1;
}
return 0;
}

| static void example_hardware_reset | ( | example_context_t * | ctx | ) | [static] |
Code that resets the hardware.
Definition at line 108 of file example.c.
{
/* reset per-thread count */
ctx->autoinc_value=0;
/* reset global count */
example_global_autoinc_value = 0;
}

| static int example_hardware_write | ( | int | which_one, |
| example_context_t * | ctx, | ||
| long long | value | ||
| ) | [static] |
Code that writes event values.
Definition at line 148 of file example.c.
{
switch ( which_one ) {
case EXAMPLE_ZERO_REG:
case EXAMPLE_CONSTANT_REG:
return PAPI_OK; /* can't be written */
case EXAMPLE_AUTOINC_REG:
ctx->autoinc_value=value;
return PAPI_OK;
case EXAMPLE_GLOBAL_AUTOINC_REG:
example_global_autoinc_value=value;
return PAPI_OK;
default:
perror( "Invalid counter write" );
return -1;
}
return 0;
}

long long example_global_autoinc_value = 0 [static] |
int num_events = 0 [static] |