]> Cypherpunks repositories - gostls13.git/commitdiff
synch chan
authorKen Thompson <ken@golang.org>
Mon, 14 Jul 2008 21:33:39 +0000 (14:33 -0700)
committerKen Thompson <ken@golang.org>
Mon, 14 Jul 2008 21:33:39 +0000 (14:33 -0700)
SVN=127055

src/runtime/Makefile
src/runtime/chan.c
src/runtime/runtime.c
src/runtime/runtime.h

index d7f351ede1cffc7c62d2e9a1ed3c21d8243e061d..f50ac826ca9766e5c7ce1eee9409fb23dbaa15dd 100644 (file)
@@ -22,6 +22,7 @@ LIBOFILES=\
        chan.$O\
        print.$O\
        rune.$O\
+       proc.$O\
        string.$O\
        sys_file.$O\
 
index 7014ebc657aa2677214e98cc7f1ab88fcc72ce54..a2263a5e7fa1ee104e20c5fbfd39a53bf3c8a8d9 100644 (file)
@@ -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; 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·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");
 }
index bc6c0ccb9dc9afa61427c272a76e4b36f38f7fd6..8180b3c8ec9c52f326140e31bbb04d961dd57dc4 100644 (file)
@@ -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)
 {
index 4273f16eac31fa2b66c635630a7852c9014434f3..0b2e8ed975a979ee8f2e9d11b6338ac6fe582483 100644 (file)
@@ -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