<commit_before>/****************************/
/* THIS IS OPEN SOURCE CODE */
/****************************/

/* 
* File:    extras.c
* CVS:     $Id$
* Author:  <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
*/

/* This file contains portable routines to do things that we wish the
vendors did in the kernel extensions or performance libraries. */

/* It also contains a new section at the end with Windows routines
 to emulate standard stuff found in Unix/Linux, but not Windows! */

#include "papi.h"
#include "papi_internal.h"
#include "papi_vector.h"
#include "papi_vector_redefine.h"

/*******************/
/* BEGIN EXTERNALS */
/*******************/

extern papi_mdi_t _papi_hwi_system_info;

#ifdef ANY_THREAD_GETS_SIGNAL
extern void _papi_hwi_lookup_thread_symbols(void);
extern int (*_papi_hwi_thread_kill_fn) (int, int);
#endif

/*****************/
/* END EXTERNALS */
/*****************/

/****************/
/* BEGIN LOCALS */
/****************/

static unsigned int _rnum = DEADBEEF;

/**************/
/* END LOCALS */
/**************/

extern unsigned long int (*_papi_hwi_thread_id_fn) (void);

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


/* compute the amount by which to increment the bucket.
   value is the current value of the bucket
   this routine is used by all three profiling cases
   it is inlined for speed
*/
inline_static int profil_increment(long_long value,
                            int flags, long_long excess,
                            long_long threshold)
{
   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);
}


static void posix_profil(caddr_t address, PAPI_sprofil_t * prof,
                         int flags, long_long excess, long_long threshold)
{
   unsigned short *buf16;
   unsigned int *buf32;
   u_long_long *buf64;
   unsigned long indx;
   u_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 = ((u_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] += 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] += 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] += profil_increment(buf64[indx], flags, excess, threshold);
            PRFDBG("posix_profil_64() bucket %lu = %lld\n", indx, buf64[indx]);
         }
      }
   }
}

void _papi_hwi_dispatch_profile(EventSetInfo_t * ESI, unsigned long pc,
                      long_long over, int profile_index)
{
  EventSetProfileInfo_t *profile = &ESI->profile;
  PAPI_sprofil_t *sprof;
  unsigned long offset = 0;
  unsigned long best_offset = 0;
  int count;
  int best_index = -1;
  int i;

  PRFDBG("handled IP 0x%lx\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]);
}

/* if isHardware is true, then the processor is using hardware overflow,
   else it is using software overflow. Use this parameter instead of 
   _papi_hwi_system_info.supports_hw_overflow is in CRAY some processors
   may use hardware overflow, some may use software overflow.

   overflow_bit: if the substrate can get the overflow bit when overflow
                 occurs, then this should be passed by the substrate;

   If both genOverflowBit and isHardwareSupport are true, that means
     the substrate doesn't know how to get the overflow bit from the
     kernel directly, so we generate the overflow bit in this function 
    since this function can access the ESI->overflow struct;
   (The substrate can only set genOverflowBit parameter to true if the<commit_msg>add type casting from caddr_t to unsined long for new changes made to profile<commit_after>/****************************/
/* THIS IS OPEN SOURCE CODE */
/****************************/

/* 
* File:    extras.c
* CVS:     $Id$
* Author:  <NAME>
*          <EMAIL>
* Mods:    dan terpstra
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
* Mods:    <NAME>
*          <EMAIL>
*/

/* This file contains portable routines to do things that we wish the
vendors did in the kernel extensions or performance libraries. */

/* It also contains a new section at the end with Windows routines
 to emulate standard stuff found in Unix/Linux, but not Windows! */

#include "papi.h"
#include "papi_internal.h"
#include "papi_vector.h"
#include "papi_vector_redefine.h"

/*******************/
/* BEGIN EXTERNALS */
/*******************/

extern papi_mdi_t _papi_hwi_system_info;

#ifdef ANY_THREAD_GETS_SIGNAL
extern void _papi_hwi_lookup_thread_symbols(void);
extern int (*_papi_hwi_thread_kill_fn) (int, int);
#endif

/*****************/
/* END EXTERNALS */
/*****************/

/****************/
/* BEGIN LOCALS */
/****************/

static unsigned int _rnum = DEADBEEF;

/**************/
/* END LOCALS */
/**************/

extern unsigned long int (*_papi_hwi_thread_id_fn) (void);

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


/* compute the amount by which to increment the bucket.
   value is the current value of the bucket
   this routine is used by all three profiling cases
   it is inlined for speed
*/
inline_static int profil_increment(long_long value,
                            int flags, long_long excess,
                            long_long threshold)
{
   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);
}


static void posix_profil(unsigned long address, PAPI_sprofil_t * prof,
                         int flags, long_long excess, long_long threshold)
{
   unsigned short *buf16;
   unsigned int *buf32;
   u_long_long *buf64;
   unsigned long indx;
   u_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 = ((u_long_long)(address - (unsigned long)prof->pr_off)) * prof->pr_scale;
      indx = (unsigned long)(lloffset >> 17);
   }

   /* confirm addresses within specified range */
   if (address >= (unsigned long)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] += 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] += 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] += profil_increment(buf64[indx], flags, excess, threshold);
            PRFDBG("posix_profil_64() bucket %lu = %lld\n", indx, buf64[indx]);
         }
      }
   }
}

void _papi_hwi_dispatch_profile(EventSetInfo_t * ESI, unsigned long pc,
                      long_long over, int profile_index)
{
  EventSetProfileInfo_t *profile = &ESI->profile;
  PAPI_sprofil_t *sprof;
  unsigned long offset = 0;
  unsigned long best_offset = 0;
  int count;
  int best_index = -1;
  int i;

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

  sprof = profile->prof[profile_index];
  count = profile->count[profile_index];
    
  for (i = 0; i < count; i++)
  {
      offset = (unsigned long)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]);
}

/* if isHardware is true, then the processor is using hardware overflow,
   else it is using software overflow. Use this parameter instead of 
   _papi_hwi_system_info.supports_hw_overflow is in CRAY some processors
   may use hardware overflow, some may use software overflow.

   overflow_bit: if the substrate can get the overflow bit when overflow
                 occurs, then this should be passed by the substrate;

   If both genOverflowBit and isHardwareSupport are true, that means
     the substrate doesn't know how to get the overflow bit from the
     kernel directly, so we generate the overflow bit in this function 
    since this function can access the ESI->overflow struct;
   (The substrate can only set genOverflowBit parameter to true if the
{'fraction_non_alphanumeric': 0.1313739661125833, 'fraction_numerical': 0.018469445113627237, 'mean_word_length': 2.592154600519181, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 66, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1817888', 'n_tokens_mistral': 4152, 'n_tokens_neox': 3917, 'n_words': 1217}