|
Packit Service |
a1973e |
/****************************/
|
|
Packit Service |
a1973e |
/* THIS IS OPEN SOURCE CODE */
|
|
Packit Service |
a1973e |
/****************************/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* File: extras.c
|
|
Packit Service |
a1973e |
* Author: Philip Mucci
|
|
Packit Service |
a1973e |
* mucci@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: dan terpstra
|
|
Packit Service |
a1973e |
* terpstra@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Haihang You
|
|
Packit Service |
a1973e |
* you@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Kevin London
|
|
Packit Service |
a1973e |
* london@cs.utk.edu
|
|
Packit Service |
a1973e |
* Mods: Maynard Johnson
|
|
Packit Service |
a1973e |
* maynardj@us.ibm.com
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* This file contains portable routines to do things that we wish the
|
|
Packit Service |
a1973e |
vendors did in the kernel extensions or performance libraries. */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "papi.h"
|
|
Packit Service |
a1973e |
#include "papi_internal.h"
|
|
Packit Service |
a1973e |
#include "papi_vector.h"
|
|
Packit Service |
a1973e |
#include "papi_memory.h"
|
|
Packit Service |
a1973e |
#include "extras.h"
|
|
Packit Service |
a1973e |
#include "threads.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if (!defined(HAVE_FFSLL) || defined(__bgp__))
|
|
Packit Service |
a1973e |
int ffsll( long long lli );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/****************/
|
|
Packit Service |
a1973e |
/* BEGIN LOCALS */
|
|
Packit Service |
a1973e |
/****************/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static unsigned int _rnum = DEADBEEF;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/**************/
|
|
Packit Service |
a1973e |
/* END LOCALS */
|
|
Packit Service |
a1973e |
/**************/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
inline_static unsigned short
|
|
Packit Service |
a1973e |
random_ushort( void )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
return ( unsigned short ) ( _rnum = 1664525 * _rnum + 1013904223 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* compute the amount by which to increment the bucket.
|
|
Packit Service |
a1973e |
value is the current value of the bucket
|
|
Packit Service |
a1973e |
this routine is used by all three profiling cases
|
|
Packit Service |
a1973e |
it is inlined for speed
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
inline_static int
|
|
Packit Service |
a1973e |
profil_increment( long long value,
|
|
Packit Service |
a1973e |
int flags, long long excess, long long threshold )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int increment = 1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags == PAPI_PROFIL_POSIX ) {
|
|
Packit Service |
a1973e |
return ( 1 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_RANDOM ) {
|
|
Packit Service |
a1973e |
if ( random_ushort( ) <= ( USHRT_MAX / 4 ) )
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_COMPRESS ) {
|
|
Packit Service |
a1973e |
/* We're likely to ignore the sample if buf[address] gets big. */
|
|
Packit Service |
a1973e |
if ( random_ushort( ) < value ) {
|
|
Packit Service |
a1973e |
return ( 0 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_WEIGHTED ) { /* Increment is between 1 and 255 */
|
|
Packit Service |
a1973e |
if ( excess <= ( long long ) 1 )
|
|
Packit Service |
a1973e |
increment = 1;
|
|
Packit Service |
a1973e |
else if ( excess > threshold )
|
|
Packit Service |
a1973e |
increment = 255;
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
threshold = threshold / ( long long ) 255;
|
|
Packit Service |
a1973e |
increment = ( int ) ( excess / threshold );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return ( increment );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
posix_profil( caddr_t address, PAPI_sprofil_t * prof,
|
|
Packit Service |
a1973e |
int flags, long long excess, long long threshold )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
unsigned short *buf16;
|
|
Packit Service |
a1973e |
unsigned int *buf32;
|
|
Packit Service |
a1973e |
unsigned long long *buf64;
|
|
Packit Service |
a1973e |
unsigned long indx;
|
|
Packit Service |
a1973e |
unsigned long long lloffset;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* SPECIAL CASE: if starting address is 0 and scale factor is 2
|
|
Packit Service |
a1973e |
then all counts go into first bin.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
if ( ( prof->pr_off == 0 ) && ( prof->pr_scale == 0x2 ) )
|
|
Packit Service |
a1973e |
indx = 0;
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
/* compute the profile buffer offset by:
|
|
Packit Service |
a1973e |
- subtracting the profiling base address from the pc address
|
|
Packit Service |
a1973e |
- multiplying by the scaling factor
|
|
Packit Service |
a1973e |
- dividing by max scale (65536, or 2^^16)
|
|
Packit Service |
a1973e |
- dividing by implicit 2 (2^^1 for a total of 2^^17), for even addresses
|
|
Packit Service |
a1973e |
NOTE: 131072 is a valid scale value. It produces byte resolution of addresses
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
lloffset =
|
|
Packit Service |
a1973e |
( unsigned long long ) ( ( address - prof->pr_off ) *
|
|
Packit Service |
a1973e |
prof->pr_scale );
|
|
Packit Service |
a1973e |
indx = ( unsigned long ) ( lloffset >> 17 );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* confirm addresses within specified range */
|
|
Packit Service |
a1973e |
if ( address >= prof->pr_off ) {
|
|
Packit Service |
a1973e |
/* test first for 16-bit buckets; this should be the fast case */
|
|
Packit Service |
a1973e |
if ( flags & PAPI_PROFIL_BUCKET_16 ) {
|
|
Packit Service |
a1973e |
if ( ( indx * sizeof ( short ) ) < prof->pr_size ) {
|
|
Packit Service |
a1973e |
buf16 = (unsigned short *) prof->pr_base;
|
|
Packit Service |
a1973e |
buf16[indx] =
|
|
Packit Service |
a1973e |
( unsigned short ) ( ( unsigned short ) buf16[indx] +
|
|
Packit Service |
a1973e |
profil_increment( buf16[indx], flags,
|
|
Packit Service |
a1973e |
excess,
|
|
Packit Service |
a1973e |
threshold ) );
|
|
Packit Service |
a1973e |
PRFDBG( "posix_profil_16() bucket %lu = %u\n", indx,
|
|
Packit Service |
a1973e |
buf16[indx] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* next, look for the 32-bit case */
|
|
Packit Service |
a1973e |
else if ( flags & PAPI_PROFIL_BUCKET_32 ) {
|
|
Packit Service |
a1973e |
if ( ( indx * sizeof ( int ) ) < prof->pr_size ) {
|
|
Packit Service |
a1973e |
buf32 = (unsigned int *) prof->pr_base;
|
|
Packit Service |
a1973e |
buf32[indx] = ( unsigned int ) buf32[indx] +
|
|
Packit Service |
a1973e |
( unsigned int ) profil_increment( buf32[indx], flags,
|
|
Packit Service |
a1973e |
excess, threshold );
|
|
Packit Service |
a1973e |
PRFDBG( "posix_profil_32() bucket %lu = %u\n", indx,
|
|
Packit Service |
a1973e |
buf32[indx] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* finally, fall through to the 64-bit case */
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
if ( ( indx * sizeof ( long long ) ) < prof->pr_size ) {
|
|
Packit Service |
a1973e |
buf64 = (unsigned long long *) prof->pr_base;
|
|
Packit Service |
a1973e |
buf64[indx] = ( unsigned long long ) buf64[indx] +
|
|
Packit Service |
a1973e |
( unsigned long long ) profil_increment( ( long long )
|
|
Packit Service |
a1973e |
buf64[indx], flags,
|
|
Packit Service |
a1973e |
excess,
|
|
Packit Service |
a1973e |
threshold );
|
|
Packit Service |
a1973e |
PRFDBG( "posix_profil_64() bucket %lu = %lld\n", indx,
|
|
Packit Service |
a1973e |
buf64[indx] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
void
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_profile( EventSetInfo_t * ESI, caddr_t pc,
|
|
Packit Service |
a1973e |
long long over, int profile_index )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
EventSetProfileInfo_t *profile = &ESI->profile;
|
|
Packit Service |
a1973e |
PAPI_sprofil_t *sprof;
|
|
Packit Service |
a1973e |
caddr_t offset = 0;
|
|
Packit Service |
a1973e |
caddr_t best_offset = 0;
|
|
Packit Service |
a1973e |
int count;
|
|
Packit Service |
a1973e |
int best_index = -1;
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
PRFDBG( "handled IP %p\n", pc );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
sprof = profile->prof[profile_index];
|
|
Packit Service |
a1973e |
count = profile->count[profile_index];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < count; i++ ) {
|
|
Packit Service |
a1973e |
offset = sprof[i].pr_off;
|
|
Packit Service |
a1973e |
if ( ( offset < pc ) && ( offset > best_offset ) ) {
|
|
Packit Service |
a1973e |
best_index = i;
|
|
Packit Service |
a1973e |
best_offset = offset;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( best_index == -1 )
|
|
Packit Service |
a1973e |
best_index = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
posix_profil( pc, &sprof[best_index], profile->flags, over,
|
|
Packit Service |
a1973e |
profile->threshold[profile_index] );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* if isHardware is true, then the processor is using hardware overflow,
|
|
Packit Service |
a1973e |
else it is using software overflow. Use this parameter instead of
|
|
Packit Service |
a1973e |
_papi_hwi_system_info.supports_hw_overflow is in CRAY some processors
|
|
Packit Service |
a1973e |
may use hardware overflow, some may use software overflow.
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
overflow_bit: if the component can get the overflow bit when overflow
|
|
Packit Service |
a1973e |
occurs, then this should be passed by the component;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
If both genOverflowBit and isHardwareSupport are true, that means
|
|
Packit Service |
a1973e |
the component doesn't know how to get the overflow bit from the
|
|
Packit Service |
a1973e |
kernel directly, so we generate the overflow bit in this function
|
|
Packit Service |
a1973e |
since this function can access the ESI->overflow struct;
|
|
Packit Service |
a1973e |
(The component can only set genOverflowBit parameter to true if the
|
|
Packit Service |
a1973e |
hardware doesn't support multiple hardware overflow. If the
|
|
Packit Service |
a1973e |
component supports multiple hardware overflow and you don't know how
|
|
Packit Service |
a1973e |
to get the overflow bit, then I don't know how to deal with this
|
|
Packit Service |
a1973e |
situation).
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_overflow_signal( void *papiContext, caddr_t address,
|
|
Packit Service |
a1973e |
int *isHardware, long long overflow_bit,
|
|
Packit Service |
a1973e |
int genOverflowBit, ThreadInfo_t ** t,
|
|
Packit Service |
a1973e |
int cidx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int retval, event_counter, i, overflow_flag, pos;
|
|
Packit Service |
a1973e |
int papi_index, j;
|
|
Packit Service |
a1973e |
int profile_index = 0;
|
|
Packit Service |
a1973e |
long long overflow_vector;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
long long temp[_papi_hwd[cidx]->cmp_info.num_cntrs], over;
|
|
Packit Service |
a1973e |
long long latest = 0;
|
|
Packit Service |
a1973e |
ThreadInfo_t *thread;
|
|
Packit Service |
a1973e |
EventSetInfo_t *ESI;
|
|
Packit Service |
a1973e |
_papi_hwi_context_t *ctx = ( _papi_hwi_context_t * ) papiContext;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
OVFDBG( "enter\n" );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( *t )
|
|
Packit Service |
a1973e |
thread = *t;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
*t = thread = _papi_hwi_lookup_thread( 0 );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( thread != NULL ) {
|
|
Packit Service |
a1973e |
ESI = thread->running_eventset[cidx];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ESI == NULL ) || ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
|
|
Packit Service |
a1973e |
OVFDBG( "Either no eventset or eventset not set to overflow.\n" );
|
|
Packit Service |
a1973e |
#ifdef ANY_THREAD_GETS_SIGNAL
|
|
Packit Service |
a1973e |
_papi_hwi_broadcast_signal( thread->tid );
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ESI->CmpIdx != cidx )
|
|
Packit Service |
a1973e |
return ( PAPI_ENOCMP );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ESI->master != thread ) {
|
|
Packit Service |
a1973e |
PAPIERROR
|
|
Packit Service |
a1973e |
( "eventset->thread %#lx vs. current thread %#lx mismatch",
|
|
Packit Service |
a1973e |
ESI->master, thread );
|
|
Packit Service |
a1973e |
return ( PAPI_EBUG );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( isHardware ) {
|
|
Packit Service |
a1973e |
if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
|
|
Packit Service |
a1973e |
ESI->state |= PAPI_PAUSED;
|
|
Packit Service |
a1973e |
*isHardware = 1;
|
|
Packit Service |
a1973e |
} else
|
|
Packit Service |
a1973e |
*isHardware = 0;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* Get the latest counter value */
|
|
Packit Service |
a1973e |
event_counter = ESI->overflow.event_counter;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
overflow_flag = 0;
|
|
Packit Service |
a1973e |
overflow_vector = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) {
|
|
Packit Service |
a1973e |
retval = _papi_hwi_read( thread->context[cidx], ESI, ESI->sw_stop );
|
|
Packit Service |
a1973e |
if ( retval < PAPI_OK )
|
|
Packit Service |
a1973e |
return ( retval );
|
|
Packit Service |
a1973e |
for ( i = 0; i < event_counter; i++ ) {
|
|
Packit Service |
a1973e |
papi_index = ESI->overflow.EventIndex[i];
|
|
Packit Service |
a1973e |
latest = ESI->sw_stop[papi_index];
|
|
Packit Service |
a1973e |
temp[i] = -1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( latest >= ( long long ) ESI->overflow.deadline[i] ) {
|
|
Packit Service |
a1973e |
OVFDBG
|
|
Packit Service |
a1973e |
( "dispatch_overflow() latest %lld, deadline %lld, threshold %d\n",
|
|
Packit Service |
a1973e |
latest, ESI->overflow.deadline[i],
|
|
Packit Service |
a1973e |
ESI->overflow.threshold[i] );
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[papi_index].pos[0];
|
|
Packit Service |
a1973e |
overflow_vector ^= ( long long ) 1 << pos;
|
|
Packit Service |
a1973e |
temp[i] = latest - ESI->overflow.deadline[i];
|
|
Packit Service |
a1973e |
overflow_flag = 1;
|
|
Packit Service |
a1973e |
/* adjust the deadline */
|
|
Packit Service |
a1973e |
ESI->overflow.deadline[i] =
|
|
Packit Service |
a1973e |
latest + ESI->overflow.threshold[i];
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else if ( genOverflowBit ) {
|
|
Packit Service |
a1973e |
/* we had assumed the overflow event can't be derived event */
|
|
Packit Service |
a1973e |
papi_index = ESI->overflow.EventIndex[0];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* suppose the pos is the same as the counter number
|
|
Packit Service |
a1973e |
* (this is not true in Itanium, but itanium doesn't
|
|
Packit Service |
a1973e |
* need us to generate the overflow bit
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[papi_index].pos[0];
|
|
Packit Service |
a1973e |
overflow_vector = ( long long ) 1 << pos;
|
|
Packit Service |
a1973e |
} else
|
|
Packit Service |
a1973e |
overflow_vector = overflow_bit;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) || overflow_flag ) {
|
|
Packit Service |
a1973e |
if ( ESI->state & PAPI_PROFILING ) {
|
|
Packit Service |
a1973e |
int k = 0;
|
|
Packit Service |
a1973e |
while ( overflow_vector ) {
|
|
Packit Service |
a1973e |
i = ffsll( overflow_vector ) - 1;
|
|
Packit Service |
a1973e |
for ( j = 0; j < event_counter; j++ ) {
|
|
Packit Service |
a1973e |
papi_index = ESI->overflow.EventIndex[j];
|
|
Packit Service |
a1973e |
/* This loop is here ONLY because Pentium 4 can have tagged *
|
|
Packit Service |
a1973e |
* events that contain more than one counter without being *
|
|
Packit Service |
a1973e |
* derived. You've gotta scan all terms to make sure you *
|
|
Packit Service |
a1973e |
* find the one to profile. */
|
|
Packit Service |
a1973e |
for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0;
|
|
Packit Service |
a1973e |
k++ ) {
|
|
Packit Service |
a1973e |
pos = ESI->EventInfoArray[papi_index].pos[k];
|
|
Packit Service |
a1973e |
if ( i == pos ) {
|
|
Packit Service |
a1973e |
profile_index = j;
|
|
Packit Service |
a1973e |
goto foundit;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if ( j == event_counter ) {
|
|
Packit Service |
a1973e |
PAPIERROR
|
|
Packit Service |
a1973e |
( "BUG! overflow_vector is 0, dropping interrupt" );
|
|
Packit Service |
a1973e |
return ( PAPI_EBUG );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
foundit:
|
|
Packit Service |
a1973e |
if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) )
|
|
Packit Service |
a1973e |
over = 0;
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
over = temp[profile_index];
|
|
Packit Service |
a1973e |
_papi_hwi_dispatch_profile( ESI, address, over,
|
|
Packit Service |
a1973e |
profile_index );
|
|
Packit Service |
a1973e |
overflow_vector ^= ( long long ) 1 << i;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
/* do not use overflow_vector after this place */
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
ESI->overflow.handler( ESI->EventSetIndex, ( void * ) address,
|
|
Packit Service |
a1973e |
overflow_vector, ctx->ucontext );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
ESI->state &= ~( PAPI_PAUSED );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#ifdef ANY_THREAD_GETS_SIGNAL
|
|
Packit Service |
a1973e |
else {
|
|
Packit Service |
a1973e |
OVFDBG( "I haven't been noticed by PAPI before\n" );
|
|
Packit Service |
a1973e |
_papi_hwi_broadcast_signal( ( *_papi_hwi_thread_id_fn ) ( ) );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include <sys/time.h>
|
|
Packit Service |
a1973e |
#include <errno.h>
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int _papi_hwi_using_signal[PAPI_NSIG];
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_start_timer( int timer, int signal, int ns )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
struct itimerval value;
|
|
Packit Service |
a1973e |
int us = ns / 1000;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if ( us == 0 )
|
|
Packit Service |
a1973e |
us = 1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef ANY_THREAD_GETS_SIGNAL
|
|
Packit Service |
a1973e |
_papi_hwi_lock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
if ( ( _papi_hwi_using_signal[signal] - 1 ) ) {
|
|
Packit Service |
a1973e |
INTDBG( "itimer already installed\n" );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
( void ) signal; /*unused */
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
value.it_interval.tv_sec = 0;
|
|
Packit Service |
a1973e |
value.it_interval.tv_usec = us;
|
|
Packit Service |
a1973e |
value.it_value.tv_sec = 0;
|
|
Packit Service |
a1973e |
value.it_value.tv_usec = us;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "Installing itimer %d, with %d us interval\n", timer, us );
|
|
Packit Service |
a1973e |
if ( setitimer( timer, &value, NULL ) < 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "setitimer errno %d", errno );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_start_signal( int signal, int need_context, int cidx )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
struct sigaction action;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
_papi_hwi_lock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
_papi_hwi_using_signal[signal]++;
|
|
Packit Service |
a1973e |
if ( _papi_hwi_using_signal[signal] - 1 ) {
|
|
Packit Service |
a1973e |
INTDBG( "_papi_hwi_using_signal is now %d\n",
|
|
Packit Service |
a1973e |
_papi_hwi_using_signal[signal] );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
memset( &action, 0x00, sizeof ( struct sigaction ) );
|
|
Packit Service |
a1973e |
action.sa_flags = SA_RESTART;
|
|
Packit Service |
a1973e |
action.sa_sigaction =
|
|
Packit Service |
a1973e |
( void ( * )( int, siginfo_t *, void * ) ) _papi_hwd[cidx]->
|
|
Packit Service |
a1973e |
dispatch_timer;
|
|
Packit Service |
a1973e |
if ( need_context )
|
|
Packit Service |
a1973e |
#if (defined(_BGL) /*|| defined (__bgp__)*/)
|
|
Packit Service |
a1973e |
action.sa_flags |= SIGPWR;
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
action.sa_flags |= SA_SIGINFO;
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "installing signal handler\n" );
|
|
Packit Service |
a1973e |
if ( sigaction( signal, &action, NULL ) < 0 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "sigaction errno %d", errno );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "_papi_hwi_using_signal[%d] is now %d.\n", signal,
|
|
Packit Service |
a1973e |
_papi_hwi_using_signal[signal] );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_stop_signal( int signal )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
_papi_hwi_lock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
if ( --_papi_hwi_using_signal[signal] == 0 ) {
|
|
Packit Service |
a1973e |
INTDBG( "removing signal handler\n" );
|
|
Packit Service |
a1973e |
if ( sigaction( signal, NULL, NULL ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "sigaction errno %d", errno );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
return ( PAPI_ESYS );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "_papi_hwi_using_signal[%d] is now %d\n", signal,
|
|
Packit Service |
a1973e |
_papi_hwi_using_signal[signal] );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
_papi_hwi_stop_timer( int timer, int signal )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
struct itimerval value;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#ifdef ANY_THREAD_GETS_SIGNAL
|
|
Packit Service |
a1973e |
_papi_hwi_lock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
if ( _papi_hwi_using_signal[signal] > 1 ) {
|
|
Packit Service |
a1973e |
INTDBG( "itimer in use by another thread\n" );
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
return ( PAPI_OK );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
_papi_hwi_unlock( INTERNAL_LOCK );
|
|
Packit Service |
a1973e |
#else
|
|
Packit Service |
a1973e |
( void ) signal; /*unused */
|
|
Packit Service |
a1973e |
#endif
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
value.it_interval.tv_sec = 0;
|
|
Packit Service |
a1973e |
value.it_interval.tv_usec = 0;
|
|
Packit Service |
a1973e |
value.it_value.tv_sec = 0;
|
|
Packit Service |
a1973e |
value.it_value.tv_usec = 0;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
INTDBG( "turning off timer\n" );
|
|
Packit Service |
a1973e |
if ( setitimer( timer, &value, NULL ) == -1 ) {
|
|
Packit Service |
a1973e |
PAPIERROR( "setitimer errno %d", errno );
|
|
Packit Service |
a1973e |
return PAPI_ESYS;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#if (!defined(HAVE_FFSLL) || defined(__bgp__))
|
|
Packit Service |
a1973e |
/* find the first set bit in long long */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
ffsll( long long lli )
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int i, num, t, tmpint, len;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
num = sizeof ( long long ) / sizeof ( int );
|
|
Packit Service |
a1973e |
if ( num == 1 )
|
|
Packit Service |
a1973e |
return ( ffs( ( int ) lli ) );
|
|
Packit Service |
a1973e |
len = sizeof ( int ) * CHAR_BIT;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for ( i = 0; i < num; i++ ) {
|
|
Packit Service |
a1973e |
tmpint = ( int ) ( ( ( lli >> len ) << len ) ^ lli );
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
t = ffs( tmpint );
|
|
Packit Service |
a1973e |
if ( t ) {
|
|
Packit Service |
a1973e |
return ( t + i * len );
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
lli = lli >> len;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
return PAPI_OK;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
#endif
|