bug in async select read
buganizer 1589219
channel is returning same values multiple times

R=r
OCL=23447
CL=23447
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index f6e2453..929d07f 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -5,6 +5,7 @@
 #include "runtime.h"
 
 static	int32	debug	= 0;
+static	int32	xxx	= 0;
 static	Lock		chanlock;
 
 typedef	struct	Hchan	Hchan;
@@ -17,8 +18,9 @@
 struct	SudoG
 {
 	G*	g;		// g and selgen constitute
-	int16	offset;		// offset of case number
 	int32	selgen;		// a weak pointer to g
+	int16	offset;		// offset of case number
+	int8	isfree;		// offset of case number
 	SudoG*	link;
 	byte	elem[8];	// synch data element (+ more)
 };
@@ -206,7 +208,6 @@
 	return;
 
 asynch:
-//prints("\nasend\n");
 	while(c->qcount >= c->dataqsiz) {
 		if(pres != nil) {
 			unlock(&chanlock);
@@ -229,10 +230,8 @@
 	sg = dequeue(&c->recvq, c);
 	if(sg != nil) {
 		gp = sg->g;
-		gp->param = sg;
 		freesg(c, sg);
 		unlock(&chanlock);
-//prints("wakeup\n");
 		ready(gp);
 	} else
 		unlock(&chanlock);
@@ -312,7 +311,6 @@
 	sg = dequeue(&c->sendq, c);
 	if(sg != nil) {
 		gp = sg->g;
-		gp->param = sg;
 		freesg(c, sg);
 		unlock(&chanlock);
 		ready(gp);
@@ -411,7 +409,7 @@
 	if(debug) {
 		prints("newselect s=");
 		sys·printpointer(sel);
-		prints("newselect size=");
+		prints(" size=");
 		sys·printint(size);
 		prints("\n");
 	}
@@ -451,7 +449,7 @@
 	c->elemalg->copy(c->elemsize, cas->u.elem, ae);
 
 	if(debug) {
-		prints("newselect s=");
+		prints("selectsend s=");
 		sys·printpointer(sel);
 		prints(" pc=");
 		sys·printpointer(cas->pc);
@@ -495,7 +493,7 @@
 	cas->u.elemp = *(byte**)((byte*)&sel + eo);
 
 	if(debug) {
-		prints("newselect s=");
+		prints("selectrecv s=");
 		sys·printpointer(sel);
 		prints(" pc=");
 		sys·printpointer(cas->pc);
@@ -510,7 +508,7 @@
 }
 
 
-// selectrecv(sel *byte) (selected bool);
+// selectdefaul(sel *byte) (selected bool);
 void
 sys·selectdefault(Select *sel, ...)
 {
@@ -534,7 +532,7 @@
 	cas->u.elemp = nil;
 
 	if(debug) {
-		prints("newselect s=");
+		prints("selectdefault s=");
 		sys·printpointer(sel);
 		prints(" pc=");
 		sys·printpointer(cas->pc);
@@ -546,7 +544,6 @@
 	}
 }
 
-uint32	xxx	= 0;
 
 // selectgo(sel *byte);
 void
@@ -589,6 +586,7 @@
 
 	lock(&chanlock);
 
+loop:
 	// pass 1 - look for something already waiting
 	dfl = nil;
 	for(i=0; i<sel->ncase; i++) {
@@ -688,16 +686,25 @@
 			o -= sel->ncase;
 	}
 
+	g->param = nil;
 	g->status = Gwaiting;
 	unlock(&chanlock);
 	sys·Gosched();
 
 	lock(&chanlock);
 	sg = g->param;
+	if(sg == nil)
+		goto loop;
+
 	o = sg->offset;
 	cas = sel->scase[o];
 	c = cas->chan;
 
+	if(c->dataqsiz > 0) {
+//		prints("shouldnt happen\n");
+		goto loop;
+	}
+
 	if(xxx) {
 		prints("wait-return: sel=");
 		sys·printpointer(sel);
@@ -712,12 +719,6 @@
 		prints("\n");
 	}
 
-	if(c->dataqsiz > 0) {
-		if(cas->send)
-			goto asyns;
-		goto asynr;
-	}
-
 	if(!cas->send) {
 		if(cas->u.elemp != nil)
 			c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
@@ -734,7 +735,6 @@
 	sg = dequeue(&c->sendq, c);
 	if(sg != nil) {
 		gp = sg->g;
-		gp->param = sg;
 		freesg(c, sg);
 		ready(gp);
 	}
@@ -748,7 +748,6 @@
 	sg = dequeue(&c->recvq, c);
 	if(sg != nil) {
 		gp = sg->g;
-		gp->param = sg;
 		freesg(c, sg);
 		ready(gp);
 	}
@@ -849,6 +848,7 @@
 	sg->selgen = g->selgen;
 	sg->g = g;
 	sg->offset = 0;
+	sg->isfree = 0;
 
 	return sg;
 }
@@ -856,6 +856,9 @@
 static void
 freesg(Hchan *c, SudoG *sg)
 {
+	if(sg->isfree)
+		throw("chan.freesg: already free");
+	sg->isfree = 1;
 	sg->link = c->free;
 	c->free = sg;
 }