PAPI  5.3.0.0
perf_event_lib.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pe_event_info_t
struct  pe_control_t
struct  pe_context_t

Defines

#define PERF_EVENT_MAX_MPX_COUNTERS   64

Functions

int _pe_set_domain (hwd_control_state_t *ctl, int domain)
int _pe_shutdown_thread (hwd_context_t *ctx)
int _pe_reset (hwd_context_t *ctx, hwd_control_state_t *ctl)
int _pe_write (hwd_context_t *ctx, hwd_control_state_t *ctl, long long *from)
int _pe_read (hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
int _pe_start (hwd_context_t *ctx, hwd_control_state_t *ctl)
int _pe_stop (hwd_context_t *ctx, hwd_control_state_t *ctl)
int _pe_ctl (hwd_context_t *ctx, int code, _papi_int_option_t *option)

Define Documentation

#define PERF_EVENT_MAX_MPX_COUNTERS   64

Definition at line 5 of file perf_event_lib.h.


Function Documentation

int _pe_ctl ( hwd_context_t ctx,
int  code,
_papi_int_option_t option 
)

Definition at line 1249 of file perf_event.c.

{
   int ret;
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
   pe_control_t *pe_ctl = NULL;

   switch ( code ) {
      case PAPI_MULTIPLEX:
       pe_ctl = ( pe_control_t * ) ( option->multiplex.ESI->ctl_state );
       ret = check_permissions( pe_ctl->tid, pe_ctl->cpu, pe_ctl->domain,
                    pe_ctl->granularity,
                    1, pe_ctl->inherit );
           if (ret != PAPI_OK) {
          return ret;
       }

       /* looks like we are allowed, so set multiplexed attribute */
       pe_ctl->multiplexed = 1;
       ret = _pe_update_control_state( pe_ctl, NULL,
                        pe_ctl->num_events, pe_ctx );
       if (ret != PAPI_OK) {
          pe_ctl->multiplexed = 0;
       }
       return ret;

      case PAPI_ATTACH:
       pe_ctl = ( pe_control_t * ) ( option->attach.ESI->ctl_state );
       ret = check_permissions( option->attach.tid, pe_ctl->cpu,
                  pe_ctl->domain, pe_ctl->granularity,
                  pe_ctl->multiplexed,
                    pe_ctl->inherit );
       if (ret != PAPI_OK) {
          return ret;
       }

       pe_ctl->tid = option->attach.tid;

       /* If events have been already been added, something may */
       /* have been done to the kernel, so update */
       ret =_pe_update_control_state( pe_ctl, NULL,
                        pe_ctl->num_events, pe_ctx);

       return ret;

      case PAPI_DETACH:
       pe_ctl = ( pe_control_t *) ( option->attach.ESI->ctl_state );

       pe_ctl->tid = 0;
       return PAPI_OK;

      case PAPI_CPU_ATTACH:
       pe_ctl = ( pe_control_t *) ( option->cpu.ESI->ctl_state );
       ret = check_permissions( pe_ctl->tid, option->cpu.cpu_num,
                    pe_ctl->domain, pe_ctl->granularity,
                    pe_ctl->multiplexed,
                    pe_ctl->inherit );
           if (ret != PAPI_OK) {
           return ret;
       }
       /* looks like we are allowed so set cpu number */

       /* this tells the kernel not to count for a thread   */
       /* should we warn if we try to set both?  perf_event */
       /* will reject it.                                   */
       pe_ctl->tid = -1;

       pe_ctl->cpu = option->cpu.cpu_num;

       return PAPI_OK;

      case PAPI_DOMAIN:
       pe_ctl = ( pe_control_t *) ( option->domain.ESI->ctl_state );
       ret = check_permissions( pe_ctl->tid, pe_ctl->cpu,
                    option->domain.domain,
                    pe_ctl->granularity,
                    pe_ctl->multiplexed,
                    pe_ctl->inherit );
           if (ret != PAPI_OK) {
          return ret;
       }
       /* looks like we are allowed, so set counting domain */
       return _pe_set_domain( pe_ctl, option->domain.domain );

      case PAPI_GRANUL:
       pe_ctl = (pe_control_t *) ( option->granularity.ESI->ctl_state );

       /* FIXME: we really don't support this yet */

           switch ( option->granularity.granularity  ) {
              case PAPI_GRN_PROCG:
              case PAPI_GRN_SYS_CPU:
              case PAPI_GRN_PROC:
           return PAPI_ECMP;

          /* Currently we only support thread and CPU granularity */
              case PAPI_GRN_SYS:
           pe_ctl->granularity=PAPI_GRN_SYS;
           break;

              case PAPI_GRN_THR:
           pe_ctl->granularity=PAPI_GRN_THR;
           break;


              default:
           return PAPI_EINVAL;
       }
           return PAPI_OK;

      case PAPI_INHERIT:
       pe_ctl = (pe_control_t *) ( option->inherit.ESI->ctl_state );
       ret = check_permissions( pe_ctl->tid, pe_ctl->cpu, pe_ctl->domain,
                  pe_ctl->granularity, pe_ctl->multiplexed,
                    option->inherit.inherit );
           if (ret != PAPI_OK) {
          return ret;
       }
       /* looks like we are allowed, so set the requested inheritance */
       if (option->inherit.inherit) {
          /* children will inherit counters */
          pe_ctl->inherit = 1;
       } else {
          /* children won't inherit counters */
          pe_ctl->inherit = 0;
       }
       return PAPI_OK;

      case PAPI_DATA_ADDRESS:
       return PAPI_ENOSUPP;
#if 0
       pe_ctl = (pe_control_t *) (option->address_range.ESI->ctl_state);
       ret = set_default_domain( pe_ctl, option->address_range.domain );
       if ( ret != PAPI_OK ) {
          return ret;
       }
       set_drange( pe_ctx, pe_ctl, option );
       return PAPI_OK;
#endif
      case PAPI_INSTR_ADDRESS:
       return PAPI_ENOSUPP;
#if 0
       pe_ctl = (pe_control_t *) (option->address_range.ESI->ctl_state);
       ret = set_default_domain( pe_ctl, option->address_range.domain );
       if ( ret != PAPI_OK ) {
          return ret;
       }
       set_irange( pe_ctx, pe_ctl, option );
       return PAPI_OK;
#endif

      case PAPI_DEF_ITIMER:
       /* What should we be checking for here?                   */
       /* This seems like it should be OS-specific not component */
       /* specific.                                              */

       return PAPI_OK;

      case PAPI_DEF_MPX_NS:
       /* Defining a given ns per set is not current supported */
       return PAPI_ENOSUPP;

      case PAPI_DEF_ITIMER_NS:
       /* We don't support this... */
       return PAPI_OK;

      default:
       return PAPI_ENOSUPP;
   }
}

Here is the call graph for this function:

int _pe_read ( hwd_context_t ctx,
hwd_control_state_t ctl,
long long **  events,
int  flags 
)

Definition at line 911 of file perf_event.c.

{
   ( void ) flags;           /*unused */
   int i, ret = -1;
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;
   long long papi_pe_buffer[READ_BUFFER_SIZE];
   long long tot_time_running, tot_time_enabled, scale;

   /* On kernels before 2.6.33 the TOTAL_TIME_ENABLED and TOTAL_TIME_RUNNING */
   /* fields are always 0 unless the counter is disabled.  So if we are on   */
   /* one of these kernels, then we must disable events before reading.      */

   /* Elsewhere though we disable multiplexing on kernels before 2.6.34 */
   /* so maybe this isn't even necessary.                               */

   if (bug_sync_read()) {
      if ( pe_ctx->state & PERF_EVENTS_RUNNING ) {
         for ( i = 0; i < pe_ctl->num_events; i++ ) {
        /* disable only the group leaders */
        if ( pe_ctl->events[i].group_leader_fd == -1 ) {
           ret = ioctl( pe_ctl->events[i].event_fd, 
               PERF_EVENT_IOC_DISABLE, NULL );
           if ( ret == -1 ) {
              PAPIERROR("ioctl(PERF_EVENT_IOC_DISABLE) "
               "returned an error: ", strerror( errno ));
              return PAPI_ESYS;
           }
        }
     }
      }
   }


   /* Handle case where we are multiplexing */
   if (pe_ctl->multiplexed) {

      /* currently we handle multiplexing by having individual events */
      /* so we read from each in turn.                                */

      for ( i = 0; i < pe_ctl->num_events; i++ ) {

         ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer,
            sizeof ( papi_pe_buffer ) );
         if ( ret == -1 ) {
        PAPIERROR("read returned an error: ", strerror( errno ));
        return PAPI_ESYS;
     }

     /* We should read 3 64-bit values from the counter */
     if (ret<(signed)(3*sizeof(long long))) {
        PAPIERROR("Error!  short read!\n");
        return PAPI_ESYS;
     }

         SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
            pe_ctl->events[i].event_fd,
        (long)pe_ctl->tid, pe_ctl->cpu, ret);
         SUBDBG("read: %lld %lld %lld\n",papi_pe_buffer[0],
            papi_pe_buffer[1],papi_pe_buffer[2]);

         tot_time_enabled = papi_pe_buffer[1];
         tot_time_running = papi_pe_buffer[2];

         SUBDBG("count[%d] = (papi_pe_buffer[%d] %lld * "
        "tot_time_enabled %lld) / tot_time_running %lld\n",
        i, 0,papi_pe_buffer[0],
        tot_time_enabled,tot_time_running);

         if (tot_time_running == tot_time_enabled) {
        /* No scaling needed */
        pe_ctl->counts[i] = papi_pe_buffer[0];
         } else if (tot_time_running && tot_time_enabled) {
        /* Scale factor of 100 to avoid overflows when computing */
        /*enabled/running */

        scale = (tot_time_enabled * 100LL) / tot_time_running;
        scale = scale * papi_pe_buffer[0];
        scale = scale / 100LL;
        pe_ctl->counts[i] = scale;
     } else {
       /* This should not happen, but Phil reports it sometime does. */
        SUBDBG("perf_event kernel bug(?) count, enabled, "
           "running: %lld, %lld, %lld\n",
           papi_pe_buffer[0],tot_time_enabled,
           tot_time_running);

        pe_ctl->counts[i] = papi_pe_buffer[0];
     }
      }
   }

   /* Handle cases where we cannot use FORMAT GROUP */
   else if (bug_format_group() || pe_ctl->inherit) {

      /* we must read each counter individually */
      for ( i = 0; i < pe_ctl->num_events; i++ ) {

         ret = read( pe_ctl->events[i].event_fd, papi_pe_buffer,
            sizeof ( papi_pe_buffer ) );
         if ( ret == -1 ) {
        PAPIERROR("read returned an error: ", strerror( errno ));
        return PAPI_ESYS;
     }

     /* we should read one 64-bit value from each counter */
     if (ret!=sizeof(long long)) {
        PAPIERROR("Error!  short read!\n");
        PAPIERROR("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
           pe_ctl->events[i].event_fd,
           (long)pe_ctl->tid, pe_ctl->cpu, ret);
        return PAPI_ESYS;
     }

         SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
            pe_ctl->events[i].event_fd, (long)pe_ctl->tid,
        pe_ctl->cpu, ret);
         SUBDBG("read: %lld\n",papi_pe_buffer[0]);

     pe_ctl->counts[i] = papi_pe_buffer[0];
      }
   }


   /* Handle cases where we are using FORMAT_GROUP   */
   /* We assume only one group leader, in position 0 */

   else {
      if (pe_ctl->events[0].group_leader_fd!=-1) {
     PAPIERROR("Was expecting group leader!\n");
      }

      ret = read( pe_ctl->events[0].event_fd, papi_pe_buffer,
          sizeof ( papi_pe_buffer ) );

      if ( ret == -1 ) {
     PAPIERROR("read returned an error: ", strerror( errno ));
     return PAPI_ESYS;
      }

      /* we read 1 64-bit value (number of events) then     */
      /* num_events more 64-bit values that hold the counts */
      if (ret<(signed)((1+pe_ctl->num_events)*sizeof(long long))) {
     PAPIERROR("Error! short read!\n");
     return PAPI_ESYS;
      }

      SUBDBG("read: fd: %2d, tid: %ld, cpu: %d, ret: %d\n",
         pe_ctl->events[0].event_fd,
         (long)pe_ctl->tid, pe_ctl->cpu, ret);
      {
     int j;
     for(j=0;j<ret/8;j++) {
            SUBDBG("read %d: %lld\n",j,papi_pe_buffer[j]);
     }
      }

      /* Make sure the kernel agrees with how many events we have */
      if (papi_pe_buffer[0]!=pe_ctl->num_events) {
     PAPIERROR("Error!  Wrong number of events!\n");
     return PAPI_ESYS;
      }

      /* put the count values in their proper location */
      for(i=0;i<papi_pe_buffer[0];i++) {
         pe_ctl->counts[i] = papi_pe_buffer[1+i];
      }
   }


   /* If we disabled the counters due to the sync_read_bug(), */
   /* then we need to re-enable them now.                     */
   if (bug_sync_read()) {
      if ( pe_ctx->state & PERF_EVENTS_RUNNING ) {
         for ( i = 0; i < pe_ctl->num_events; i++ ) {
        if ( pe_ctl->events[i].group_leader_fd == -1 ) {
           /* this should refresh any overflow counters too */
           ret = ioctl( pe_ctl->events[i].event_fd,
                PERF_EVENT_IOC_ENABLE, NULL );
           if ( ret == -1 ) {
              /* Should never happen */
              PAPIERROR("ioctl(PERF_EVENT_IOC_ENABLE) returned an error: ",
                strerror( errno ));
              return PAPI_ESYS;
           }
        }
     }
      }
   }

   /* point PAPI to the values we read */
   *events = pe_ctl->counts;

   return PAPI_OK;
}

Here is the call graph for this function:

int _pe_reset ( hwd_context_t ctx,
hwd_control_state_t ctl 
)

Definition at line 856 of file perf_event.c.

{
   int i, ret;
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;

   ( void ) ctx;             /*unused */

   /* We need to reset all of the events, not just the group leaders */
   for( i = 0; i < pe_ctl->num_events; i++ ) {
      ret = ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_RESET, NULL );
      if ( ret == -1 ) {
     PAPIERROR("ioctl(%d, PERF_EVENT_IOC_RESET, NULL) "
           "returned error, Linux says: %s",
           pe_ctl->events[i].event_fd, strerror( errno ) );
     return PAPI_ESYS;
      }
   }

   return PAPI_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int _pe_set_domain ( hwd_control_state_t ctl,
int  domain 
)

Definition at line 817 of file perf_event.c.

{

   int i;
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;

   SUBDBG("old control domain %d, new domain %d\n",
      pe_ctl->domain,domain);

   pe_ctl->domain = domain;

   /* Force the domain on all events */
   for( i = 0; i < pe_ctl->num_events; i++ ) {
      pe_ctl->events[i].attr.exclude_user =
                    !( pe_ctl->domain & PAPI_DOM_USER );
      pe_ctl->events[i].attr.exclude_kernel =
            !( pe_ctl->domain & PAPI_DOM_KERNEL );
      pe_ctl->events[i].attr.exclude_hv =
            !( pe_ctl->domain & PAPI_DOM_SUPERVISOR );
   }
   return PAPI_OK;
}

Here is the caller graph for this function:

Definition at line 842 of file perf_event.c.

{
    pe_context_t *pe_ctx = ( pe_context_t *) ctx;

    pe_ctx->initialized=0;

    return PAPI_OK;
}
int _pe_start ( hwd_context_t ctx,
hwd_control_state_t ctl 
)

Definition at line 1110 of file perf_event.c.

{
   int ret;
   int i;
   int did_something = 0;
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;

   /* Reset the counters first.  Is this necessary? */
   ret = _pe_reset( pe_ctx, pe_ctl );
   if ( ret ) {
      return ret;
   }

   /* Enable all of the group leaders                */
   /* All group leaders have a group_leader_fd of -1 */
   for( i = 0; i < pe_ctl->num_events; i++ ) {
      if (pe_ctl->events[i].group_leader_fd == -1) {
     SUBDBG("ioctl(enable): fd: %d\n", pe_ctl->events[i].event_fd);
     ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_ENABLE, NULL) ;

     /* ioctls always return -1 on failure */
         if (ret == -1) {
            PAPIERROR("ioctl(PERF_EVENT_IOC_ENABLE) failed.\n");
            return PAPI_ESYS;
     }

     did_something++;
      }
   }

   if (!did_something) {
      PAPIERROR("Did not enable any counters.\n");
      return PAPI_EBUG;
   }

   pe_ctx->state |= PERF_EVENTS_RUNNING;

   return PAPI_OK;

}

Here is the call graph for this function:

int _pe_stop ( hwd_context_t ctx,
hwd_control_state_t ctl 
)

Definition at line 1154 of file perf_event.c.

{

   int ret;
   int i;
   pe_context_t *pe_ctx = ( pe_context_t *) ctx;
   pe_control_t *pe_ctl = ( pe_control_t *) ctl;

   /* Just disable the group leaders */
   for ( i = 0; i < pe_ctl->num_events; i++ ) {
      if ( pe_ctl->events[i].group_leader_fd == -1 ) {
     ret=ioctl( pe_ctl->events[i].event_fd, PERF_EVENT_IOC_DISABLE, NULL);
     if ( ret == -1 ) {
        PAPIERROR( "ioctl(%d, PERF_EVENT_IOC_DISABLE, NULL) "
               "returned error, Linux says: %s",
               pe_ctl->events[i].event_fd, strerror( errno ) );
        return PAPI_EBUG;
     }
      }
   }

   pe_ctx->state &= ~PERF_EVENTS_RUNNING;

   return PAPI_OK;
}

Here is the call graph for this function:

int _pe_write ( hwd_context_t ctx,
hwd_control_state_t ctl,
long long *  from 
)

Definition at line 881 of file perf_event.c.

{
   ( void ) ctx;             /*unused */
   ( void ) ctl;             /*unused */
   ( void ) from;            /*unused */
   /*
    * Counters cannot be written.  Do we need to virtualize the
    * counters so that they can be written, or perhaps modify code so that
    * they can be written? FIXME ?
    */

    return PAPI_ENOSUPP;
}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines