From: Ken Thompson Date: Mon, 14 Jul 2008 21:33:39 +0000 (-0700) Subject: synch chan X-Git-Tag: weekly.2009-11-06~3506 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=526200345cd6b1e1449f7adb62f05410ff01a44a;p=gostls13.git synch chan SVN=127055 --- diff --git a/src/runtime/Makefile b/src/runtime/Makefile index d7f351ede1..f50ac826ca 100644 --- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -22,6 +22,7 @@ LIBOFILES=\ 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 7014ebc657..a2263a5e7f 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 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint, Hchan* ret) { Hchan *c; + int32 i; if(elemalg >= nelem(algarray)) { prints("0<="); @@ -37,10 +51,30 @@ sys·newchan(uint32 elemsize, uint32 elemalg, uint32 hint, 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; ilink = 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·newchan(uint32 elemsize, uint32 elemalg, uint32 hint, 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 @@ void sys·chansend(Hchan* c, ...) { byte *ae; + G *gr; ae = (byte*)&c + c->eo; if(debug) { @@ -72,6 +108,23 @@ sys·chansend(Hchan* c, ...) 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 @@ void sys·chanrecv1(Hchan* c, ...) { byte *ae; + G *gs; ae = (byte*)&c + c->eo; if(debug) { @@ -86,18 +140,42 @@ sys·chanrecv1(Hchan* c, ...) 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 bc6c0ccb9d..8180b3c8ec 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -581,238 +581,10 @@ check(void) 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 4273f16eac..0b2e8ed975 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -42,6 +42,7 @@ typedef struct G G; typedef struct M M; typedef struct Stktop Stktop; typedef struct Alg Alg; +typedef struct WaitQ WaitQ; /* * per cpu declaration @@ -57,6 +58,7 @@ enum // G status Gidle, Grunnable, + Gwaiting, Gdead, }; enum @@ -104,10 +106,12 @@ struct G 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 @@ struct M int32 siz1; int32 siz2; }; -struct Stktop +struct WaitQ +{ + G* first; + G* last; +}; +struct Stktop { uint8* oldbase; uint8* oldsp; @@ -166,6 +175,8 @@ int32 findnull(int8*); void dump(byte*, int32); int32 runetochar(byte*, int32); int32 chartorune(uint32*, byte*); +G* dequeue(WaitQ*); +void enqueue(WaitQ*, G*); /* * very low level c-called