Skip to content

Commit

Permalink
Add multiplexing test
Browse files Browse the repository at this point in the history
This checks if multiplexing works.  Prior to 2.6.34 this
did not work as expected.
  • Loading branch information
deater committed Aug 20, 2012
1 parent 41c880e commit d46d5d4
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
20 August 2012
+ Add multiplexing test

16 August 2012
+ Add reset_leader test

Expand Down
31 changes: 25 additions & 6 deletions bugs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ CFLAGS = -Wall -O2 -I../include
LFLAGS =

all: \
read_group_attached \
check_schedulability \
check_multiplexing \
check_papi_multiplexing \
check_schedulability \
nmi_watchdog_group_leader \
read_group_attached \
sync_read_required \
nmi_watchdog_group_leader


#

Expand Down Expand Up @@ -62,6 +64,21 @@ check_papi_multiplexing: check_papi_multiplexing.o \
check_papi_multiplexing.o: check_papi_multiplexing.c
$(CC) $(CFLAGS) -c check_papi_multiplexing.c

###

check_multiplexing: check_multiplexing.o \
../lib/perf_helpers.o \
../lib/test_utils.o \
../lib/instructions_testcode.o
$(CC) $(LFLAGS) -o check_multiplexing check_multiplexing.o \
../lib/perf_helpers.o \
../lib/test_utils.o \
../lib/instructions_testcode.o

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


###

sync_read_required: sync_read_required.o \
Expand Down Expand Up @@ -92,10 +109,12 @@ nmi_watchdog_group_leader.o: nmi_watchdog_group_leader.c

clean:
rm -f *~ *.o \
read_group_attached \
check_schedulability \
check_multiplexing \
check_papi_multiplexing \
check_schedulability \
nmi_watchdog_group_leader \
read_group_attached \
sync_read_required \
nmi_watchdog_group_leader



205 changes: 205 additions & 0 deletions bugs/check_multiplexing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/* check_multiplexing.c */
/* by Vince Weaver vweaver1 _at_ eecs.utk.edu */

/* Prior to 2.6.34 perf_event multiplexing was unreliable */
/* The values were not updated properly. */
/* This was probably fixed by */
/* 45e16a6834b6af098702e5ea6c9a40de42ff77d8 */


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

#include <unistd.h>
#include <errno.h>

#include <sys/mman.h>

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

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

#define NUM_EVENTS 10

int fd[NUM_EVENTS];
long long events[NUM_EVENTS]={
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
};

long long base_results[NUM_EVENTS][3];
long long mpx_results[NUM_EVENTS][3];
long long scaled_results[NUM_EVENTS];
long long scale;
double error[NUM_EVENTS];
int bad_error=0;

int test_routine(void) {

int i,result;

for(i=0;i<500;i++) {
result=instructions_million();
}

return result;
}

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

int ret,quiet,i;

struct perf_event_attr pe;

char test_string[]="Testing if multiplexing works...";

quiet=test_quiet();

if (!quiet) {
printf("Before 2.6.34 the values returned when multiplexing\n");
printf(" were not reliable and could result in wrong results.\n");
}

/* setup all 10 counters */

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

memset(&pe,0,sizeof(struct perf_event_attr));
pe.type=PERF_TYPE_HARDWARE;
pe.size=sizeof(struct perf_event_attr);
pe.config=events[i];
pe.disabled=1;
pe.exclude_kernel=1;
pe.exclude_hv=1;
pe.read_format=PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;

arch_adjust_domain(&pe,quiet);

fd[i]=perf_event_open(&pe,0,-1,-1,0);
if (fd[i]<0) {
fprintf(stderr,"Failed adding mpx event %d %s\n",i,strerror(errno));
test_fail(test_string);
return -1;
}
}

/*************************************************/
/* Collect results for each counter individually */
/*************************************************/

for(i=0;i<NUM_EVENTS;i++) {
ret=ioctl(fd[i], PERF_EVENT_IOC_ENABLE,0);
if (ret<0) {
fprintf(stderr,"Error starting event %d\n",i);
}

test_routine();

ret=ioctl(fd[i], PERF_EVENT_IOC_DISABLE,0);
if (ret<0) {
fprintf(stderr,"Error stopping event %d\n",i);
}

ret=read(fd[i],&base_results[i],3*sizeof(long long));
if (ret<3*sizeof(long long)) {
fprintf(stderr,"Event %d unexpected read size %d\n",i,ret);
test_fail(test_string);
}
if (base_results[i][1]!=base_results[i][2]) {
fprintf(stderr,"Event %d running %lld != %lld base\n",
i,base_results[i][1],base_results[i][2]);
test_fail(test_string);
}

}

/*************************************************/
/* Collect multiplexed results */
/*************************************************/

for(i=0;i<NUM_EVENTS;i++) {
ret=ioctl(fd[i], PERF_EVENT_IOC_RESET,0);
if (ret<0) {
fprintf(stderr,"Error starting event %d\n",i);
}
}

for(i=0;i<NUM_EVENTS;i++) {
ret=ioctl(fd[i], PERF_EVENT_IOC_ENABLE,0);
if (ret<0) {
fprintf(stderr,"Error starting event %d\n",i);
}
}


test_routine();

for(i=0;i<NUM_EVENTS;i++) {
ret=ioctl(fd[i], PERF_EVENT_IOC_DISABLE,0);
if (ret<0) {
fprintf(stderr,"Error stopping event %d\n",i);
}
}


for(i=0;i<NUM_EVENTS;i++) {
ret=read(fd[i],&mpx_results[i],3*sizeof(long long));
if (ret<3*sizeof(long long)) {
fprintf(stderr,"Event %d unexpected read size %d\n",i,ret);
test_fail(test_string);
}

scale = (mpx_results[i][1] * 100LL) / mpx_results[i][2];
scale = scale * mpx_results[i][0];
scale = scale / 100LL;
scaled_results[i] = scale;

}

for(i=0;i<NUM_EVENTS;i++) {
error[i]=((double)base_results[i][0] - (double)scaled_results[i])/
(double)base_results[i][0];
error[i]*=100.0;
if ((error[i]>10.0) || (error[i]<-10.0)) {
bad_error++;
}

}

if (!quiet) {
printf("Event\tTotalCount\tRawCount\tScaledCount\tError\n");
for(i=0;i<NUM_EVENTS;i++) {

printf("%d\t%lld\t%lld\t%lld\t%.2f%%\n",i,
base_results[i][0],mpx_results[i][0],scaled_results[i],
error[i]);

}
}

if (bad_error>0) {
fprintf(stderr,"Error on %d events is too high.\n",bad_error);
test_fail(test_string);
}


test_pass(test_string);

return 0;
}

1 change: 1 addition & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ echo "* Checking bugs that PAPI has to work around"
./bugs/check_schedulability
./bugs/check_papi_multiplexing
./bugs/nmi_watchdog_group_leader
./bugs/check_multiplexing

echo
echo "* Checking bugs that can silently produce wrong results"
Expand Down

0 comments on commit d46d5d4

Please sign in to comment.