Commit 3338c71f authored by Ken Thompson's avatar Ken Thompson

bug in async select read

buganizer 1589219
channel is returning same values multiple times

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