PAPI  5.0.1.0
extras.c File Reference
Include dependency graph for extras.c:

Go to the source code of this file.

Functions

static unsigned short random_ushort (void)
static int profil_increment (long long value, int flags, long long excess, long long threshold)
static void posix_profil (caddr_t address, PAPI_sprofil_t *prof, int flags, long long excess, long long threshold)
void _papi_hwi_dispatch_profile (EventSetInfo_t *ESI, caddr_t pc, long long over, int profile_index)
int _papi_hwi_dispatch_overflow_signal (void *papiContext, caddr_t address, int *isHardware, long long overflow_bit, int genOverflowBit, ThreadInfo_t **t, int cidx)
int _papi_hwi_start_timer (int timer, int signal, int ns)
int _papi_hwi_start_signal (int signal, int need_context, int cidx)
int _papi_hwi_stop_signal (int signal)
int _papi_hwi_stop_timer (int timer, int signal)

Variables

static unsigned int _rnum = 0xdedbeef
int _papi_hwi_using_signal [128]

Function Documentation

int _papi_hwi_dispatch_overflow_signal ( void *  papiContext,
caddr_t  address,
int *  isHardware,
long long  overflow_bit,
int  genOverflowBit,
ThreadInfo_t **  t,
int  cidx 
)

< EventSet has overflowing enabled

< No error

< Component Index isn't set

< Internal error, please send mail to the developers

< Using Hardware

< EventSet temp. disabled by the library

< Using Hardware

< No error

< Using Hardware

< EventSet has profiling enabled

< Internal error, please send mail to the developers

< Using Hardware

< EventSet temp. disabled by the library

< No error

Definition at line 214 of file extras.c.

{
    int retval, event_counter, i, overflow_flag, pos;
    int papi_index, j;
    int profile_index = 0;
    long long overflow_vector;

    long long temp[_papi_hwd[cidx]->cmp_info.num_cntrs], over;
    long long latest = 0;
    ThreadInfo_t *thread;
    EventSetInfo_t *ESI;
    _papi_hwi_context_t *ctx = ( _papi_hwi_context_t * ) papiContext;

    OVFDBG( "enter\n" );

    if ( *t )
        thread = *t;
    else
        *t = thread = _papi_hwi_lookup_thread( 0 );

    if ( thread != NULL ) {
        ESI = thread->running_eventset[cidx];

        if ( ( ESI == NULL ) || ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
            OVFDBG( "Either no eventset or eventset not set to overflow.\n" );
#ifdef ANY_THREAD_GETS_SIGNAL
            _papi_hwi_broadcast_signal( thread->tid );
#endif
            return ( PAPI_OK );
        }

        if ( ESI->CmpIdx != cidx )
            return ( PAPI_ENOCMP );

        if ( ESI->master != thread ) {
            PAPIERROR
                ( "eventset->thread 0x%lx vs. current thread 0x%lx mismatch",
                  ESI->master, thread );
            return ( PAPI_EBUG );
        }

        if ( isHardware ) {
            if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
                ESI->state |= PAPI_PAUSED;
                *isHardware = 1;
            } else
                *isHardware = 0;
        }
        /* Get the latest counter value */
        event_counter = ESI->overflow.event_counter;

        overflow_flag = 0;
        overflow_vector = 0;

        if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) {
            retval = _papi_hwi_read( thread->context[cidx], ESI, ESI->sw_stop );
            if ( retval < PAPI_OK )
                return ( retval );
            for ( i = 0; i < event_counter; i++ ) {
                papi_index = ESI->overflow.EventIndex[i];
                latest = ESI->sw_stop[papi_index];
                temp[i] = -1;

                if ( latest >= ( long long ) ESI->overflow.deadline[i] ) {
                    OVFDBG
                        ( "dispatch_overflow() latest %lld, deadline %lld, threshold %d\n",
                          latest, ESI->overflow.deadline[i],
                          ESI->overflow.threshold[i] );
                    pos = ESI->EventInfoArray[papi_index].pos[0];
                    overflow_vector ^= ( long long ) 1 << pos;
                    temp[i] = latest - ESI->overflow.deadline[i];
                    overflow_flag = 1;
                    /* adjust the deadline */
                    ESI->overflow.deadline[i] =
                        latest + ESI->overflow.threshold[i];
                }
            }
        } else if ( genOverflowBit ) {
            /* we had assumed the overflow event can't be derived event */
            papi_index = ESI->overflow.EventIndex[0];

            /* suppose the pos is the same as the counter number
             * (this is not true in Itanium, but itanium doesn't 
             * need us to generate the overflow bit
             */
            pos = ESI->EventInfoArray[papi_index].pos[0];
            overflow_vector = ( long long ) 1 << pos;
        } else
            overflow_vector = overflow_bit;

        if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) || overflow_flag ) {
            if ( ESI->state & PAPI_PROFILING ) {
                int k = 0;
                while ( overflow_vector ) {
                    i = ffsll( overflow_vector ) - 1;
                    for ( j = 0; j < event_counter; j++ ) {
                        papi_index = ESI->overflow.EventIndex[j];
                        /* This loop is here ONLY because Pentium 4 can have tagged *
                         * events that contain more than one counter without being  *
                         * derived. You've gotta scan all terms to make sure you    *
                         * find the one to profile. */
                        for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0;
                              k++ ) {
                            pos = ESI->EventInfoArray[papi_index].pos[k];
                            if ( i == pos ) {
                                profile_index = j;
                                goto foundit;
                            }
                        }
                    }
                    if ( j == event_counter ) {
                        PAPIERROR
                            ( "BUG! overflow_vector is 0, dropping interrupt" );
                        return ( PAPI_EBUG );
                    }

                  foundit:
                    if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) )
                        over = 0;
                    else
                        over = temp[profile_index];
                    _papi_hwi_dispatch_profile( ESI, address, over,
                                                profile_index );
                    overflow_vector ^= ( long long ) 1 << i;
                }
                /* do not use overflow_vector after this place */
            } else {
                ESI->overflow.handler( ESI->EventSetIndex, ( void * ) address,
                                       overflow_vector, ctx->ucontext );
            }
        }
        ESI->state &= ~( PAPI_PAUSED );
    }
#ifdef ANY_THREAD_GETS_SIGNAL
    else {
        OVFDBG( "I haven't been noticed by PAPI before\n" );
        _papi_hwi_broadcast_signal( ( *_papi_hwi_thread_id_fn ) (  ) );
    }
#endif
    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _papi_hwi_dispatch_profile ( EventSetInfo_t ESI,
caddr_t  pc,
long long  over,
int  profile_index 
)

Definition at line 163 of file extras.c.

{
    EventSetProfileInfo_t *profile = &ESI->profile;
    PAPI_sprofil_t *sprof;
    caddr_t offset = 0;
    caddr_t best_offset = 0;
    int count;
    int best_index = -1;
    int i;

    PRFDBG( "handled IP 0x%p\n", pc );

    sprof = profile->prof[profile_index];
    count = profile->count[profile_index];

    for ( i = 0; i < count; i++ ) {
        offset = sprof[i].pr_off;
        if ( ( offset < pc ) && ( offset > best_offset ) ) {
            best_index = i;
            best_offset = offset;
        }
    }

    if ( best_index == -1 )
        best_index = 0;

    posix_profil( pc, &sprof[best_index], profile->flags, over,
                  profile->threshold[profile_index] );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_start_signal ( int  signal,
int  need_context,
int  cidx 
)

< Used with setting up array

< Used with setting up array

< No error

< Used with setting up array

< A System/C library call failed

< Used with setting up array

< No error

Definition at line 401 of file extras.c.

{
    struct sigaction action;

    _papi_hwi_lock( INTERNAL_LOCK );
    _papi_hwi_using_signal[signal]++;
    if ( _papi_hwi_using_signal[signal] - 1 ) {
        INTDBG( "_papi_hwi_using_signal is now %d\n",
                _papi_hwi_using_signal[signal] );
        _papi_hwi_unlock( INTERNAL_LOCK );
        return ( PAPI_OK );
    }

    memset( &action, 0x00, sizeof ( struct sigaction ) );
    action.sa_flags = SA_RESTART;
    action.sa_sigaction =
        ( void ( * )( int, siginfo_t *, void * ) ) _papi_hwd[cidx]->
        dispatch_timer;
    if ( need_context )
#if (defined(_BGL) /*|| defined (__bgp__)*/)
        action.sa_flags |= SIGPWR;
#else
        action.sa_flags |= SA_SIGINFO;
#endif

    INTDBG( "installing signal handler\n" );
    if ( sigaction( signal, &action, NULL ) < 0 ) {
        PAPIERROR( "sigaction errno %d", errno );
        _papi_hwi_unlock( INTERNAL_LOCK );
        return ( PAPI_ESYS );
    }

    INTDBG( "_papi_hwi_using_signal[%d] is now %d.\n", signal,
            _papi_hwi_using_signal[signal] );
    _papi_hwi_unlock( INTERNAL_LOCK );

    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_start_timer ( int  timer,
int  signal,
int  ns 
)

< A System/C library call failed

< No error

Definition at line 366 of file extras.c.

{
    struct itimerval value;
    int us = ns / 1000;

    if ( us == 0 )
        us = 1;

#ifdef ANY_THREAD_GETS_SIGNAL
    _papi_hwi_lock( INTERNAL_LOCK );
    if ( ( _papi_hwi_using_signal[signal] - 1 ) ) {
        INTDBG( "itimer already installed\n" );
        _papi_hwi_unlock( INTERNAL_LOCK );
        return ( PAPI_OK );
    }
    _papi_hwi_unlock( INTERNAL_LOCK );
#else
    ( void ) signal;         /*unused */
#endif

    value.it_interval.tv_sec = 0;
    value.it_interval.tv_usec = us;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = us;

    INTDBG( "Installing itimer %d, with %d us interval\n", timer, us );
    if ( setitimer( timer, &value, NULL ) < 0 ) {
        PAPIERROR( "setitimer errno %d", errno );
        return ( PAPI_ESYS );
    }

    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_stop_signal ( int  signal)

< Used with setting up array

< Used with setting up array

< A System/C library call failed

< Used with setting up array

< No error

Definition at line 441 of file extras.c.

{
    _papi_hwi_lock( INTERNAL_LOCK );
    if ( --_papi_hwi_using_signal[signal] == 0 ) {
        INTDBG( "removing signal handler\n" );
        if ( sigaction( signal, NULL, NULL ) == -1 ) {
            PAPIERROR( "sigaction errno %d", errno );
            _papi_hwi_unlock( INTERNAL_LOCK );
            return ( PAPI_ESYS );
        }
    }

    INTDBG( "_papi_hwi_using_signal[%d] is now %d\n", signal,
            _papi_hwi_using_signal[signal] );
    _papi_hwi_unlock( INTERNAL_LOCK );

    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_stop_timer ( int  timer,
int  signal 
)

< A System/C library call failed

< No error

Definition at line 461 of file extras.c.

{
#ifdef ANY_THREAD_GETS_SIGNAL
    _papi_hwi_lock( INTERNAL_LOCK );
    if ( _papi_hwi_using_signal[signal] > 1 ) {
        INTDBG( "itimer in use by another thread\n" );
        _papi_hwi_unlock( INTERNAL_LOCK );
        return ( PAPI_OK );
    }
    _papi_hwi_unlock( INTERNAL_LOCK );
#else
    ( void ) signal;         /*unused */
#endif

    INTDBG( "turning off timer\n" );
    if ( setitimer( timer, NULL, NULL ) == -1 ) {
        PAPIERROR( "setitimer errno %d", errno );
        return ( PAPI_ESYS );
    }

    return ( PAPI_OK );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void posix_profil ( caddr_t  address,
PAPI_sprofil_t prof,
int  flags,
long long  excess,
long long  threshold 
) [static]

< Use 16 bit buckets to accumulate profile info (default)

< Use 32 bit buckets to accumulate profile info

Definition at line 92 of file extras.c.

{
    unsigned short *buf16;
    unsigned int *buf32;
    unsigned long long *buf64;
    unsigned long indx;
    unsigned long long lloffset;

    /* SPECIAL CASE: if starting address is 0 and scale factor is 2
       then all counts go into first bin.
     */
    if ( ( prof->pr_off == 0 ) && ( prof->pr_scale == 0x2 ) )
        indx = 0;
    else {
        /* compute the profile buffer offset by:
           - subtracting the profiling base address from the pc address
           - multiplying by the scaling factor
           - dividing by max scale (65536, or 2^^16) 
           - dividing by implicit 2 (2^^1 for a total of 2^^17), for even addresses
           NOTE: 131072 is a valid scale value. It produces byte resolution of addresses
         */
        lloffset =
            ( unsigned long long ) ( ( address - prof->pr_off ) *
                                     prof->pr_scale );
        indx = ( unsigned long ) ( lloffset >> 17 );
    }

    /* confirm addresses within specified range */
    if ( address >= prof->pr_off ) {
        /* test first for 16-bit buckets; this should be the fast case */
        if ( flags & PAPI_PROFIL_BUCKET_16 ) {
            if ( ( indx * sizeof ( short ) ) < prof->pr_size ) {
                buf16 = prof->pr_base;
                buf16[indx] =
                    ( unsigned short ) ( ( unsigned short ) buf16[indx] +
                                         profil_increment( buf16[indx], flags,
                                                           excess,
                                                           threshold ) );
                PRFDBG( "posix_profil_16() bucket %lu = %u\n", indx,
                        buf16[indx] );
            }
        }
        /* next, look for the 32-bit case */
        else if ( flags & PAPI_PROFIL_BUCKET_32 ) {
            if ( ( indx * sizeof ( int ) ) < prof->pr_size ) {
                buf32 = prof->pr_base;
                buf32[indx] = ( unsigned int ) buf32[indx] +
                    ( unsigned int ) profil_increment( buf32[indx], flags,
                                                       excess, threshold );
                PRFDBG( "posix_profil_32() bucket %lu = %u\n", indx,
                        buf32[indx] );
            }
        }
        /* finally, fall through to the 64-bit case */
        else {
            if ( ( indx * sizeof ( long long ) ) < prof->pr_size ) {
                buf64 = prof->pr_base;
                buf64[indx] = ( unsigned long long ) buf64[indx] +
                    ( unsigned long long ) profil_increment( ( long long )
                                                             buf64[indx], flags,
                                                             excess,
                                                             threshold );
                PRFDBG( "posix_profil_64() bucket %lu = %lld\n", indx,
                        buf64[indx] );
            }
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int profil_increment ( long long  value,
int  flags,
long long  excess,
long long  threshold 
) [inline, static]

< Default type of profiling, similar to 'man profil'.

< Drop a random 25% of the samples.

< Ignore samples if hash buckets get big.

< Weight the samples by their value.

Definition at line 56 of file extras.c.

{
    int increment = 1;

    if ( flags == PAPI_PROFIL_POSIX ) {
        return ( 1 );
    }

    if ( flags & PAPI_PROFIL_RANDOM ) {
        if ( random_ushort(  ) <= ( USHRT_MAX / 4 ) )
            return ( 0 );
    }

    if ( flags & PAPI_PROFIL_COMPRESS ) {
        /* We're likely to ignore the sample if buf[address] gets big. */
        if ( random_ushort(  ) < value ) {
            return ( 0 );
        }
    }

    if ( flags & PAPI_PROFIL_WEIGHTED ) {   /* Increment is between 1 and 255 */
        if ( excess <= ( long long ) 1 )
            increment = 1;
        else if ( excess > threshold )
            increment = 255;
        else {
            threshold = threshold / ( long long ) 255;
            increment = ( int ) ( excess / threshold );
        }
    }
    return ( increment );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned short random_ushort ( void  ) [inline, static]

Definition at line 44 of file extras.c.

{
    return ( unsigned short ) ( _rnum = 1664525 * _rnum + 1013904223 );
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 363 of file extras.c.

unsigned int _rnum = 0xdedbeef [static]

Definition at line 37 of file extras.c.

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines