Skip to content

Commit

Permalink
Add simultaneous_group_overflow test
Browse files Browse the repository at this point in the history
This test does not work at all like I think it should.

The mysteries of perf_event.
  • Loading branch information
deater committed Sep 14, 2012
1 parent a38fcc2 commit b51f3cb
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
14 September 2012
+ Add simultaneous overflows test

21 August 2012
+ Add check_reset_mpx test

Expand Down
1 change: 1 addition & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ echo "* Checking basic perf_event functionality"
./validation/inherit
./validation/inherit_stat
./validation/enable_on_exec
./validation/simultaneous_group_overflow

echo
echo "* Checking bugs that PAPI has to work around"
Expand Down
21 changes: 18 additions & 3 deletions validation/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ all: \
inherit_stat \
non-existent \
offcore_response \
simultaneous_group_overflow \
rdpmc_support \
rdpmc_validation \
simple_overflow_leader \
Expand Down Expand Up @@ -178,6 +179,20 @@ rdpmc_validation.o: rdpmc_validation.c

###

simultaneous_group_overflow: simultaneous_group_overflow.o ../lib/test_utils.o \
../lib/perf_helpers.o \
../lib/matrix_multiply.o
$(CC) $(LFLAGS) -o simultaneous_group_overflow simultaneous_group_overflow.o \
../lib/test_utils.o \
../lib/perf_helpers.o \
../lib/matrix_multiply.o

simultaneous_group_overflow.o: simultaneous_group_overflow.c
$(CC) $(CFLAGS) -c simultaneous_group_overflow.c


###

simple_overflow_leader: simple_overflow_leader.o ../lib/test_utils.o \
../lib/perf_helpers.o \
../lib/matrix_multiply.o
Expand All @@ -189,6 +204,8 @@ simple_overflow_leader: simple_overflow_leader.o ../lib/test_utils.o \
simple_overflow_leader.o: simple_overflow_leader.c
$(CC) $(CFLAGS) -c simple_overflow_leader.c



###

simple_overflow_sibling: simple_overflow_sibling.o ../lib/test_utils.o \
Expand All @@ -214,11 +231,9 @@ clean:
inherit_stat \
non-existent \
offcore_response \
simultaneous_group_overflow \
rdpmc_support \
rdpmc_validation \
simple_overflow_leader \
simple_overflow_sibling




291 changes: 291 additions & 0 deletions validation/simultaneous_group_overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
/* overflow_two_events.c */
/* by Vince Weaver [email protected] */

/* Test to see if we can sample on two events at once */
/* within the same group. */

/* the answer seems to be no, but it's complicated */
/* this test tries a PAPI-esque way of doing things */
/* in this case we disable the event in the handler */
/* but in the group case if it's the group leader */
/* everything gets disabled, but refresh only */
/* restarts the one event. */

#define _GNU_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <fcntl.h>

#include <errno.h>

#include <signal.h>

#include <sys/mman.h>

#include <sys/ioctl.h>
#include <asm/unistd.h>
#include <sys/prctl.h>

#include "perf_event.h"
#include "test_utils.h"
#include "perf_helpers.h"
#include "matrix_multiply.h"

#define NUM_EVENTS 2

struct {
int fd;
int overflows;
int individual_overflow;
} events[NUM_EVENTS];

struct {
char name[BUFSIZ];
int type;
int config;
int period;
} event_values[NUM_EVENTS] = {
{ "perf::instructions", PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, 1000000},
{ "perf::instructions", PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, 2000000},
};



static void our_handler(int signum,siginfo_t *info, void *uc) {

int ret,i;
int fd = info->si_fd;

// ret=ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);

for(i=0;i<NUM_EVENTS;i++) {
if (events[i].fd==fd) {
events[i].overflows++;
break;
}
}

if (i==NUM_EVENTS) printf("fd %d not found\n",fd);

//printf("fd: %d overflowed\n",fd);
ret=ioctl(fd, PERF_EVENT_IOC_REFRESH,1);

(void) ret;

}



int main(int argc, char** argv) {

int ret,quiet,i,matches=0;

struct perf_event_attr pe;

struct sigaction sa;
void *our_mmap;
char test_string[]="Testing multiple event overflow within group...";

for(i=0;i<NUM_EVENTS;i++) {
events[i].fd=-1;
events[i].overflows=0;
}

quiet=test_quiet();

/*********************************************************************/
if (!quiet) printf("This tests simultaneous overflow within group.\n");
/*********************************************************************/

/*****************************/
/* set up our signal handler */
/*****************************/

memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = our_handler;
sa.sa_flags = SA_SIGINFO;

if (sigaction( SIGIO, &sa, NULL) < 0) {
fprintf(stderr,"Error setting up signal handler\n");
exit(1);
}

/***********************/
/* get expected counts */
/***********************/

for(i=0;i<NUM_EVENTS;i++) {
memset(&pe,0,sizeof(struct perf_event_attr));

pe.type=event_values[i].type;
pe.size=sizeof(struct perf_event_attr);
pe.config=event_values[i].config;
pe.sample_period=event_values[i].period;
pe.sample_type=0;
pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID;
pe.disabled=1;
pe.pinned=0;
pe.exclude_kernel=1;
pe.exclude_hv=1;
pe.wakeup_events=0;

events[i].fd=perf_event_open(&pe,0,-1,-1,0);
if (events[i].fd<0) {
fprintf(stderr,"Error opening leader %llx\n",pe.config);
exit(1);
}

/* on older kernels you need this even if you don't use it */
our_mmap=mmap(NULL, (1+1)*4096,
PROT_READ|PROT_WRITE, MAP_SHARED, events[i].fd, 0);

fcntl(events[i].fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
fcntl(events[i].fd, F_SETSIG, SIGIO);
fcntl(events[i].fd, F_SETOWN,getpid());

ioctl(events[i].fd, PERF_EVENT_IOC_RESET, 0);

if (!quiet) {
printf("Testing matrix matrix multiply\n");
printf("\tEvent %s with period %d\n",
event_values[i].name,
event_values[i].period);
}

ret=ioctl(events[i].fd, PERF_EVENT_IOC_ENABLE,0);

printf("\t");
naive_matrix_multiply(quiet);

ret=ioctl(events[i].fd, PERF_EVENT_IOC_DISABLE,0);

if (!quiet) {
printf("\tfd %d overflows: %d (%s/%d)\n",
events[i].fd,events[i].overflows,
event_values[i].name,
event_values[i].period);
}
if (events[i].overflows==0) {
if (!quiet) printf("No overflow events generated.\n");
test_fail(test_string);
}

close(events[i].fd);

events[i].individual_overflow=events[i].overflows;

events[i].overflows=0;
events[i].fd=-1;
}


/**********************************/
/* test overflow for both */
/**********************************/

if (!quiet) {
printf("Testing matrix matrix multiply\n");
for(i=0;i<NUM_EVENTS;i++) {
printf("\tEvent %s with period %d\n",
event_values[i].name,
event_values[i].period);
}
}

for(i=0;i<NUM_EVENTS;i++) {

memset(&pe,0,sizeof(struct perf_event_attr));

pe.type=event_values[i].type;
pe.size=sizeof(struct perf_event_attr);
pe.config=event_values[i].config;
pe.sample_period=event_values[i].period;
pe.sample_type=PERF_SAMPLE_ID;
pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID;
pe.disabled=(i==0)?1:0;
pe.pinned=(i==0)?1:0;
pe.exclude_kernel=1;
pe.exclude_hv=1;
pe.wakeup_events=0;

events[i].fd=perf_event_open(&pe,0,-1,(i==0)?-1:events[0].fd,0);
if (events[i].fd<0) {
fprintf(stderr,"Error opening leader %llx\n",pe.config);
test_fail(test_string);
}

/* on older kernels you need this even if you don't use it */
our_mmap=mmap(NULL, (1+1)*4096,
PROT_READ|PROT_WRITE, MAP_SHARED, events[i].fd, 0);

fcntl(events[i].fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
fcntl(events[i].fd, F_SETSIG, SIGIO);
fcntl(events[i].fd, F_SETOWN,getpid());

ioctl(events[i].fd, PERF_EVENT_IOC_RESET, 0);
}

ret=ioctl(events[0].fd, PERF_EVENT_IOC_ENABLE,0);

if (ret<0) {
if (!quiet) fprintf(stderr,"Error with PERF_EVENT_IOC_ENABLE of group leader: "
"%d %s\n",errno,strerror(errno));
test_fail(test_string);
}

printf("\t");
naive_matrix_multiply(quiet);

ret=ioctl(events[0].fd, PERF_EVENT_IOC_DISABLE,0);

for(i=0;i<NUM_EVENTS;i++) {
if (!quiet) {
printf("\tfd %d overflows: %d (%s/%d)\n",
events[i].fd,events[i].overflows,
event_values[i].name,event_values[i].period);
}
}

for(i=0;i<NUM_EVENTS;i++) {
if (events[i].overflows==0) {
if (!quiet) printf("No overflow events generated.\n");
test_fail(test_string);
}
}

for(i=0;i<NUM_EVENTS;i++) {
close(events[i].fd);
}


/* test validity */
for(i=0;i<NUM_EVENTS;i++) {

if (!quiet) fprintf(stderr,"Event %s/%d Expected %d Got %d\n",
event_values[i].name, event_values[i].period,
events[i].individual_overflow,events[i].overflows);


if (events[i].individual_overflow!=events[i].overflows) {
}
else{
matches++;
}
}

if (matches==NUM_EVENTS) {

fprintf(stderr,"Test unexpectedly worked!\n");
test_fail(test_string);
}


test_pass(test_string);

return 0;
}

0 comments on commit b51f3cb

Please sign in to comment.