#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);
Hchan* ret)
{
Hchan *c;
+ int32 i;
if(elemalg >= nelem(algarray)) {
prints("0<=");
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);
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);
sys·chansend(Hchan* c, ...)
{
byte *ae;
+ G *gr;
ae = (byte*)&c + c->eo;
if(debug) {
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);
sys·chanrecv1(Hchan* c, ...)
{
byte *ae;
+ G *gs;
ae = (byte*)&c + c->eo;
if(debug) {
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");
}
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)
{