Skip to content

PAPI Overflow

Treece-Burgess edited this page Jan 29, 2024 · 14 revisions

Overflow

An overflow happens when the number of occurrences of a particular hardware event exceeds a specified threshold. PAPI provides the ability to call user-defined handlers when an overflow occurs. This can be done in hardware, if the processor generates an interrupt signal when the counter reaches a specified value, or in software, by setting up a high-resolution interval timer and installing a timer interrupt handler. For software based overflow, PAPI compares the current counter value against the threshold every time the timer interrupt occurs. If the current value exceeds the threshold, then the user’s handler is called from within the signal context with some additional arguments. These arguments allow the user to determine which event overflowed, by how much it overflowed, and at what location in the source code the overflow occurred.

Using the same mechanism as for user programmable overflow, PAPI also guards against register precision overflow of counter values. Each counter can potentially be incremented multiple times in a single clock cycle. This fact combined with increasing clock speeds and the small dynamic range of some of the physical counters means that an overflow is likely to occur on platforms where 64-bit counters are not supported in hardware or by the operating system. In those cases, PAPI implements 64-bit counters in software using the same mechanism that handles overflow dispatch.

Beginning Overflows in Event Sets

An event set can begin registering overflows by utilizing the below five arguments and calling the PAPI_overflow low-level function:

int EventSet = PAPI_NULL, EventCode, threshold, flags;
PAPI_overflow_handler_t handler; /* user defined function to process to process overflow events */
int retval = PAPI_overflow(EventSet, EventCode, threshold, flags, handler);

Arguments for PAPI_overflow:

  • EventSet -- a reference to the event set to use.
  • EventCode -- the event to be used for overflow detection.
  • threshold -- the overflow threshold value to use.
  • flags -- bit map that controls the overflow mode of operation. The only currently valid setting is PAPI_OVERFLOW_FORCE_SW, which overrides the default hardware overflow setting on a platform that supports hardware overflow.
  • handler -- the handler function to call upon overflow.

This function marks a specific EventCode in an EventSet to generate an overflow signal after every threshold events are counted. Multiple events within an event set can be programmed to overflow by making successive calls to this function, but only a single overflow handler can be registered. To turn off overflow for a specific event, call PAPI_overflow with EventCode set to the desired event and threshold set to zero.

Overflow Handler

The handler function is a user-supplied callback routine that performs whatever special processing needed to handle the overflow interrupt, including sorting multiple overflowing events from each other. It must conform to the following prototype:

void PAPI_overflow_handler(int EventSet, void *address, long long overflow_vector, void *context) {
        // your code
}

Arguments for example Overflow Handler function:

  • EventSet -- a reference to the event set in use.
  • address -- the address of the program counter when the overflow occurred.
  • overflow_vector -- a 64-bit vector that specifies which counter(s) generated the overflow. Bit 0 corresponds to counter 0. The handler should be able to deal with multiple overflow bits per call if more than one event may be set to overflow.
  • context -- a platform dependent structure containing information about the state of the machine when the overflow occurred. This structure is provided for completeness, but can generally be ignored by most users.

Example

In the following code example, PAPI_overflow is used to mark PAPI_TOT_INS in order to generate an overflow signal after every 100,000 counted events:

#include <papi.h>    
#include <stdio.h>
#include <stdlib.h>

int total = 0; 

void handle_error (int retval)
{
    printf("PAPI error %d: %s\n", retval, PAPI_strerror(retval));
    exit(1);
}

void handler(int EventSet, void *address, long_long overflow_vector, void *context)
{
    fprintf(stderr, "handler(%d) Overflow at %p! vector=0x%llx\n",
            EventSet, address, overflow_vector);
    total++;
}

void do_flops( int n ) 
{
    int i;
    double a = 0.5, b = 2.2, c = 0.11;

    for ( i = 0; i < n; i++ ) { 
        c += a * b;
    }   
}

int main()
{
    int EventSet = PAPI_NULL, EventCode = PAPI_TOT_INS, n = 100000, threshold = 100000, flags = 0, retval;
    long long values[1];

    /* Initialize the PAPI library */
    retval = PAPI_library_init(PAPI_VER_CURRENT);
    if (retval != PAPI_VER_CURRENT)
        handle_error(retval);

    /* Create the EventSet */
    retval = PAPI_create_eventset(&EventSet);
    if (retval != PAPI_OK)
        handle_error(1);
    
    /* Add Total Instructions Executed to our EventSet */
    retval = PAPI_add_event(EventSet, PAPI_TOT_INS);
    if (retval != PAPI_OK)
        handle_error(retval);

    retval = PAPI_overflow(EventSet, EventCode, threshold, flags, handler);
    if (retval != PAPI_OK)
        handle_error(retval);

    /* start overflow run */
    retval = PAPI_start(EventSet);
    if (retval != PAPI_OK) { 
        handle_error(retval);
    }

    /* do arbitrary work */
    do_flops(n);

    /* stop overflow run */
    retval = PAPI_stop( EventSet, values );
    if ( retval != PAPI_OK )
        handle_error(retval);
    retval = PAPI_overflow( EventSet, EventCode, 0, flags, handler );
    if ( retval != PAPI_OK )
        handle_error(retval);

    printf("Overflows: %d\n", total);

    /* Executes if all low-level PAPI
    function calls returned PAPI_OK */
    printf("\033[0;32m\n\nPASSED\n\033[0m");
    exit(0); 
}

Possible Output

handler(0) Overflow at 0x40128b! vector=0x1
handler(0) Overflow at 0x401286! vector=0x1
handler(0) Overflow at 0x401282! vector=0x1
handler(0) Overflow at 0x401286! vector=0x1
handler(0) Overflow at 0x401282! vector=0x1
handler(0) Overflow at 0x401282! vector=0x1
handler(0) Overflow at 0x401286! vector=0x1
handler(0) Overflow at 0x40128b! vector=0x1
handler(0) Overflow at 0x7f8d4689d51d! vector=0x1
Overflows: 9


PASSED

On success, all PAPI functions return PAPI_OK and the above possible output is returned. On error, a non-zero error code is returned.

For more code examples, see ctests/overflow.c, ctests/overflow_twoevents.c or ctests/overflow_pthreads.c in the papi source distribution.