From: Ken Thompson Date: Sat, 20 Sep 2008 03:43:30 +0000 (-0700) Subject: fix bugs in asynch select X-Git-Tag: weekly.2009-11-06~3162 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1da727a31f949e63636c465698059bf89b7bc3ce;p=gostls13.git fix bugs in asynch select R=r OCL=15586 CL=15586 --- diff --git a/src/runtime/chan.c b/src/runtime/chan.c index ffbab902f4..17f00d4ce7 100644 --- a/src/runtime/chan.c +++ b/src/runtime/chan.c @@ -201,6 +201,7 @@ sendchan(Hchan *c, byte *ep, bool *pres) return; asynch: +//prints("\nasend\n"); while(c->qcount >= c->dataqsiz) { // (rsc) should check for pres != nil sg = allocsg(c); @@ -208,6 +209,7 @@ asynch: enqueue(&c->sendq, sg); unlock(&chanlock); sys·gosched(); + lock(&chanlock); } if(ep != nil) @@ -218,10 +220,12 @@ asynch: 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 + } else unlock(&chanlock); } @@ -290,10 +294,11 @@ asynch: sg = dequeue(&c->sendq, c); if(sg != nil) { gp = sg->g; + gp->param = sg; freesg(c, sg); unlock(&chanlock); ready(gp); - }else + } else unlock(&chanlock); } @@ -523,7 +528,6 @@ sys·selectgo(Select *sel) for(i=0; incase; i++) { cas = &sel->scase[o]; c = cas->chan; - if(c->dataqsiz > 0) { if(cas->send) { if(c->qcount < c->dataqsiz) @@ -532,7 +536,7 @@ sys·selectgo(Select *sel) if(c->qcount > 0) goto asynr; } - } + } else if(cas->send) { sg = dequeue(&c->recvq, c); @@ -557,23 +561,29 @@ sys·selectgo(Select *sel) if(c->dataqsiz > 0) { if(cas->send) { if(c->qcount < c->dataqsiz) { - prints("second pass asyn send\n"); + prints("selectgo: pass 2 async send\n"); goto asyns; } + sg = allocsg(c); + sg->offset = o; + enqueue(&c->sendq, sg); } else { if(c->qcount > 0) { - prints("second pass asyn recv\n"); + prints("selectgo: pass 2 async recv\n"); goto asynr; } + sg = allocsg(c); + sg->offset = o; + enqueue(&c->recvq, sg); } - } + } else if(cas->send) { sg = dequeue(&c->recvq, c); if(sg != nil) { - prints("second pass syn send\n"); + prints("selectgo: pass 2 sync send\n"); g->selgen++; - goto gots; // probably an error + goto gots; } sg = allocsg(c); sg->offset = o; @@ -582,9 +592,9 @@ sys·selectgo(Select *sel) } else { sg = dequeue(&c->sendq, c); if(sg != nil) { - prints("second pass syn recv\n"); + prints("selectgo: pass 2 sync recv\n"); g->selgen++; - goto gotr; // probably an error + goto gotr; } sg = allocsg(c); sg->offset = o; @@ -596,9 +606,6 @@ sys·selectgo(Select *sel) o -= sel->ncase; } - // send and recv paths to sleep for a rendezvous - // (rsc) not correct to set Gwaiting after queueing; - // might already have been readied. g->status = Gwaiting; unlock(&chanlock); sys·gosched(); @@ -623,6 +630,12 @@ sys·selectgo(Select *sel) 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); @@ -632,10 +645,31 @@ sys·selectgo(Select *sel) goto retc; asynr: + if(cas->u.elemp != nil) + c->elemalg->copy(c->elemsize, cas->u.elemp, c->recvdataq->elem); + c->recvdataq = c->recvdataq->link; + c->qcount--; + sg = dequeue(&c->sendq, c); + if(sg != nil) { + gp = sg->g; + freesg(c, sg); + ready(gp); + } + goto retc; + asyns: - unlock(&chanlock); - throw("asyn"); - return; // compiler doesn't know throw doesn't return + if(cas->u.elem != nil) + c->elemalg->copy(c->elemsize, c->senddataq->elem, cas->u.elem); + c->senddataq = c->senddataq->link; + c->qcount++; + sg = dequeue(&c->recvq, c); + if(sg != nil) { + gp = sg->g; + gp->param = sg; + freesg(c, sg); + ready(gp); + } + goto retc; gotr: // recv path to wakeup the sender (sg)