196 lines · 4.5 KB · C
RawDownload
 /*                  pong.c Generic Benchmark code *               Dave Turner - Ames Lab - July of 1994+++ * *  Most Unix timers can't be trusted for very short times, so take this *  into account when looking at the results.  This code also only times *  a single message passing event for each size, so the results may vary *  between runs.  For more accurate measurements, grab NetPIPE from *  http://www.scl.ameslab.gov/ . */#include "rompi.h"//#include <asm/io.h>/* fucking useless include files! */unsigned long readl(unsigned long *l){	volatile unsigned long *ll = (volatile unsigned long *)l;	return *ll;} void writel(unsigned long new, unsigned long *l){	volatile unsigned long *ll = (volatile unsigned long *)l;	*ll = new;} typedef uvlong ticks; static __inline__ ticks getticks(void){	unsigned int tbl, tbu0, tbu1; 	do {		__asm__ __volatile__ ("mftbu %0" : "=r"(tbu0));		__asm__ __volatile__ ("mftb %0" : "=r"(tbl));		__asm__ __volatile__ ("mftbu %0" : "=r"(tbu1));	} while (tbu0 != tbu1); 	return (((unsigned long long)tbu0) << 32) | tbl;} static __inline__ void mb(void){	__asm__ __volatile__ ("mbar\n");} uvlongmynsec(void){	uvlong t;	static int fd = -1;	extern int pread(int, void *, int, unsigned long long); 	if (fd < 0) {		fd = open("/dev/bintime", 0);		if (fd < 0)			panic("Can't open /dev/bintime");	} 	pread(fd, &t, sizeof(t), 0ULL);	return t;} /* just test the kernel-based fast inject mechanism. Let's hope  * it's not going to require we drain it all. Because we're not going to.  */intmain (int argc, char **argv){	int cfd;  	vlong start, end;	int ctlfd;	char ctlcmd[128]; 	int amt;	/* the wiring is crucial. We only got to about 2.9 microseconds 	 * per send without wiring. With wiring, we got to 1.165 microseconds	 * per send. What is likely going on is inj interrupts taking time	 * and slowing down the rest of the work. 	 */	char wire[32];	int wlen;	int core = 0;	int num = 1024, i;	int role;	u8int *coord;	unsigned long *l;    	unsigned char *data;	struct AmRing *amr;	unsigned long amrbase;	    	/* reguire our ID */	if (argc < 2) {		print("%s 0-or-1 [core (default %d) [num-iter (default %d)]]\n", argv[0], core, num);		exit(1);	}	role = strtol(argv[1], 0, 0);	if (argc > 2) {		core = strtoul(argv[2], 0, 0);	}	if (argc > 3) {		num = strtoul(argv[3], 0, 0);	} 	/* wire us to core 'core' */	sprintf(ctlcmd, "/proc/%d/ctl", getpid());	print("ctlcmd is %s\n", ctlcmd);	ctlfd = open(ctlcmd, 2);	print("ctlfd  is %d\n", ctlfd);	if (ctlfd < 0) {		perror(ctlcmd);		exit(1);	}	sprintf(wire, "wired %d", core);	wlen = strlen(wire);	if (write(ctlfd, wire, wlen) < wlen) {		perror(wire);		exit(1);	} 	/* set up amr  ... just make the base the next page. */	amrbase = (unsigned int) malloc(2*1024*1024);	print("amrbase is %#x", amrbase);	amrbase = (unsigned int) malloc(2*1024*1024);	print("amrbase is %#x", amrbase);	amrbase = (amrbase+255)&(~0xff);	amr = (void *)amrbase;	print("amr is %p\n", amr);	memset(amr, 0, sizeof(*amr));	amr->base = (void *)&amr[1];	amr->size = 1 << 20;	for (i = 0, l = (unsigned long *)amr->base; i < amr->size/sizeof(unsigned long); i++)		l[i] = 0xdeadbeef + role;			coord = malloc(1024);	data = malloc(1024);	print("coord %p data %p\n", coord, malloc);	/* moved here so we can easily test some things on IO nodes	 * after CN have all crashed :-)	 */	cfd = open("/dev/torusctl", 2);	if (cfd < 0) {		perror("cfd");		exit(1);	}	sprintf(ctlcmd, "r %p", amr);	print("ctlcmd is %s\n", ctlcmd);	amt = write(cfd, ctlcmd, strlen(ctlcmd));	print("ctlcmd write amt %d\n", amt);	if (amt < 0) {		print("r cmd failed\n");		exit(1);	}   for(i = 0; i < 240; i++)  data[i] = i + 0x55; 	print("Run until amr->prod is %d\n", 256 * num);	start = getticks();	/* we are 1 or 0. 1 sends, 0 eats. */	if (role == 0) {		/* suck it up */		/* do I need an mbar now */		while (readl(&amr->prod) < 256 * num) {			mb();			if (readl(&amr->con) != readl(&amr->prod)){				if (readl(&amr->con) == 0)						start = getticks();				print("Advance to %d\n", readl(&amr->prod));				writel(readl(&amr->prod), &amr->con);			} 		} 	} else {		/* do we need to clear out the packet each time through? */		for(i = 0; i < num; i++) {			int res;			memset(coord, 0, 3);			if (! i) print("Call with %p and %p\n", coord, data);			res = syscall(669, coord, data);			if (! res) 				print("Fail @ %d\n", i);		}	}	 	end = getticks();	print("%lld %lld - %d / p\n", end, start, num);	for (i = 0, l = (unsigned long *)amr->base; i < 8; i++)		print("l[%d] = 0x%x\n", i, l[i]);	return 0;}