extras.c File Reference

Include dependency graph for extras.c:

Go to the source code of this file.

Functions

int ffsll (long long lli)
inline_static unsigned short random_ushort (void)
inline_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 = DEADBEEF
int _papi_hwi_using_signal [PAPI_NSIG]

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 
)

Definition at line 219 of file extras.c.

00223 {
00224     int retval, event_counter, i, overflow_flag, pos;
00225     int papi_index, j;
00226     int profile_index = 0;
00227     long long overflow_vector;
00228 
00229     long long temp[_papi_hwd[cidx]->cmp_info.num_cntrs], over;
00230     long long latest = 0;
00231     ThreadInfo_t *thread;
00232     EventSetInfo_t *ESI;
00233     _papi_hwi_context_t *ctx = ( _papi_hwi_context_t * ) papiContext;
00234 
00235     OVFDBG( "enter\n" );
00236 
00237     if ( *t )
00238         thread = *t;
00239     else
00240         *t = thread = _papi_hwi_lookup_thread( 0 );
00241 
00242     if ( thread != NULL ) {
00243         ESI = thread->running_eventset[cidx];
00244 
00245         if ( ( ESI == NULL ) || ( ( ESI->state & PAPI_OVERFLOWING ) == 0 ) ) {
00246             OVFDBG( "Either no eventset or eventset not set to overflow.\n" );
00247 #ifdef ANY_THREAD_GETS_SIGNAL
00248             _papi_hwi_broadcast_signal( thread->tid );
00249 #endif
00250             return ( PAPI_OK );
00251         }
00252 
00253         if ( ESI->CmpIdx != cidx )
00254             return ( PAPI_ENOCMP );
00255 
00256         if ( ESI->master != thread ) {
00257             PAPIERROR
00258                 ( "eventset->thread %#lx vs. current thread %#lx mismatch",
00259                   ESI->master, thread );
00260             return ( PAPI_EBUG );
00261         }
00262 
00263         if ( isHardware ) {
00264             if ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) {
00265                 ESI->state |= PAPI_PAUSED;
00266                 *isHardware = 1;
00267             } else
00268                 *isHardware = 0;
00269         }
00270         /* Get the latest counter value */
00271         event_counter = ESI->overflow.event_counter;
00272 
00273         overflow_flag = 0;
00274         overflow_vector = 0;
00275 
00276         if ( !( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) ) {
00277             retval = _papi_hwi_read( thread->context[cidx], ESI, ESI->sw_stop );
00278             if ( retval < PAPI_OK )
00279                 return ( retval );
00280             for ( i = 0; i < event_counter; i++ ) {
00281                 papi_index = ESI->overflow.EventIndex[i];
00282                 latest = ESI->sw_stop[papi_index];
00283                 temp[i] = -1;
00284 
00285                 if ( latest >= ( long long ) ESI->overflow.deadline[i] ) {
00286                     OVFDBG
00287                         ( "dispatch_overflow() latest %lld, deadline %lld, threshold %d\n",
00288                           latest, ESI->overflow.deadline[i],
00289                           ESI->overflow.threshold[i] );
00290                     pos = ESI->EventInfoArray[papi_index].pos[0];
00291                     overflow_vector ^= ( long long ) 1 << pos;
00292                     temp[i] = latest - ESI->overflow.deadline[i];
00293                     overflow_flag = 1;
00294                     /* adjust the deadline */
00295                     ESI->overflow.deadline[i] =
00296                         latest + ESI->overflow.threshold[i];
00297                 }
00298             }
00299         } else if ( genOverflowBit ) {
00300             /* we had assumed the overflow event can't be derived event */
00301             papi_index = ESI->overflow.EventIndex[0];
00302 
00303             /* suppose the pos is the same as the counter number
00304              * (this is not true in Itanium, but itanium doesn't 
00305              * need us to generate the overflow bit
00306              */
00307             pos = ESI->EventInfoArray[papi_index].pos[0];
00308             overflow_vector = ( long long ) 1 << pos;
00309         } else
00310             overflow_vector = overflow_bit;
00311 
00312         if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) || overflow_flag ) {
00313             if ( ESI->state & PAPI_PROFILING ) {
00314                 int k = 0;
00315                 while ( overflow_vector ) {
00316                     i = ffsll( overflow_vector ) - 1;
00317                     for ( j = 0; j < event_counter; j++ ) {
00318                         papi_index = ESI->overflow.EventIndex[j];
00319                         /* This loop is here ONLY because Pentium 4 can have tagged *
00320                          * events that contain more than one counter without being  *
00321                          * derived. You've gotta scan all terms to make sure you    *
00322                          * find the one to profile. */
00323                         for ( k = 0, pos = 0; k < PAPI_EVENTS_IN_DERIVED_EVENT && pos >= 0;
00324                               k++ ) {
00325                             pos = ESI->EventInfoArray[papi_index].pos[k];
00326                             if ( i == pos ) {
00327                                 profile_index = j;
00328                                 goto foundit;
00329                             }
00330                         }
00331                     }
00332                     if ( j == event_counter ) {
00333                         PAPIERROR
00334                             ( "BUG! overflow_vector is 0, dropping interrupt" );
00335                         return ( PAPI_EBUG );
00336                     }
00337 
00338                   foundit:
00339                     if ( ( ESI->overflow.flags & PAPI_OVERFLOW_HARDWARE ) )
00340                         over = 0;
00341                     else
00342                         over = temp[profile_index];
00343                     _papi_hwi_dispatch_profile( ESI, address, over,
00344                                                 profile_index );
00345                     overflow_vector ^= ( long long ) 1 << i;
00346                 }
00347                 /* do not use overflow_vector after this place */
00348             } else {
00349                 ESI->overflow.handler( ESI->EventSetIndex, ( void * ) address,
00350                                        overflow_vector, ctx->ucontext );
00351             }
00352         }
00353         ESI->state &= ~( PAPI_PAUSED );
00354     }
00355 #ifdef ANY_THREAD_GETS_SIGNAL
00356     else {
00357         OVFDBG( "I haven't been noticed by PAPI before\n" );
00358         _papi_hwi_broadcast_signal( ( *_papi_hwi_thread_id_fn ) (  ) );
00359     }
00360 #endif
00361     return ( PAPI_OK );
00362 }

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 168 of file extras.c.

00170 {
00171     EventSetProfileInfo_t *profile = &ESI->profile;
00172     PAPI_sprofil_t *sprof;
00173     caddr_t offset = 0;
00174     caddr_t best_offset = 0;
00175     int count;
00176     int best_index = -1;
00177     int i;
00178 
00179     PRFDBG( "handled IP %p\n", pc );
00180 
00181     sprof = profile->prof[profile_index];
00182     count = profile->count[profile_index];
00183 
00184     for ( i = 0; i < count; i++ ) {
00185         offset = sprof[i].pr_off;
00186         if ( ( offset < pc ) && ( offset > best_offset ) ) {
00187             best_index = i;
00188             best_offset = offset;
00189         }
00190     }
00191 
00192     if ( best_index == -1 )
00193         best_index = 0;
00194 
00195     posix_profil( pc, &sprof[best_index], profile->flags, over,
00196                   profile->threshold[profile_index] );
00197 }

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 
)

Definition at line 406 of file extras.c.

00407 {
00408     struct sigaction action;
00409 
00410     _papi_hwi_lock( INTERNAL_LOCK );
00411     _papi_hwi_using_signal[signal]++;
00412     if ( _papi_hwi_using_signal[signal] - 1 ) {
00413         INTDBG( "_papi_hwi_using_signal is now %d\n",
00414                 _papi_hwi_using_signal[signal] );
00415         _papi_hwi_unlock( INTERNAL_LOCK );
00416         return ( PAPI_OK );
00417     }
00418 
00419     memset( &action, 0x00, sizeof ( struct sigaction ) );
00420     action.sa_flags = SA_RESTART;
00421     action.sa_sigaction =
00422         ( void ( * )( int, siginfo_t *, void * ) ) _papi_hwd[cidx]->
00423         dispatch_timer;
00424     if ( need_context )
00425 #if (defined(_BGL) /*|| defined (__bgp__)*/)
00426         action.sa_flags |= SIGPWR;
00427 #else
00428         action.sa_flags |= SA_SIGINFO;
00429 #endif
00430 
00431     INTDBG( "installing signal handler\n" );
00432     if ( sigaction( signal, &action, NULL ) < 0 ) {
00433         PAPIERROR( "sigaction errno %d", errno );
00434         _papi_hwi_unlock( INTERNAL_LOCK );
00435         return ( PAPI_ESYS );
00436     }
00437 
00438     INTDBG( "_papi_hwi_using_signal[%d] is now %d.\n", signal,
00439             _papi_hwi_using_signal[signal] );
00440     _papi_hwi_unlock( INTERNAL_LOCK );
00441 
00442     return ( PAPI_OK );
00443 }

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 
)

Definition at line 371 of file extras.c.

00372 {
00373     struct itimerval value;
00374     int us = ns / 1000;
00375 
00376     if ( us == 0 )
00377         us = 1;
00378 
00379 #ifdef ANY_THREAD_GETS_SIGNAL
00380     _papi_hwi_lock( INTERNAL_LOCK );
00381     if ( ( _papi_hwi_using_signal[signal] - 1 ) ) {
00382         INTDBG( "itimer already installed\n" );
00383         _papi_hwi_unlock( INTERNAL_LOCK );
00384         return ( PAPI_OK );
00385     }
00386     _papi_hwi_unlock( INTERNAL_LOCK );
00387 #else
00388     ( void ) signal;         /*unused */
00389 #endif
00390 
00391     value.it_interval.tv_sec = 0;
00392     value.it_interval.tv_usec = us;
00393     value.it_value.tv_sec = 0;
00394     value.it_value.tv_usec = us;
00395 
00396     INTDBG( "Installing itimer %d, with %d us interval\n", timer, us );
00397     if ( setitimer( timer, &value, NULL ) < 0 ) {
00398         PAPIERROR( "setitimer errno %d", errno );
00399         return ( PAPI_ESYS );
00400     }
00401 
00402     return ( PAPI_OK );
00403 }

Here is the call graph for this function:

Here is the caller graph for this function:

int _papi_hwi_stop_signal ( int  signal  ) 

Definition at line 446 of file extras.c.

00447 {
00448     _papi_hwi_lock( INTERNAL_LOCK );
00449     if ( --_papi_hwi_using_signal[signal] == 0 ) {
00450         INTDBG( "removing signal handler\n" );
00451         if ( sigaction( signal, NULL, NULL ) == -1 ) {
00452             PAPIERROR( "sigaction errno %d", errno );
00453             _papi_hwi_unlock( INTERNAL_LOCK );
00454             return ( PAPI_ESYS );
00455         }
00456     }
00457 
00458     INTDBG( "_papi_hwi_using_signal[%d] is now %d\n", signal,
00459             _papi_hwi_using_signal[signal] );
00460     _papi_hwi_unlock( INTERNAL_LOCK );
00461 
00462     return ( PAPI_OK );
00463 }

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 
)

Definition at line 466 of file extras.c.

00467 {
00468     struct itimerval value;
00469 
00470 #ifdef ANY_THREAD_GETS_SIGNAL
00471     _papi_hwi_lock( INTERNAL_LOCK );
00472     if ( _papi_hwi_using_signal[signal] > 1 ) {
00473         INTDBG( "itimer in use by another thread\n" );
00474         _papi_hwi_unlock( INTERNAL_LOCK );
00475         return ( PAPI_OK );
00476     }
00477     _papi_hwi_unlock( INTERNAL_LOCK );
00478 #else
00479     ( void ) signal;         /*unused */
00480 #endif
00481 
00482     value.it_interval.tv_sec = 0;
00483     value.it_interval.tv_usec = 0;
00484     value.it_value.tv_sec = 0;
00485     value.it_value.tv_usec = 0;
00486 
00487     INTDBG( "turning off timer\n" );
00488     if ( setitimer( timer, &value, NULL ) == -1 ) {
00489         PAPIERROR( "setitimer errno %d", errno );
00490         return PAPI_ESYS;
00491     }
00492 
00493     return PAPI_OK;
00494 }

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]

Definition at line 97 of file extras.c.

00099 {
00100     unsigned short *buf16;
00101     unsigned int *buf32;
00102     unsigned long long *buf64;
00103     unsigned long indx;
00104     unsigned long long lloffset;
00105 
00106     /* SPECIAL CASE: if starting address is 0 and scale factor is 2
00107        then all counts go into first bin.
00108      */
00109     if ( ( prof->pr_off == 0 ) && ( prof->pr_scale == 0x2 ) )
00110         indx = 0;
00111     else {
00112         /* compute the profile buffer offset by:
00113            - subtracting the profiling base address from the pc address
00114            - multiplying by the scaling factor
00115            - dividing by max scale (65536, or 2^^16) 
00116            - dividing by implicit 2 (2^^1 for a total of 2^^17), for even addresses
00117            NOTE: 131072 is a valid scale value. It produces byte resolution of addresses
00118          */
00119         lloffset =
00120             ( unsigned long long ) ( ( address - prof->pr_off ) *
00121                                      prof->pr_scale );
00122         indx = ( unsigned long ) ( lloffset >> 17 );
00123     }
00124 
00125     /* confirm addresses within specified range */
00126     if ( address >= prof->pr_off ) {
00127         /* test first for 16-bit buckets; this should be the fast case */
00128         if ( flags & PAPI_PROFIL_BUCKET_16 ) {
00129             if ( ( indx * sizeof ( short ) ) < prof->pr_size ) {
00130                 buf16 = prof->pr_base;
00131                 buf16[indx] =
00132                     ( unsigned short ) ( ( unsigned short ) buf16[indx] +
00133                                          profil_increment( buf16[indx], flags,
00134                                                            excess,
00135                                                            threshold ) );
00136                 PRFDBG( "posix_profil_16() bucket %lu = %u\n", indx,
00137                         buf16[indx] );
00138             }
00139         }
00140         /* next, look for the 32-bit case */
00141         else if ( flags & PAPI_PROFIL_BUCKET_32 ) {
00142             if ( ( indx * sizeof ( int ) ) < prof->pr_size ) {
00143                 buf32 = prof->pr_base;
00144                 buf32[indx] = ( unsigned int ) buf32[indx] +
00145                     ( unsigned int ) profil_increment( buf32[indx], flags,
00146                                                        excess, threshold );
00147                 PRFDBG( "posix_profil_32() bucket %lu = %u\n", indx,
00148                         buf32[indx] );
00149             }
00150         }
00151         /* finally, fall through to the 64-bit case */
00152         else {
00153             if ( ( indx * sizeof ( long long ) ) < prof->pr_size ) {
00154                 buf64 = prof->pr_base;
00155                 buf64[indx] = ( unsigned long long ) buf64[indx] +
00156                     ( unsigned long long ) profil_increment( ( long long )
00157                                                              buf64[indx], flags,
00158                                                              excess,
00159                                                              threshold );
00160                 PRFDBG( "posix_profil_64() bucket %lu = %lld\n", indx,
00161                         buf64[indx] );
00162             }
00163         }
00164     }
00165 }

Here is the call graph for this function:

Here is the caller graph for this function:

inline_static int profil_increment ( long long  value,
int  flags,
long long  excess,
long long  threshold 
)

Definition at line 61 of file extras.c.

00063 {
00064     int increment = 1;
00065 
00066     if ( flags == PAPI_PROFIL_POSIX ) {
00067         return ( 1 );
00068     }
00069 
00070     if ( flags & PAPI_PROFIL_RANDOM ) {
00071         if ( random_ushort(  ) <= ( USHRT_MAX / 4 ) )
00072             return ( 0 );
00073     }
00074 
00075     if ( flags & PAPI_PROFIL_COMPRESS ) {
00076         /* We're likely to ignore the sample if buf[address] gets big. */
00077         if ( random_ushort(  ) < value ) {
00078             return ( 0 );
00079         }
00080     }
00081 
00082     if ( flags & PAPI_PROFIL_WEIGHTED ) {   /* Increment is between 1 and 255 */
00083         if ( excess <= ( long long ) 1 )
00084             increment = 1;
00085         else if ( excess > threshold )
00086             increment = 255;
00087         else {
00088             threshold = threshold / ( long long ) 255;
00089             increment = ( int ) ( excess / threshold );
00090         }
00091     }
00092     return ( increment );
00093 }

Here is the call graph for this function:

Here is the caller graph for this function:

inline_static unsigned short random_ushort ( void   ) 

Definition at line 49 of file extras.c.

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

Here is the caller graph for this function:


Variable Documentation

int _papi_hwi_using_signal[PAPI_NSIG]

Definition at line 368 of file extras.c.

unsigned int _rnum = DEADBEEF [static]

Definition at line 42 of file extras.c.


Generated on 26 Jan 2016 for PAPI by  doxygen 1.6.1