rminnichgraph app6ecf9e115 years agoHistory
390 lines · 9.0 KB · C
RawDownload
#include "rompi.h"//#include <asm/io.h>typedef uvlong ticks; /* need to resync kernel to this but for now it's ok */extern int myproc, nproc; int amrdebug = 0;/* stuff we might as well keep around for the duration. */static int cfd, ctlfd; /* fucking useless include files! */unsigned long read8(unsigned char *l){	volatile unsigned char *ll = (volatile unsigned char *)l;	return *ll;}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;} static __inline__ void mb(void){	__asm__ __volatile__ ("mbar\n");} struct AmRing * amringsetup(int logN, int core){	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; 	struct AmRing *amr;	unsigned long amrbase;  	/* wire us to core 'core' */	sprintf(ctlcmd, "/proc/%d/ctl", getpid());	if (amrdebug > 2)		print("ctlcmd is %s\n", ctlcmd);	ctlfd = open(ctlcmd, 2);	if (amrdebug > 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);	amrbase = (unsigned int) malloc(2*1024*1024);	if (amrdebug > 2)		print("amrbase is %#x", amrbase);	amrbase = (amrbase+255)&(~0xff);	amr = (void *)amrbase;	if (amrdebug > 2)		print("amr is %p\n", amr);	memset(amr, 0, sizeof(*amr));	amr->base = (u8int *)&amr[1];	amr->size = 1 << logN;	amr->logN = logN;	/* 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);	if (amrdebug > 2)		print("ctlcmd is %s\n", ctlcmd);	amt = write(cfd, ctlcmd, strlen(ctlcmd));	if (amrdebug > 2)		print("ctlcmd write amt %d\n", amt);	if (amt < 0) {		print("r cmd failed\n");		exit(1);	}	if (amrdebug > 2)		print("cmd succeeded\n");	return amr;} intamrsend(struct AmRing *amr, void *data, int size, int rank){	void ranktoxyz(int rank, int *x, int *y, int *z);    	int x, y, z;	u8int *coord;	int res;	ranktoxyz(rank, &x, &y, &z);	coord = mallocz(3, 0);	coord[0] = x;	coord[1] = y;	coord[2] = z;	if (amrdebug > 3)		printf("SEND TO [%d, %d, %d] %p\n", x,y,z,data);	res = syscall(669, coord, data);	//res = syscall(666, coord, data);	/* calling 301 is hanging up the node? 4/11/ 0912 */	//res = syscall(301, coord, data);	if (amrdebug > 3)		printf("res is %d\n", res);	//free(coord);	return res;}  /* return pointer to the set of config packets; set *size to the number  * that are there.  * later. For now we just return the next.  */volatile Tpkt *amrrecv(struct AmRing *amr, int *num, volatile Tpkt *p, int *x, int *y, int *z){	volatile Tpkt *tpkt = NULL;	mb();	unsigned long con = readl(&amr->con), 		prod = readl(&amr->prod);	if (amrdebug > 3)		printf("con %ld, %ld\n", con, prod);	*num = 0; 	if (con != prod) {		tpkt = (volatile Tpkt *) &amr->base[amr->con % amr->size];				{ 			int i,j; 			unsigned char * cp = (unsigned char *)&amr->base[amr->con % amr->size];			for(i = 0; i < 15 && amrdebug > 4; i++) {				printf("%p: ", &cp[i*16+j]);				for(j = 0; j < 16; j++)					printf("%02lx ", read8(&cp[i*16+j]));				printf("\n");			}		}		if (p){			unsigned char *cp = (unsigned char *)p;			int i, j;			if (amrdebug > 4)				printf("memcpy(%p, %p, %d);\n", p, &amr->base[amr->con % amr->size], 256);			memcpy((void *)p, &amr->base[amr->con % amr->size], 256);			for(i = 0; i < 16 && amrdebug > 4; i++) {				printf("%p: ", &cp[i*16]);				for(j = 0; j < 16; j++)					printf("%02lx ", read8(&cp[i*16+j]));				printf("\n");			}		} 		if (amrdebug > 3)			printf("Con %ld, tpkt %p, prod %ld, payloadbyte %02x\n", 			       con, tpkt, prod, p->payload[0]);		writel(con + 256, &amr->con);		*x = read8((u8int *)&tpkt->Hdr.src[X]);		*y = read8((u8int *)&tpkt->Hdr.src[Y]);		*z = read8((u8int *)&tpkt->Hdr.src[Z]);		*num = 1;	}	if (amrdebug > 3)		printf("amrrecv returns %p\n", tpkt);	mb();	return tpkt;} /* just one for now */unsigned char *amrrecvbuf(struct AmRing *amr, unsigned char *p, int *rank){    int xyztorank(int x, int y, int z);     int num = 1;    int x, y, z;    volatile Tpkt *pkt = amrrecv(amr, &num, NULL, &x, &y, &z);    if (amrdebug > 3)	print("amrrecvbuf: pkt %p\n", pkt);    if (pkt) {	memcpy(p, (void *)pkt, 256);	*rank = xyztorank(x,y,z);	if (amrdebug > 3)	    print("amrrecvbuf: rank %d\n", *rank);	return p;    }    if (amrdebug > 3)	print("amrrecvbuf: nothing there\n");    return NULL;} void waitamrpacket(struct AmRing *amr, u8int type, volatile Tpkt *pkt, 		   int *x, int *y, int *z, int secondstimeout){	int num; 	/* eat packets until packet type 'type' is found. */	do {		amrrecv(amr, &num, pkt, x, y, z);		if (num) {			if (amrdebug > 4){				print("waitamrpacket gets %d, wants %d\n", pkt->payload[0], type);				int i,j; 				for(i = 0; i < 15 ; i++) 					for(j = 0; j < 16; j++)						printf("%02lx ", read8((u8int *)&pkt->payload[i*16+j]));								printf("\n");			}		} 			if (secondstimeout)		    sleep(secondstimeout);			} while (num < 1 || read8((u8int *)&pkt->payload[0]) != type);	if (amrdebug > 3)		print("waitamrpacket: returing for %d from (%d, %d, %d)\n", type, x,y,z);}  intsendonebeacon(struct AmRing *amr, int numnodes, u8int bdata){	u8int *data;	int i;  	data = mallocz(256, 1);	for(i = 0; i < 256; i++)		data[i] = 'a' + i;	data[0] = bdata; 	if (amrdebug > 2)		print("0: beacon. numnodes %d\n", numnodes);	for(i = 1; i < numnodes; i++) {		amrsend(amr, data, 240, i);		if (amrdebug > 3)			print("0: send %d\n", i);	}	if (amrdebug > 2)		print("all beacons sent\n");	return numnodes;} intbeacon(struct AmRing *amr, int *nodestatus, int numnodes, u8int bdata){	u8int *data;	Tpkt *pkt;	int num;	int x, y, z;	int rank;	int i;	int dontcare; 	pkt = mallocz(1024, 1);	data = mallocz(256, 1);	for(i = 0; i < 256; i++)		data[i] = 'a' + i;	data[0] = bdata;	/* go ahead and send the beacon. */	if (amrdebug > 2)		print("0: beacon. numnodes %d\n", numnodes);	for(num = i = 1; i < numnodes; i++) {		if (! nodestatus[i]){			amrsend(amr, data, 240, i);			if (amrdebug > 3)				print("0: send %d\n", i);		} else {			num++;		}	}	if (amrdebug > 2)		print("all beacons sent\n");	/* gather any responses */	while (amrrecv(amr, &dontcare, pkt, &x, &y, &z) && (num < numnodes)) {		int xyztorank(int x, int y, int z);		rank = xyztorank(x, y, z);		if (amrdebug > 3)			printf("beacon: one from %d(%d,%d,%d) status %d\n", rank, x,y,z, nodestatus[rank]);		if (nodestatus[rank] == 0) {			num++;			if (amrdebug > 3) print("num %d of %d\n", num, numnodes);		}		nodestatus[rank]++;	}	free(data);	/* return total responses contained in 'nodes' */	if (amrdebug > 2)		print("beacon: return %d of %d needed\n", num, numnodes);	return num;} voidwaitbeacon(struct AmRing *amr, u8int bdata){	int x, y, z;	static Tpkt *pkt = NULL;	if (! pkt)		pkt = mallocz(1024, 1);	waitamrpacket(amr, bdata, pkt, &x, &y, &z, 0);	if (amrdebug > 2)		printf("Waitbeacon gets it from (%d,%d,%d)\n", x, y, z);} voidrespondbeacon(struct AmRing *amr, u8int response){	unsigned char *data;	data = mallocz(256, 1);	data[0] = response;	if (amrdebug > 2)		printf("Respondbeacon to 0\n");	/* send a response to a packet -- first char is 'b' */	amrsend(amr, data, 240, 0);	free(data);} voidintreduce(struct AmRing *amr){	if (! myproc) {		/* just sweep up the 'i' packets */		/* second 32-bits is the sum */		/* return the sum with an 'I' packet */	} else {		/* send the packet of type 'i' */		/* waitpacket 'I' */	}} voidamrstartup(struct AmRing *amr){	/* step 1: everyone checks in */	if (! myproc) {		/* node 0 beacons once per second. It collects responses. 		 * once all nodes have checked in it sends a start message. 		 */		int numresponded = 0;		int *nodes = mallocz(nproc*sizeof(*nodes), 1);		if (amrdebug > 2)			printf("amrstartup: time for node 0 to tell %d nodes\n", nproc);		while (numresponded < nproc) {			numresponded = beacon(amr, nodes, nproc, 'B');			if (amrdebug > 3)				printf("amrstartup: %d to date\n", numresponded);			sleep(5);			if (amrdebug > 3)				printf("amrstartup: node 0 starts again\n");			//exit(1);		}	} else {		/* wait for the beacon */		waitbeacon(amr, 'B');		/* send our response */		respondbeacon(amr, 'b');		if (amrdebug > 2)			printf("responded\n");	} 	/* step 2: node 0 tells everyone they can proceed */	if (! myproc) {		sendonebeacon(amr, nproc, 'D');	} else {		waitbeacon(amr, 'D');	}		/* amring is now usable for normal work */}