|
PAPI
5.3.0.0
|

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 PERF_EVENT_MAX_MPX_COUNTERS 64 |
Definition at line 5 of file perf_event_lib.h.
| 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;
}
}

| 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;
}

| 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;
}


| 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;
}

| int _pe_shutdown_thread | ( | hwd_context_t * | ctx | ) |
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;
}

| 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;
}

| 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;
}