Commit 52620034 authored by Ken Thompson's avatar Ken Thompson

synch chan

SVN=127055
parent f7e2bb55
......@@ -22,6 +22,7 @@ LIBOFILES=\
chan.$O\
print.$O\
rune.$O\
proc.$O\
string.$O\
sys_file.$O\
......
......@@ -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");
}
......@@ -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)
{
......
......@@ -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
......
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