forked from deater/perf_event_tests
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add simultaneous_group_overflow test
This test does not work at all like I think it should. The mysteries of perf_event.
- Loading branch information
Showing
4 changed files
with
313 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|