137da2899SCharles.Forsyth #include "lib9.h"
237da2899SCharles.Forsyth #include "isa.h"
337da2899SCharles.Forsyth #include "interp.h"
437da2899SCharles.Forsyth #include "raise.h"
537da2899SCharles.Forsyth
637da2899SCharles.Forsyth #define OP(fn) void fn(void)
737da2899SCharles.Forsyth #define W(p) *((WORD*)(p))
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth #define CANGET(c) ((c)->size > 0)
1037da2899SCharles.Forsyth #define CANPUT(c) ((c)->buf != H && (c)->size < (c)->buf->len)
1137da2899SCharles.Forsyth
1237da2899SCharles.Forsyth extern OP(isend);
1337da2899SCharles.Forsyth extern OP(irecv);
1437da2899SCharles.Forsyth
1537da2899SCharles.Forsyth /*
1637da2899SCharles.Forsyth * Count the number of ready channels in an array of channels
1737da2899SCharles.Forsyth * Set each channel's alt pointer to the owning prog
1837da2899SCharles.Forsyth */
1937da2899SCharles.Forsyth static int
altmark(Channel * c,Prog * p)2037da2899SCharles.Forsyth altmark(Channel *c, Prog *p)
2137da2899SCharles.Forsyth {
2237da2899SCharles.Forsyth int nrdy;
2337da2899SCharles.Forsyth Array *a;
2437da2899SCharles.Forsyth Channel **ca, **ec;
2537da2899SCharles.Forsyth
2637da2899SCharles.Forsyth nrdy = 0;
2737da2899SCharles.Forsyth a = (Array*)c;
2837da2899SCharles.Forsyth ca = (Channel**)a->data;
2937da2899SCharles.Forsyth ec = ca + a->len;
3037da2899SCharles.Forsyth while(ca < ec) {
3137da2899SCharles.Forsyth c = *ca;
3237da2899SCharles.Forsyth if(c != H) {
3337da2899SCharles.Forsyth if(c->send->prog || CANGET(c))
3437da2899SCharles.Forsyth nrdy++;
3537da2899SCharles.Forsyth cqadd(&c->recv, p);
3637da2899SCharles.Forsyth }
3737da2899SCharles.Forsyth ca++;
3837da2899SCharles.Forsyth }
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth return nrdy;
4137da2899SCharles.Forsyth }
4237da2899SCharles.Forsyth
4337da2899SCharles.Forsyth /*
4437da2899SCharles.Forsyth * Remove alt references to an array of channels
4537da2899SCharles.Forsyth */
4637da2899SCharles.Forsyth static void
altunmark(Channel * c,WORD * ptr,Prog * p,int sr,Channel ** sel,int dn)4737da2899SCharles.Forsyth altunmark(Channel *c, WORD *ptr, Prog *p, int sr, Channel **sel, int dn)
4837da2899SCharles.Forsyth {
4937da2899SCharles.Forsyth int n;
5037da2899SCharles.Forsyth Array *a;
5137da2899SCharles.Forsyth Channel **ca, **ec;
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth n = 0;
5437da2899SCharles.Forsyth a = (Array*)c;
5537da2899SCharles.Forsyth ca = (Channel**)a->data;
5637da2899SCharles.Forsyth ec = ca + a->len;
5737da2899SCharles.Forsyth while(ca < ec) {
5837da2899SCharles.Forsyth c = *ca;
5937da2899SCharles.Forsyth if(c != H && c->recv->prog)
6037da2899SCharles.Forsyth cqdelp(&c->recv, p);
6137da2899SCharles.Forsyth if(sr == 1 && *sel == c) {
6237da2899SCharles.Forsyth W(p->R.d) = dn;
6337da2899SCharles.Forsyth p->ptr = ptr + 1;
6437da2899SCharles.Forsyth ptr[0] = n;
6537da2899SCharles.Forsyth *sel = nil;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth ca++;
6837da2899SCharles.Forsyth n++;
6937da2899SCharles.Forsyth }
7037da2899SCharles.Forsyth }
7137da2899SCharles.Forsyth
7237da2899SCharles.Forsyth /*
7337da2899SCharles.Forsyth * ALT Pass 1 - Count the number of ready channels and mark
7437da2899SCharles.Forsyth * each channel as ALT by this prog
7537da2899SCharles.Forsyth */
7637da2899SCharles.Forsyth static int
altrdy(Alt * a,Prog * p)7737da2899SCharles.Forsyth altrdy(Alt *a, Prog *p)
7837da2899SCharles.Forsyth {
7937da2899SCharles.Forsyth char *e;
8037da2899SCharles.Forsyth Type *t;
8137da2899SCharles.Forsyth int nrdy;
8237da2899SCharles.Forsyth Channel *c;
8337da2899SCharles.Forsyth Altc *ac, *eac;
8437da2899SCharles.Forsyth
8537da2899SCharles.Forsyth e = nil;
8637da2899SCharles.Forsyth nrdy = 0;
8737da2899SCharles.Forsyth
8837da2899SCharles.Forsyth ac = a->ac + a->nsend;
8937da2899SCharles.Forsyth eac = ac + a->nrecv;
9037da2899SCharles.Forsyth while(ac < eac) {
9137da2899SCharles.Forsyth c = ac->c;
9237da2899SCharles.Forsyth ac++;
9337da2899SCharles.Forsyth if(c == H) {
9437da2899SCharles.Forsyth e = exNilref;
9537da2899SCharles.Forsyth continue;
9637da2899SCharles.Forsyth }
9737da2899SCharles.Forsyth t = D2H(c)->t;
9837da2899SCharles.Forsyth if(t == &Tarray)
9937da2899SCharles.Forsyth nrdy += altmark(c, p);
10037da2899SCharles.Forsyth else {
10137da2899SCharles.Forsyth if(c->send->prog || CANGET(c))
10237da2899SCharles.Forsyth nrdy++;
10337da2899SCharles.Forsyth cqadd(&c->recv, p);
10437da2899SCharles.Forsyth }
10537da2899SCharles.Forsyth }
10637da2899SCharles.Forsyth
10737da2899SCharles.Forsyth ac = a->ac;
10837da2899SCharles.Forsyth eac = ac + a->nsend;
10937da2899SCharles.Forsyth while(ac < eac) {
11037da2899SCharles.Forsyth c = ac->c;
11137da2899SCharles.Forsyth ac++;
11237da2899SCharles.Forsyth if(c == H) {
11337da2899SCharles.Forsyth e = exNilref;
11437da2899SCharles.Forsyth continue;
11537da2899SCharles.Forsyth }
11637da2899SCharles.Forsyth if(c->recv->prog || CANPUT(c)) {
11737da2899SCharles.Forsyth if(c->recv->prog == p) {
11837da2899SCharles.Forsyth e = exAlt;
11937da2899SCharles.Forsyth continue;
12037da2899SCharles.Forsyth }
12137da2899SCharles.Forsyth nrdy++;
12237da2899SCharles.Forsyth }
12337da2899SCharles.Forsyth cqadd(&c->send, p);
12437da2899SCharles.Forsyth }
12537da2899SCharles.Forsyth
12637da2899SCharles.Forsyth if(e != nil) {
12737da2899SCharles.Forsyth altdone(a, p, nil, -1);
12837da2899SCharles.Forsyth error(e);
12937da2899SCharles.Forsyth }
13037da2899SCharles.Forsyth
13137da2899SCharles.Forsyth return nrdy;
13237da2899SCharles.Forsyth }
13337da2899SCharles.Forsyth
13437da2899SCharles.Forsyth /*
13537da2899SCharles.Forsyth * ALT Pass 3 - Pull out of an ALT cancelling the channel pointers in each item
13637da2899SCharles.Forsyth */
13737da2899SCharles.Forsyth void
altdone(Alt * a,Prog * p,Channel * sel,int sr)13837da2899SCharles.Forsyth altdone(Alt *a, Prog *p, Channel *sel, int sr)
13937da2899SCharles.Forsyth {
14037da2899SCharles.Forsyth int n;
14137da2899SCharles.Forsyth Type *t;
14237da2899SCharles.Forsyth Channel *c;
14337da2899SCharles.Forsyth Altc *ac, *eac;
14437da2899SCharles.Forsyth
14537da2899SCharles.Forsyth n = 0;
14637da2899SCharles.Forsyth ac = a->ac;
14737da2899SCharles.Forsyth eac = a->ac + a->nsend;
14837da2899SCharles.Forsyth while(ac < eac) {
14937da2899SCharles.Forsyth c = ac->c;
15037da2899SCharles.Forsyth if(c != H) {
15137da2899SCharles.Forsyth if(c->send->prog)
15237da2899SCharles.Forsyth cqdelp(&c->send, p);
15337da2899SCharles.Forsyth if(sr == 0 && c == sel) {
15437da2899SCharles.Forsyth p->ptr = ac->ptr;
15537da2899SCharles.Forsyth W(p->R.d) = n;
15637da2899SCharles.Forsyth sel = nil;
15737da2899SCharles.Forsyth }
15837da2899SCharles.Forsyth }
15937da2899SCharles.Forsyth ac++;
16037da2899SCharles.Forsyth n++;
16137da2899SCharles.Forsyth }
16237da2899SCharles.Forsyth
16337da2899SCharles.Forsyth eac = a->ac + a->nsend + a->nrecv;
16437da2899SCharles.Forsyth while(ac < eac) {
16537da2899SCharles.Forsyth c = ac->c;
16637da2899SCharles.Forsyth if(c != H) {
16737da2899SCharles.Forsyth t = D2H(c)->t;
16837da2899SCharles.Forsyth if(t == &Tarray)
16937da2899SCharles.Forsyth altunmark(c, ac->ptr, p, sr, &sel, n);
17037da2899SCharles.Forsyth else {
17137da2899SCharles.Forsyth if(c->recv->prog)
17237da2899SCharles.Forsyth cqdelp(&c->recv, p);
17337da2899SCharles.Forsyth if(sr == 1 && c == sel) {
17437da2899SCharles.Forsyth p->ptr = ac->ptr;
17537da2899SCharles.Forsyth W(p->R.d) = n;
17637da2899SCharles.Forsyth sel = nil;
17737da2899SCharles.Forsyth }
17837da2899SCharles.Forsyth }
17937da2899SCharles.Forsyth }
18037da2899SCharles.Forsyth ac++;
18137da2899SCharles.Forsyth n++;
18237da2899SCharles.Forsyth }
18337da2899SCharles.Forsyth }
18437da2899SCharles.Forsyth
18537da2899SCharles.Forsyth /*
18637da2899SCharles.Forsyth * ALT Pass 2 - Perform the communication on the chosen channel
18737da2899SCharles.Forsyth */
18837da2899SCharles.Forsyth static void
altcomm(Alt * a,int which)18937da2899SCharles.Forsyth altcomm(Alt *a, int which)
19037da2899SCharles.Forsyth {
19137da2899SCharles.Forsyth Type *t;
19237da2899SCharles.Forsyth Array *r;
19337da2899SCharles.Forsyth int n, an;
19437da2899SCharles.Forsyth WORD *ptr;
19537da2899SCharles.Forsyth Altc *ac, *eac;
19637da2899SCharles.Forsyth Channel *c, **ca, **ec;
19737da2899SCharles.Forsyth
19837da2899SCharles.Forsyth n = 0;
19937da2899SCharles.Forsyth ac = a->ac;
20037da2899SCharles.Forsyth eac = ac + a->nsend;
20137da2899SCharles.Forsyth while(ac < eac) {
20237da2899SCharles.Forsyth c = ac->c;
20337da2899SCharles.Forsyth if((c->recv->prog != nil || CANPUT(c)) && which-- == 0) {
20437da2899SCharles.Forsyth W(R.d) = n;
20537da2899SCharles.Forsyth R.s = ac->ptr;
20637da2899SCharles.Forsyth R.d = &c;
20737da2899SCharles.Forsyth isend();
20837da2899SCharles.Forsyth return;
20937da2899SCharles.Forsyth }
21037da2899SCharles.Forsyth ac++;
21137da2899SCharles.Forsyth n++;
21237da2899SCharles.Forsyth }
21337da2899SCharles.Forsyth
21437da2899SCharles.Forsyth eac = eac + a->nrecv;
21537da2899SCharles.Forsyth while(ac < eac) {
21637da2899SCharles.Forsyth c = ac->c;
21737da2899SCharles.Forsyth t = D2H(c)->t;
21837da2899SCharles.Forsyth if(t == &Tarray) {
21937da2899SCharles.Forsyth an = 0;
22037da2899SCharles.Forsyth r = (Array*)c;
22137da2899SCharles.Forsyth ca = (Channel**)r->data;
22237da2899SCharles.Forsyth ec = ca + r->len;
22337da2899SCharles.Forsyth while(ca < ec) {
22437da2899SCharles.Forsyth c = *ca;
22537da2899SCharles.Forsyth if(c != H && (c->send->prog != nil || CANGET(c)) && which-- == 0) {
22637da2899SCharles.Forsyth W(R.d) = n;
22737da2899SCharles.Forsyth R.s = &c;
22837da2899SCharles.Forsyth ptr = ac->ptr;
22937da2899SCharles.Forsyth R.d = ptr + 1;
23037da2899SCharles.Forsyth ptr[0] = an;
23137da2899SCharles.Forsyth irecv();
23237da2899SCharles.Forsyth return;
23337da2899SCharles.Forsyth }
23437da2899SCharles.Forsyth ca++;
23537da2899SCharles.Forsyth an++;
23637da2899SCharles.Forsyth }
23737da2899SCharles.Forsyth }
23837da2899SCharles.Forsyth else
23937da2899SCharles.Forsyth if((c->send->prog != nil || CANGET(c)) && which-- == 0) {
24037da2899SCharles.Forsyth W(R.d) = n;
24137da2899SCharles.Forsyth R.s = &c;
24237da2899SCharles.Forsyth R.d = ac->ptr;
24337da2899SCharles.Forsyth irecv();
24437da2899SCharles.Forsyth return;
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth ac++;
24737da2899SCharles.Forsyth n++;
24837da2899SCharles.Forsyth }
24937da2899SCharles.Forsyth return;
25037da2899SCharles.Forsyth }
25137da2899SCharles.Forsyth
25237da2899SCharles.Forsyth void
altgone(Prog * p)25337da2899SCharles.Forsyth altgone(Prog *p)
25437da2899SCharles.Forsyth {
25537da2899SCharles.Forsyth Alt *a;
25637da2899SCharles.Forsyth
25737da2899SCharles.Forsyth if (p->state == Palt) {
25837da2899SCharles.Forsyth a = p->R.s;
25937da2899SCharles.Forsyth altdone(a, p, nil, -1);
26037da2899SCharles.Forsyth p->kill = "alt channel hungup";
26137da2899SCharles.Forsyth addrun(p);
26237da2899SCharles.Forsyth }
26337da2899SCharles.Forsyth }
26437da2899SCharles.Forsyth
26537da2899SCharles.Forsyth void
xecalt(int block)26637da2899SCharles.Forsyth xecalt(int block)
26737da2899SCharles.Forsyth {
26837da2899SCharles.Forsyth Alt *a;
26937da2899SCharles.Forsyth Prog *p;
27037da2899SCharles.Forsyth int nrdy;
271*2a409d9cSCharles.Forsyth static ulong xrand = 0x20342;
27237da2899SCharles.Forsyth
27337da2899SCharles.Forsyth p = currun();
27437da2899SCharles.Forsyth
27537da2899SCharles.Forsyth a = R.s;
27637da2899SCharles.Forsyth nrdy = altrdy(a, p);
27737da2899SCharles.Forsyth if(nrdy == 0) {
27837da2899SCharles.Forsyth if(block) {
27937da2899SCharles.Forsyth delrun(Palt);
28037da2899SCharles.Forsyth p->R.s = R.s;
28137da2899SCharles.Forsyth p->R.d = R.d;
28237da2899SCharles.Forsyth R.IC = 1;
28337da2899SCharles.Forsyth R.t = 1;
28437da2899SCharles.Forsyth return;
28537da2899SCharles.Forsyth }
28637da2899SCharles.Forsyth W(R.d) = a->nsend + a->nrecv;
28737da2899SCharles.Forsyth altdone(a, p, nil, -1);
28837da2899SCharles.Forsyth return;
28937da2899SCharles.Forsyth }
29037da2899SCharles.Forsyth
291*2a409d9cSCharles.Forsyth xrand = xrand*1103515245 + 12345;
292*2a409d9cSCharles.Forsyth altcomm(a, (xrand>>8)%nrdy);
29337da2899SCharles.Forsyth altdone(a, p, nil, -1);
29437da2899SCharles.Forsyth }
295