synch chan

SVN=127055
diff --git a/src/runtime/Makefile b/src/runtime/Makefile
index d7f351e..f50ac82 100644
--- a/src/runtime/Makefile
+++ b/src/runtime/Makefile
@@ -22,6 +22,7 @@
 	chan.$O\
 	print.$O\
 	rune.$O\
+	proc.$O\
 	string.$O\
 	sys_file.$O\
 
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index 7014ebc..a2263a5 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -4,16 +4,29 @@
 
 #include "runtime.h"
 
-static	int32	debug	= 1;
+static	int32	debug	= 0;
 
 typedef	struct	Hchan	Hchan;
+typedef	struct	Link	Link;
 
 struct	Hchan
 {
 	uint32	elemsize;
-	uint32	hint;
-	uint32	eo;
-	Alg*	elemalg;
+	uint32	dataqsiz;		// size of the circular q
+	uint32	qcount;			// total data in the q
+	uint32	eo;			// vararg of element
+	uint32	po;			// vararg of present bool
+	Alg*	elemalg;		// interface for element type
+	Link*	senddataq;		// pointer for sender
+	Link*	recvdataq;		// pointer for receiver
+	WaitQ	recvq;			// list of recv waiters
+	WaitQ	sendq;			// list of send waiters
+};
+
+struct	Link
+{
+	Link*	link;
+	byte	data[8];
 };
 
 // newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
@@ -22,6 +35,7 @@
 	Hchan* ret)
 {
 	Hchan *c;
+	int32 i;
 
 	if(elemalg >= nelem(algarray)) {
 		prints("0<=");
@@ -37,10 +51,30 @@
 
 	c->elemsize = elemsize;
 	c->elemalg = &algarray[elemalg];
-	c->hint = hint;
+
+	if(hint > 0) {
+		Link *d, *b, *e;
+
+		// make a circular q
+		b = nil;
+		e = nil;
+		for(i=0; i<hint; i++) {
+			d = mal(sizeof(*d));
+			if(e == nil)
+				e = d;
+			d->link = b;
+			b = d;
+		}
+		e->link = b;
+		c->recvdataq = b;
+		c->senddataq = b;
+		c->qcount = 0;
+		c->dataqsiz = hint;
+	}
 
 	// these calculations are compiler dependent
 	c->eo = rnd(sizeof(c), elemsize);
+	c->po = rnd(c->eo+elemsize, 1);
 
 	ret = c;
 	FLUSH(&ret);
@@ -52,10 +86,11 @@
 		sys·printint(elemsize);
 		prints("; elemalg=");
 		sys·printint(elemalg);
-		prints("; hint=");
-		sys·printint(hint);
+		prints("; dataqsiz=");
+		sys·printint(c->dataqsiz);
 		prints("\n");
 	}
+
 }
 
 // chansend(hchan *chan any, elem any);
@@ -63,6 +98,7 @@
 sys·chansend(Hchan* c, ...)
 {
 	byte *ae;
+	G *gr;
 
 	ae = (byte*)&c + c->eo;
 	if(debug) {
@@ -72,6 +108,23 @@
 		c->elemalg->print(c->elemsize, ae);
 		prints("\n");
 	}
+	if(c->dataqsiz > 0)
+		goto asynch;
+
+	gr = dequeue(&c->recvq);
+	if(gr != nil) {
+		c->elemalg->copy(c->elemsize, gr->elem, ae);
+		gr->status = Grunnable;
+		return;
+	}
+	c->elemalg->copy(c->elemsize, g->elem, ae);
+	g->status = Gwaiting;
+	enqueue(&c->sendq, g);
+	sys·gosched();
+	return;
+
+asynch:
+	throw("sys·chansend: asynch not yet");
 }
 
 // chanrecv1(hchan *chan any) (elem any);
@@ -79,6 +132,7 @@
 sys·chanrecv1(Hchan* c, ...)
 {
 	byte *ae;
+	G *gs;
 
 	ae = (byte*)&c + c->eo;
 	if(debug) {
@@ -86,18 +140,42 @@
 		sys·printpointer(c);
 		prints("\n");
 	}
+	if(c->dataqsiz > 0)
+		goto asynch;
+
+	gs = dequeue(&c->sendq);
+	if(gs != nil) {
+		c->elemalg->copy(c->elemsize, ae, gs->elem);
+		gs->status = Grunnable;
+		return;
+	}
+	g->status = Gwaiting;
+	enqueue(&c->recvq, g);
+	sys·gosched();
+	c->elemalg->copy(c->elemsize, ae, g->elem);
+	return;
+
+asynch:
+	throw("sys·chanrecv1: asynch not yet");
 }
 
 // chanrecv2(hchan *chan any) (elem any, pres bool);
 void
 sys·chanrecv2(Hchan* c, ...)
 {
-	byte *ae;
+	byte *ae, *ap;
 
 	ae = (byte*)&c + c->eo;
+	ap = (byte*)&c + c->po;
 	if(debug) {
 		prints("chanrecv2: chan=");
 		sys·printpointer(c);
 		prints("\n");
 	}
+	if(c->dataqsiz > 0)
+		goto asynch;
+	throw("sys·chanrecv2: synch not yet");
+
+asynch:
+	throw("sys·chanrecv2: asynch not yet");
 }
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index bc6c0cc..8180b3c 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -581,238 +581,10 @@
 	initsig();
 }
 
-void
-sys·goexit(void)
-{
-//prints("goexit goid=");
-//sys·printint(g->goid);
-//prints("\n");
-	g->status = Gdead;
-	sys·gosched();
-}
-
-void
-sys·newproc(int32 siz, byte* fn, byte* arg0)
-{
-	byte *stk, *sp;
-	G *newg;
-
-//prints("newproc siz=");
-//sys·printint(siz);
-//prints(" fn=");
-//sys·printpointer(fn);
-
-	siz = (siz+7) & ~7;
-	if(siz > 1024) {
-		prints("sys·newproc: too many args: ");
-		sys·printint(siz);
-		prints("\n");
-		sys·panicl(123);
-	}
-
-	newg = mal(sizeof(G));
-	stk = mal(4096);
-	newg->stackguard = stk+160;
-
-	sp = stk + 4096 - 4*8;
-	newg->stackbase = sp;
-
-	sp -= siz;
-	mcpy(sp, (byte*)&arg0, siz);
-
-	sp -= 8;
-	*(byte**)sp = (byte*)sys·goexit;
-
-	sp -= 8;	// retpc used by gogo
-	newg->sched.SP = sp;
-	newg->sched.PC = fn;
-
-	goidgen++;
-	newg->goid = goidgen;
-
-	newg->status = Grunnable;
-	newg->link = allg;
-	allg = newg;
-
-//prints(" goid=");
-//sys·printint(newg->goid);
-//prints("\n");
-}
-
-G*
-select(void)
-{
-	G *gp, *bestg;
-
-	bestg = nil;
-	for(gp=allg; gp!=nil; gp=gp->link) {
-		if(gp->status != Grunnable)
-			continue;
-		if(bestg == nil || gp->pri < bestg->pri)
-			bestg = gp;
-	}
-	if(bestg != nil)
-		bestg->pri++;
-	return bestg;
-}
-
-void
-gom0init(void)
-{
-	gosave(&m->sched);
-	sys·gosched();
-}
-
-void
-sys·gosched(void)
-{
-	G* gp;
-
-	if(g != m->g0) {
-		if(gosave(&g->sched))
-			return;
-		g = m->g0;
-		gogo(&m->sched);
-	}
-	gp = select();
-	if(gp == nil) {
-//		prints("sched: no more work\n");
-		sys·exit(0);
-	}
-
-	m->curg = gp;
-	g = gp;
-	gogo(&gp->sched);
-}
-
-//
-// the calling sequence for a routine that
-// needs N bytes stack, A args.
-//
-//	N1 = (N+160 > 4096)? N+160: 0
-//	A1 = A
-//
-// if N <= 75
-//	CMPQ	SP, 0(R15)
-//	JHI	4(PC)
-//	MOVQ	$(N1<<0) | (A1<<32)), AX
-//	MOVQ	AX, 0(R14)
-//	CALL	sys·morestack(SB)
-//
-// if N > 75
-//	LEAQ	(-N-75)(SP), AX
-//	CMPQ	AX, 0(R15)
-//	JHI	4(PC)
-//	MOVQ	$(N1<<0) | (A1<<32)), AX
-//	MOVQ	AX, 0(R14)
-//	CALL	sys·morestack(SB)
-//
-
-void
-oldstack(void)
-{
-	Stktop *top;
-	uint32 siz2;
-	byte *sp;
-if(debug) prints("oldstack m->cret = ");
-if(debug) sys·printpointer((void*)m->cret);
-if(debug) prints("\n");
-
-	top = (Stktop*)m->curg->stackbase;
-
-	m->curg->stackbase = top->oldbase;
-	m->curg->stackguard = top->oldguard;
-	siz2 = (top->magic>>32) & 0xffffLL;
-
-	sp = (byte*)top;
-	if(siz2 > 0) {
-		siz2 = (siz2+7) & ~7;
-		sp -= siz2;
-		mcpy(top->oldsp+16, sp, siz2);
-	}
-
-	m->morestack.SP = top->oldsp+8;
-	m->morestack.PC = (byte*)(*(uint64*)(top->oldsp+8));
-if(debug) prints("oldstack sp=");
-if(debug) sys·printpointer(m->morestack.SP);
-if(debug) prints(" pc=");
-if(debug) sys·printpointer(m->morestack.PC);
-if(debug) prints("\n");
-	gogoret(&m->morestack, m->cret);
-}
-
-void
-newstack(void)
-{
-	int32 siz1, siz2;
-	Stktop *top;
-	byte *stk, *sp;
-	void (*fn)(void);
-
-	siz1 = m->morearg & 0xffffffffLL;
-	siz2 = (m->morearg>>32) & 0xffffLL;
-
-if(debug) prints("newstack siz1=");
-if(debug) sys·printint(siz1);
-if(debug) prints(" siz2=");
-if(debug) sys·printint(siz2);
-if(debug) prints(" moresp=");
-if(debug) sys·printpointer(m->moresp);
-if(debug) prints("\n");
-
-	if(siz1 < 4096)
-		siz1 = 4096;
-	stk = mal(siz1 + 1024);
-	stk += 512;
-
-	top = (Stktop*)(stk+siz1-sizeof(*top));
-
-	top->oldbase = m->curg->stackbase;
-	top->oldguard = m->curg->stackguard;
-	top->oldsp = m->moresp;
-	top->magic = m->morearg;
-
-	m->curg->stackbase = (byte*)top;
-	m->curg->stackguard = stk + 160;
-
-	sp = (byte*)top;
-	
-	if(siz2 > 0) {
-		siz2 = (siz2+7) & ~7;
-		sp -= siz2;
-		mcpy(sp, m->moresp+16, siz2);
-	}
-
-	g = m->curg;
-	fn = (void(*)(void))(*(uint64*)m->moresp);
-if(debug) prints("fn=");
-if(debug) sys·printpointer(fn);
-if(debug) prints("\n");
-	setspgoto(sp, fn, retfromnewstack);
-
-	*(int32*)345 = 123;
-}
-
-void
-sys·morestack(uint64 u)
-{
-	while(g == m->g0) {
-		// very bad news
-		*(int32*)123 = 123;
-	}
-
-	g = m->g0;
-	m->moresp = (byte*)(&u-1);
-	setspgoto(m->sched.SP, newstack, nil);
-
-	*(int32*)234 = 123;
-}
-
 /*
  * map and chan helpers for
  * dealing with unknown types
  */
-
 static uint64
 memhash(uint32 s, void *a)
 {
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 4273f16..0b2e8ed 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -42,6 +42,7 @@
 typedef	struct	M		M;
 typedef struct	Stktop		Stktop;
 typedef	struct	Alg		Alg;
+typedef	struct	WaitQ		WaitQ;
 
 /*
  * per cpu declaration
@@ -57,6 +58,7 @@
 	// G status
 	Gidle,
 	Grunnable,
+	Gwaiting,
 	Gdead,
 };
 enum
@@ -104,10 +106,12 @@
 	byte*	stackguard;	// must not move
 	byte*	stackbase;	// must not move
 	Gobuf	sched;
-	G*	link;
+	G*	alllink;	// on allq
+	G*	qlink;		// on wait q
 	int32	status;
 	int32	pri;
 	int32	goid;
+	byte	elem[8];	// transfer element for chan
 };
 struct	M
 {
@@ -121,7 +125,12 @@
 	int32	siz1;
 	int32	siz2;
 };
-struct Stktop
+struct	WaitQ
+{
+	G*	first;
+	G*	last;
+};
+struct	Stktop
 {
 	uint8*	oldbase;
 	uint8*	oldsp;
@@ -166,6 +175,8 @@
 void	dump(byte*, int32);
 int32	runetochar(byte*, int32);
 int32	chartorune(uint32*, byte*);
+G*	dequeue(WaitQ*);
+void	enqueue(WaitQ*, G*);
 
 /*
  * very low level c-called