137da2899SCharles.Forsyth #include "dat.h"
237da2899SCharles.Forsyth #include "fns.h"
337da2899SCharles.Forsyth #include <isa.h>
437da2899SCharles.Forsyth #include <interp.h>
537da2899SCharles.Forsyth #include <kernel.h>
637da2899SCharles.Forsyth #include "error.h"
737da2899SCharles.Forsyth #include "raise.h"
837da2899SCharles.Forsyth
937da2899SCharles.Forsyth struct
1037da2899SCharles.Forsyth {
1137da2899SCharles.Forsyth Lock l;
1237da2899SCharles.Forsyth Prog* runhd;
1337da2899SCharles.Forsyth Prog* runtl;
1437da2899SCharles.Forsyth Prog* head;
1537da2899SCharles.Forsyth Prog* tail;
1637da2899SCharles.Forsyth Rendez irend;
1737da2899SCharles.Forsyth int idle;
1837da2899SCharles.Forsyth int nyield;
1937da2899SCharles.Forsyth int creating;
2037da2899SCharles.Forsyth Proc* vmq; /* queue of procs wanting vm */
2137da2899SCharles.Forsyth Proc* vmqt;
2237da2899SCharles.Forsyth Proc* idlevmq; /* queue of procs wanting work */
2337da2899SCharles.Forsyth Atidle* idletasks;
2437da2899SCharles.Forsyth } isched;
2537da2899SCharles.Forsyth
2637da2899SCharles.Forsyth int bflag;
2737da2899SCharles.Forsyth int cflag;
2837da2899SCharles.Forsyth uvlong gcbusy;
2937da2899SCharles.Forsyth uvlong gcidle;
3037da2899SCharles.Forsyth uvlong gcidlepass;
3137da2899SCharles.Forsyth uvlong gcpartial;
3237da2899SCharles.Forsyth int keepbroken = 1;
3337da2899SCharles.Forsyth extern int vflag;
3437da2899SCharles.Forsyth static Prog* proghash[64];
3537da2899SCharles.Forsyth
3637da2899SCharles.Forsyth static Progs* delgrp(Prog*);
3737da2899SCharles.Forsyth static void addgrp(Prog*, Prog*);
3837da2899SCharles.Forsyth void printgrp(Prog*, char*);
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth static Prog**
pidlook(int pid)4137da2899SCharles.Forsyth pidlook(int pid)
4237da2899SCharles.Forsyth {
4337da2899SCharles.Forsyth ulong h;
4437da2899SCharles.Forsyth Prog **l;
4537da2899SCharles.Forsyth
4637da2899SCharles.Forsyth h = (ulong)pid % nelem(proghash);
4737da2899SCharles.Forsyth for(l = &proghash[h]; *l != nil && (*l)->pid != pid; l = &(*l)->pidlink)
4837da2899SCharles.Forsyth ;
4937da2899SCharles.Forsyth return l;
5037da2899SCharles.Forsyth }
5137da2899SCharles.Forsyth
5237da2899SCharles.Forsyth int
tready(void * a)5337da2899SCharles.Forsyth tready(void *a)
5437da2899SCharles.Forsyth {
5537da2899SCharles.Forsyth USED(a);
5637da2899SCharles.Forsyth return isched.runhd != nil || isched.vmq != nil;
5737da2899SCharles.Forsyth }
5837da2899SCharles.Forsyth
5937da2899SCharles.Forsyth Prog*
progpid(int pid)6037da2899SCharles.Forsyth progpid(int pid)
6137da2899SCharles.Forsyth {
6237da2899SCharles.Forsyth return *pidlook(pid);
6337da2899SCharles.Forsyth }
6437da2899SCharles.Forsyth
6537da2899SCharles.Forsyth Prog*
progn(int n)6637da2899SCharles.Forsyth progn(int n)
6737da2899SCharles.Forsyth {
6837da2899SCharles.Forsyth Prog *p;
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth for(p = isched.head; p && n--; p = p->next)
7137da2899SCharles.Forsyth ;
7237da2899SCharles.Forsyth return p;
7337da2899SCharles.Forsyth }
7437da2899SCharles.Forsyth
7537da2899SCharles.Forsyth int
nprog(void)7637da2899SCharles.Forsyth nprog(void)
7737da2899SCharles.Forsyth {
7837da2899SCharles.Forsyth int n;
7937da2899SCharles.Forsyth Prog *p;
8037da2899SCharles.Forsyth
8137da2899SCharles.Forsyth n = 0;
8237da2899SCharles.Forsyth for(p = isched.head; p; p = p->next)
8337da2899SCharles.Forsyth n++;
8437da2899SCharles.Forsyth return n;
8537da2899SCharles.Forsyth }
8637da2899SCharles.Forsyth
8737da2899SCharles.Forsyth static void
execatidle(void)8837da2899SCharles.Forsyth execatidle(void)
8937da2899SCharles.Forsyth {
9037da2899SCharles.Forsyth int done;
9137da2899SCharles.Forsyth
9237da2899SCharles.Forsyth if(tready(nil))
9337da2899SCharles.Forsyth return;
9437da2899SCharles.Forsyth
9537da2899SCharles.Forsyth gcidle++;
9637da2899SCharles.Forsyth up->type = IdleGC;
9737da2899SCharles.Forsyth up->iprog = nil;
9837da2899SCharles.Forsyth addrun(up->prog);
9937da2899SCharles.Forsyth done = gccolor+3;
10037da2899SCharles.Forsyth while(gccolor < done && gcruns()) {
10137da2899SCharles.Forsyth if(isched.vmq != nil || isched.runhd != isched.runtl) {
10237da2899SCharles.Forsyth gcpartial++;
10337da2899SCharles.Forsyth break;
10437da2899SCharles.Forsyth }
10537da2899SCharles.Forsyth rungc(isched.head);
10637da2899SCharles.Forsyth gcidlepass++;
107112f90aeSforsyth if(((ulong)gcidlepass&0xFF) == 0)
10837da2899SCharles.Forsyth osyield();
10937da2899SCharles.Forsyth }
11037da2899SCharles.Forsyth up->type = Interp;
11137da2899SCharles.Forsyth delrunq(up->prog);
11237da2899SCharles.Forsyth }
11337da2899SCharles.Forsyth
11437da2899SCharles.Forsyth Prog*
newprog(Prog * p,Modlink * m)11537da2899SCharles.Forsyth newprog(Prog *p, Modlink *m)
11637da2899SCharles.Forsyth {
11737da2899SCharles.Forsyth Heap *h;
11837da2899SCharles.Forsyth Prog *n, **ph;
11937da2899SCharles.Forsyth Osenv *on, *op;
12037da2899SCharles.Forsyth static int pidnum;
12137da2899SCharles.Forsyth
12263ef3c30SCharles.Forsyth if(p != nil){
12363ef3c30SCharles.Forsyth if(p->group != nil)
12463ef3c30SCharles.Forsyth p->flags |= p->group->flags & Pkilled;
12563ef3c30SCharles.Forsyth if(p->kill != nil)
12663ef3c30SCharles.Forsyth error(p->kill);
12763ef3c30SCharles.Forsyth if(p->flags & Pkilled)
12863ef3c30SCharles.Forsyth error("");
12963ef3c30SCharles.Forsyth }
13037da2899SCharles.Forsyth n = malloc(sizeof(Prog)+sizeof(Osenv));
13137da2899SCharles.Forsyth if(n == 0){
13237da2899SCharles.Forsyth if(p == nil)
13337da2899SCharles.Forsyth panic("no memory");
13437da2899SCharles.Forsyth else
13537da2899SCharles.Forsyth error(exNomem);
13637da2899SCharles.Forsyth }
13737da2899SCharles.Forsyth
13837da2899SCharles.Forsyth n->pid = ++pidnum;
13937da2899SCharles.Forsyth if(n->pid <= 0)
14037da2899SCharles.Forsyth panic("no pids");
14137da2899SCharles.Forsyth n->group = nil;
14237da2899SCharles.Forsyth
14337da2899SCharles.Forsyth if(isched.tail != nil) {
14437da2899SCharles.Forsyth n->prev = isched.tail;
14537da2899SCharles.Forsyth isched.tail->next = n;
14637da2899SCharles.Forsyth }
14737da2899SCharles.Forsyth else {
14837da2899SCharles.Forsyth isched.head = n;
14937da2899SCharles.Forsyth n->prev = nil;
15037da2899SCharles.Forsyth }
15137da2899SCharles.Forsyth isched.tail = n;
15237da2899SCharles.Forsyth
15337da2899SCharles.Forsyth ph = pidlook(n->pid);
15437da2899SCharles.Forsyth if(*ph != nil)
15537da2899SCharles.Forsyth panic("dup pid");
15637da2899SCharles.Forsyth n->pidlink = nil;
15737da2899SCharles.Forsyth *ph = n;
15837da2899SCharles.Forsyth
15937da2899SCharles.Forsyth n->osenv = (Osenv*)((uchar*)n + sizeof(Prog));
16037da2899SCharles.Forsyth n->xec = xec;
16137da2899SCharles.Forsyth n->quanta = PQUANTA;
16237da2899SCharles.Forsyth n->flags = 0;
16337da2899SCharles.Forsyth n->exval = H;
16437da2899SCharles.Forsyth
16537da2899SCharles.Forsyth h = D2H(m);
16637da2899SCharles.Forsyth h->ref++;
16737da2899SCharles.Forsyth Setmark(h);
16837da2899SCharles.Forsyth n->R.M = m;
16937da2899SCharles.Forsyth n->R.MP = m->MP;
17037da2899SCharles.Forsyth if(m->MP != H)
17137da2899SCharles.Forsyth Setmark(D2H(m->MP));
17237da2899SCharles.Forsyth addrun(n);
17337da2899SCharles.Forsyth
17437da2899SCharles.Forsyth if(p == nil){
17537da2899SCharles.Forsyth newgrp(n);
17637da2899SCharles.Forsyth return n;
17737da2899SCharles.Forsyth }
17837da2899SCharles.Forsyth
17937da2899SCharles.Forsyth addgrp(n, p);
18037da2899SCharles.Forsyth n->flags = p->flags;
18137da2899SCharles.Forsyth if(p->flags & Prestrict)
18237da2899SCharles.Forsyth n->flags |= Prestricted;
18337da2899SCharles.Forsyth memmove(n->osenv, p->osenv, sizeof(Osenv));
18437da2899SCharles.Forsyth op = p->osenv;
18537da2899SCharles.Forsyth on = n->osenv;
18637da2899SCharles.Forsyth on->waitq = op->childq;
18737da2899SCharles.Forsyth on->childq = nil;
18837da2899SCharles.Forsyth on->debug = nil;
18937da2899SCharles.Forsyth incref(&on->pgrp->r);
19037da2899SCharles.Forsyth incref(&on->fgrp->r);
19137da2899SCharles.Forsyth incref(&on->egrp->r);
19237da2899SCharles.Forsyth if(on->sigs != nil)
19337da2899SCharles.Forsyth incref(&on->sigs->r);
19437da2899SCharles.Forsyth on->user = nil;
19537da2899SCharles.Forsyth kstrdup(&on->user, op->user);
19637da2899SCharles.Forsyth on->errstr = on->errbuf0;
19737da2899SCharles.Forsyth on->syserrstr = on->errbuf1;
19837da2899SCharles.Forsyth
19937da2899SCharles.Forsyth return n;
20037da2899SCharles.Forsyth }
20137da2899SCharles.Forsyth
20237da2899SCharles.Forsyth void
delprog(Prog * p,char * msg)20337da2899SCharles.Forsyth delprog(Prog *p, char *msg)
20437da2899SCharles.Forsyth {
20537da2899SCharles.Forsyth Osenv *o;
20637da2899SCharles.Forsyth Prog **ph;
20737da2899SCharles.Forsyth
20837da2899SCharles.Forsyth tellsomeone(p, msg); /* call before being removed from prog list */
20937da2899SCharles.Forsyth
21037da2899SCharles.Forsyth o = p->osenv;
21137da2899SCharles.Forsyth release();
21237da2899SCharles.Forsyth closepgrp(o->pgrp);
21337da2899SCharles.Forsyth closefgrp(o->fgrp);
21437da2899SCharles.Forsyth closeegrp(o->egrp);
21537da2899SCharles.Forsyth closesigs(o->sigs);
21637da2899SCharles.Forsyth acquire();
21737da2899SCharles.Forsyth
21837da2899SCharles.Forsyth delgrp(p);
21937da2899SCharles.Forsyth
22037da2899SCharles.Forsyth if(p->prev)
22137da2899SCharles.Forsyth p->prev->next = p->next;
22237da2899SCharles.Forsyth else
22337da2899SCharles.Forsyth isched.head = p->next;
22437da2899SCharles.Forsyth
22537da2899SCharles.Forsyth if(p->next)
22637da2899SCharles.Forsyth p->next->prev = p->prev;
22737da2899SCharles.Forsyth else
22837da2899SCharles.Forsyth isched.tail = p->prev;
22937da2899SCharles.Forsyth
23037da2899SCharles.Forsyth ph = pidlook(p->pid);
23137da2899SCharles.Forsyth if(*ph == nil)
23237da2899SCharles.Forsyth panic("lost pid");
23337da2899SCharles.Forsyth *ph = p->pidlink;
23437da2899SCharles.Forsyth
23537da2899SCharles.Forsyth if(p == isched.runhd) {
23637da2899SCharles.Forsyth isched.runhd = p->link;
23737da2899SCharles.Forsyth if(p->link == nil)
23837da2899SCharles.Forsyth isched.runtl = nil;
23937da2899SCharles.Forsyth }
24037da2899SCharles.Forsyth p->state = 0xdeadbeef;
24137da2899SCharles.Forsyth free(o->user);
24237da2899SCharles.Forsyth free(p->killstr);
24337da2899SCharles.Forsyth free(p->exstr);
24437da2899SCharles.Forsyth free(p);
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth
24737da2899SCharles.Forsyth void
renameproguser(char * old,char * new)24837da2899SCharles.Forsyth renameproguser(char *old, char *new)
24937da2899SCharles.Forsyth {
25037da2899SCharles.Forsyth Prog *p;
25137da2899SCharles.Forsyth Osenv *o;
25237da2899SCharles.Forsyth
25337da2899SCharles.Forsyth acquire();
25437da2899SCharles.Forsyth for(p = isched.head; p; p = p->next){
25537da2899SCharles.Forsyth o = p->osenv;
25637da2899SCharles.Forsyth if(o->user != nil && strcmp(o->user, old) == 0)
25737da2899SCharles.Forsyth kstrdup(&o->user, new);
25837da2899SCharles.Forsyth }
25937da2899SCharles.Forsyth release();
26037da2899SCharles.Forsyth }
26137da2899SCharles.Forsyth
26237da2899SCharles.Forsyth void
tellsomeone(Prog * p,char * buf)26337da2899SCharles.Forsyth tellsomeone(Prog *p, char *buf)
26437da2899SCharles.Forsyth {
26537da2899SCharles.Forsyth Osenv *o;
26637da2899SCharles.Forsyth
26737da2899SCharles.Forsyth if(waserror())
26837da2899SCharles.Forsyth return;
26937da2899SCharles.Forsyth o = p->osenv;
27037da2899SCharles.Forsyth if(o->childq != nil)
27137da2899SCharles.Forsyth qproduce(o->childq, buf, strlen(buf));
27237da2899SCharles.Forsyth if(o->waitq != nil)
27337da2899SCharles.Forsyth qproduce(o->waitq, buf, strlen(buf));
27437da2899SCharles.Forsyth poperror();
27537da2899SCharles.Forsyth }
27637da2899SCharles.Forsyth
27737da2899SCharles.Forsyth static void
swiprog(Prog * p)27837da2899SCharles.Forsyth swiprog(Prog *p)
27937da2899SCharles.Forsyth {
28037da2899SCharles.Forsyth Proc *q;
28137da2899SCharles.Forsyth
28237da2899SCharles.Forsyth lock(&procs.l);
28337da2899SCharles.Forsyth for(q = procs.head; q; q = q->next) {
28437da2899SCharles.Forsyth if(q->iprog == p) {
28537da2899SCharles.Forsyth unlock(&procs.l);
28637da2899SCharles.Forsyth swiproc(q, 1);
28737da2899SCharles.Forsyth return;
28837da2899SCharles.Forsyth }
28937da2899SCharles.Forsyth }
29037da2899SCharles.Forsyth unlock(&procs.l);
29137da2899SCharles.Forsyth /*print("didn't find\n");*/
29237da2899SCharles.Forsyth }
29337da2899SCharles.Forsyth
29437da2899SCharles.Forsyth static Prog*
grpleader(Prog * p)29537da2899SCharles.Forsyth grpleader(Prog *p)
29637da2899SCharles.Forsyth {
29737da2899SCharles.Forsyth Progs *g;
29837da2899SCharles.Forsyth Prog *l;
29937da2899SCharles.Forsyth
30037da2899SCharles.Forsyth g = p->group;
30137da2899SCharles.Forsyth if(g != nil && (l = g->head) != nil && l->pid == g->id)
30237da2899SCharles.Forsyth return l;
30337da2899SCharles.Forsyth return nil;
30437da2899SCharles.Forsyth }
30537da2899SCharles.Forsyth
30637da2899SCharles.Forsyth int
exprog(Prog * p,char * exc)30737da2899SCharles.Forsyth exprog(Prog *p, char *exc)
30837da2899SCharles.Forsyth {
30937da2899SCharles.Forsyth /* similar code to killprog but not quite */
31037da2899SCharles.Forsyth switch(p->state) {
31137da2899SCharles.Forsyth case Palt:
31237da2899SCharles.Forsyth altdone(p->R.s, p, nil, -1);
31337da2899SCharles.Forsyth break;
31437da2899SCharles.Forsyth case Psend:
31537da2899SCharles.Forsyth cqdelp(&p->chan->send, p);
31637da2899SCharles.Forsyth break;
31737da2899SCharles.Forsyth case Precv:
31837da2899SCharles.Forsyth cqdelp(&p->chan->recv, p);
31937da2899SCharles.Forsyth break;
32037da2899SCharles.Forsyth case Pready:
32137da2899SCharles.Forsyth break;
32237da2899SCharles.Forsyth case Prelease:
32337da2899SCharles.Forsyth swiprog(p);
32437da2899SCharles.Forsyth break;
32537da2899SCharles.Forsyth case Pexiting:
32637da2899SCharles.Forsyth case Pbroken:
32737da2899SCharles.Forsyth case Pdebug:
32837da2899SCharles.Forsyth return 0;
32937da2899SCharles.Forsyth default:
33037da2899SCharles.Forsyth panic("exprog - bad state 0x%x\n", p->state);
33137da2899SCharles.Forsyth }
33237da2899SCharles.Forsyth if(p->state != Pready && p->state != Prelease)
33337da2899SCharles.Forsyth addrun(p);
33437da2899SCharles.Forsyth if(p->kill == nil){
33537da2899SCharles.Forsyth if(p->killstr == nil){
33637da2899SCharles.Forsyth p->killstr = malloc(ERRMAX);
33737da2899SCharles.Forsyth if(p->killstr == nil){
33837da2899SCharles.Forsyth p->kill = Enomem;
33937da2899SCharles.Forsyth return 1;
34037da2899SCharles.Forsyth }
34137da2899SCharles.Forsyth }
34237da2899SCharles.Forsyth kstrcpy(p->killstr, exc, ERRMAX);
34337da2899SCharles.Forsyth p->kill = p->killstr;
34437da2899SCharles.Forsyth }
34537da2899SCharles.Forsyth return 1;
34637da2899SCharles.Forsyth }
34737da2899SCharles.Forsyth
34837da2899SCharles.Forsyth static void
propex(Prog * p,char * estr)34937da2899SCharles.Forsyth propex(Prog *p, char *estr)
35037da2899SCharles.Forsyth {
35137da2899SCharles.Forsyth Prog *f, *nf, *pgl;
35237da2899SCharles.Forsyth
35337da2899SCharles.Forsyth if(!(p->flags & (Ppropagate|Pnotifyleader)) || p->group == nil)
35437da2899SCharles.Forsyth return;
35537da2899SCharles.Forsyth if(*estr == 0){
35637da2899SCharles.Forsyth if((p->flags & Pkilled) == 0)
35737da2899SCharles.Forsyth return;
35837da2899SCharles.Forsyth estr = "killed";
35937da2899SCharles.Forsyth }
36037da2899SCharles.Forsyth pgl = grpleader(p);
36137da2899SCharles.Forsyth if(pgl == nil)
36237da2899SCharles.Forsyth pgl = p;
36337da2899SCharles.Forsyth if(!(pgl->flags & (Ppropagate|Pnotifyleader)))
36437da2899SCharles.Forsyth return; /* exceptions are local; don't propagate */
36537da2899SCharles.Forsyth for(f = p->group->head; f != nil; f = nf){
36637da2899SCharles.Forsyth nf = f->grpnext;
36737da2899SCharles.Forsyth if(f != p && f != pgl){
36837da2899SCharles.Forsyth if(pgl->flags & Ppropagate)
36937da2899SCharles.Forsyth exprog(f, estr);
37037da2899SCharles.Forsyth else{
37137da2899SCharles.Forsyth f->flags &= ~(Ppropagate|Pnotifyleader); /* prevent recursion */
37237da2899SCharles.Forsyth killprog(f, "killed");
37337da2899SCharles.Forsyth }
37437da2899SCharles.Forsyth }
37537da2899SCharles.Forsyth }
37637da2899SCharles.Forsyth if(p != pgl)
37737da2899SCharles.Forsyth exprog(pgl, estr);
37837da2899SCharles.Forsyth }
37937da2899SCharles.Forsyth
38037da2899SCharles.Forsyth int
killprog(Prog * p,char * cause)38137da2899SCharles.Forsyth killprog(Prog *p, char *cause)
38237da2899SCharles.Forsyth {
38337da2899SCharles.Forsyth Osenv *env;
38437da2899SCharles.Forsyth char msg[ERRMAX+2*KNAMELEN];
38537da2899SCharles.Forsyth
38637da2899SCharles.Forsyth if(p == isched.runhd) {
38737da2899SCharles.Forsyth p->kill = "";
38837da2899SCharles.Forsyth p->flags |= Pkilled;
38937da2899SCharles.Forsyth p->state = Pexiting;
39037da2899SCharles.Forsyth return 0;
39137da2899SCharles.Forsyth }
39237da2899SCharles.Forsyth
39337da2899SCharles.Forsyth switch(p->state) {
39437da2899SCharles.Forsyth case Palt:
39537da2899SCharles.Forsyth altdone(p->R.s, p, nil, -1);
39637da2899SCharles.Forsyth break;
39737da2899SCharles.Forsyth case Psend:
39837da2899SCharles.Forsyth cqdelp(&p->chan->send, p);
39937da2899SCharles.Forsyth break;
40037da2899SCharles.Forsyth case Precv:
40137da2899SCharles.Forsyth cqdelp(&p->chan->recv, p);
40237da2899SCharles.Forsyth break;
40337da2899SCharles.Forsyth case Pready:
40437da2899SCharles.Forsyth delrunq(p);
40537da2899SCharles.Forsyth break;
40637da2899SCharles.Forsyth case Prelease:
40737da2899SCharles.Forsyth p->kill = "";
40837da2899SCharles.Forsyth p->flags |= Pkilled;
40937da2899SCharles.Forsyth p->state = Pexiting;
41037da2899SCharles.Forsyth swiprog(p);
41137da2899SCharles.Forsyth /* No break */
41237da2899SCharles.Forsyth case Pexiting:
41337da2899SCharles.Forsyth return 0;
41437da2899SCharles.Forsyth case Pbroken:
41537da2899SCharles.Forsyth case Pdebug:
41637da2899SCharles.Forsyth break;
41737da2899SCharles.Forsyth default:
41837da2899SCharles.Forsyth panic("killprog - bad state 0x%x\n", p->state);
41937da2899SCharles.Forsyth }
42037da2899SCharles.Forsyth
42137da2899SCharles.Forsyth if(p->addrun != nil) {
42237da2899SCharles.Forsyth p->kill = "";
42337da2899SCharles.Forsyth p->flags |= Pkilled;
42437da2899SCharles.Forsyth p->addrun(p);
42537da2899SCharles.Forsyth p->addrun = nil;
42637da2899SCharles.Forsyth return 0;
42737da2899SCharles.Forsyth }
42837da2899SCharles.Forsyth
42937da2899SCharles.Forsyth env = p->osenv;
43037da2899SCharles.Forsyth if(env->debug != nil) {
43137da2899SCharles.Forsyth p->state = Pbroken;
43237da2899SCharles.Forsyth dbgexit(p, 0, cause);
43337da2899SCharles.Forsyth return 0;
43437da2899SCharles.Forsyth }
43537da2899SCharles.Forsyth
43637da2899SCharles.Forsyth propex(p, "killed");
43737da2899SCharles.Forsyth
43837da2899SCharles.Forsyth snprint(msg, sizeof(msg), "%d \"%s\":%s", p->pid, p->R.M->m->name, cause);
43937da2899SCharles.Forsyth
44037da2899SCharles.Forsyth p->state = Pexiting;
44137da2899SCharles.Forsyth gclock();
44237da2899SCharles.Forsyth destroystack(&p->R);
44337da2899SCharles.Forsyth delprog(p, msg);
44437da2899SCharles.Forsyth gcunlock();
44537da2899SCharles.Forsyth
44637da2899SCharles.Forsyth return 1;
44737da2899SCharles.Forsyth }
44837da2899SCharles.Forsyth
44937da2899SCharles.Forsyth void
newgrp(Prog * p)45037da2899SCharles.Forsyth newgrp(Prog *p)
45137da2899SCharles.Forsyth {
45237da2899SCharles.Forsyth Progs *pg, *g;
45337da2899SCharles.Forsyth
45437da2899SCharles.Forsyth if(p->group != nil && p->group->id == p->pid)
45537da2899SCharles.Forsyth return;
45637da2899SCharles.Forsyth g = malloc(sizeof(*g));
45737da2899SCharles.Forsyth if(g == nil)
45837da2899SCharles.Forsyth error(Enomem);
45937da2899SCharles.Forsyth p->flags &= ~(Ppropagate|Pnotifyleader);
46037da2899SCharles.Forsyth g->id = p->pid;
46137da2899SCharles.Forsyth g->flags = 0;
462*cb6deeccSforsyth if(p->group != nil)
463*cb6deeccSforsyth g->flags |= p->group->flags&Pprivatemem;
46437da2899SCharles.Forsyth g->child = nil;
46537da2899SCharles.Forsyth pg = delgrp(p);
46637da2899SCharles.Forsyth g->head = g->tail = p;
46737da2899SCharles.Forsyth p->group = g;
46837da2899SCharles.Forsyth if(pg != nil){
46937da2899SCharles.Forsyth g->sib = pg->child;
47037da2899SCharles.Forsyth pg->child = g;
47137da2899SCharles.Forsyth }
47237da2899SCharles.Forsyth g->parent = pg;
47337da2899SCharles.Forsyth }
47437da2899SCharles.Forsyth
47537da2899SCharles.Forsyth static void
addgrp(Prog * n,Prog * p)47637da2899SCharles.Forsyth addgrp(Prog *n, Prog *p)
47737da2899SCharles.Forsyth {
47837da2899SCharles.Forsyth Progs *g;
47937da2899SCharles.Forsyth
48037da2899SCharles.Forsyth n->group = p->group;
48137da2899SCharles.Forsyth if((g = n->group) != nil){
48237da2899SCharles.Forsyth n->grpnext = nil;
48337da2899SCharles.Forsyth if(g->head != nil){
48437da2899SCharles.Forsyth n->grpprev = g->tail;
48537da2899SCharles.Forsyth g->tail->grpnext = n;
48637da2899SCharles.Forsyth }else{
48737da2899SCharles.Forsyth n->grpprev = nil;
48837da2899SCharles.Forsyth g->head = n;
48937da2899SCharles.Forsyth }
49037da2899SCharles.Forsyth g->tail = n;
49137da2899SCharles.Forsyth }
49237da2899SCharles.Forsyth }
49337da2899SCharles.Forsyth
49437da2899SCharles.Forsyth static Progs*
delgrp(Prog * p)49537da2899SCharles.Forsyth delgrp(Prog *p)
49637da2899SCharles.Forsyth {
49737da2899SCharles.Forsyth Progs *g, *pg, *cg, **l;
49837da2899SCharles.Forsyth
49937da2899SCharles.Forsyth g = p->group;
50037da2899SCharles.Forsyth if(g == nil)
50137da2899SCharles.Forsyth return nil;
50237da2899SCharles.Forsyth if(p->grpprev)
50337da2899SCharles.Forsyth p->grpprev->grpnext = p->grpnext;
50437da2899SCharles.Forsyth else
50537da2899SCharles.Forsyth g->head = p->grpnext;
50637da2899SCharles.Forsyth if(p->grpnext)
50737da2899SCharles.Forsyth p->grpnext->grpprev = p->grpprev;
50837da2899SCharles.Forsyth else
50937da2899SCharles.Forsyth g->tail = p->grpprev;
51037da2899SCharles.Forsyth p->grpprev = p->grpnext = nil;
51137da2899SCharles.Forsyth p->group = nil;
51237da2899SCharles.Forsyth
51337da2899SCharles.Forsyth if(g->head == nil){
51437da2899SCharles.Forsyth /* move up, giving subgroups of groups with no Progs to their parents */
51537da2899SCharles.Forsyth do{
51637da2899SCharles.Forsyth if((pg = g->parent) != nil){
51737da2899SCharles.Forsyth pg = g->parent;
51837da2899SCharles.Forsyth for(l = &pg->child; *l != nil && *l != g; l = &(*l)->sib)
51937da2899SCharles.Forsyth ;
52037da2899SCharles.Forsyth *l = g->sib;
52137da2899SCharles.Forsyth }
52237da2899SCharles.Forsyth /* put subgroups in new parent group */
52337da2899SCharles.Forsyth while((cg = g->child) != nil){
52437da2899SCharles.Forsyth g->child = cg->sib;
52537da2899SCharles.Forsyth cg->parent = pg;
52637da2899SCharles.Forsyth if(pg != nil){
52737da2899SCharles.Forsyth cg->sib = pg->child;
52837da2899SCharles.Forsyth pg->child = cg;
52937da2899SCharles.Forsyth }
53037da2899SCharles.Forsyth }
53137da2899SCharles.Forsyth free(g);
53237da2899SCharles.Forsyth }while((g = pg) != nil && g->head == nil);
53337da2899SCharles.Forsyth }
53437da2899SCharles.Forsyth return g;
53537da2899SCharles.Forsyth }
53637da2899SCharles.Forsyth
53737da2899SCharles.Forsyth void
printgrp(Prog * p,char * v)53837da2899SCharles.Forsyth printgrp(Prog *p, char *v)
53937da2899SCharles.Forsyth {
54037da2899SCharles.Forsyth Progs *g;
54137da2899SCharles.Forsyth Prog *q;
54237da2899SCharles.Forsyth
54337da2899SCharles.Forsyth g = p->group;
54437da2899SCharles.Forsyth print("%s pid %d grp %d pgrp %d: [pid", v, p->pid, g->id, g->parent!=nil?g->parent->id:0);
54537da2899SCharles.Forsyth for(q = g->head; q != nil; q = q->grpnext)
54637da2899SCharles.Forsyth print(" %d", q->pid);
54737da2899SCharles.Forsyth print(" subgrp");
54837da2899SCharles.Forsyth for(g = g->child; g != nil; g = g->sib)
54937da2899SCharles.Forsyth print(" %d", g->id);
55037da2899SCharles.Forsyth print("]\n");
55137da2899SCharles.Forsyth }
55237da2899SCharles.Forsyth
55337da2899SCharles.Forsyth int
killgrp(Prog * p,char * msg)55437da2899SCharles.Forsyth killgrp(Prog *p, char *msg)
55537da2899SCharles.Forsyth {
55637da2899SCharles.Forsyth int i, npid, *pids;
55737da2899SCharles.Forsyth Prog *f;
55837da2899SCharles.Forsyth Progs *g;
55937da2899SCharles.Forsyth
56037da2899SCharles.Forsyth /* interpreter has been acquired */
56137da2899SCharles.Forsyth g = p->group;
562d3ba796fSCharles.Forsyth if(g == nil || g->head == nil)
56337da2899SCharles.Forsyth return 0;
564d3ba796fSCharles.Forsyth while(g->flags & Pkilled){
565d3ba796fSCharles.Forsyth release();
566d3ba796fSCharles.Forsyth acquire();
567d3ba796fSCharles.Forsyth }
56837da2899SCharles.Forsyth npid = 0;
56937da2899SCharles.Forsyth for(f = g->head; f != nil; f = f->grpnext)
57037da2899SCharles.Forsyth if(f->group != g)
57137da2899SCharles.Forsyth panic("killgrp");
57237da2899SCharles.Forsyth else
57337da2899SCharles.Forsyth npid++;
57463ef3c30SCharles.Forsyth /* use pids not Prog* because state can change during killprog (eg, in delprog) */
57537da2899SCharles.Forsyth pids = malloc(npid*sizeof(int));
57637da2899SCharles.Forsyth if(pids == nil)
57737da2899SCharles.Forsyth error(Enomem);
57837da2899SCharles.Forsyth npid = 0;
57937da2899SCharles.Forsyth for(f = g->head; f != nil; f = f->grpnext)
58037da2899SCharles.Forsyth pids[npid++] = f->pid;
58163ef3c30SCharles.Forsyth g->flags |= Pkilled;
58237da2899SCharles.Forsyth if(waserror()) {
58363ef3c30SCharles.Forsyth g->flags &= ~Pkilled;
58437da2899SCharles.Forsyth free(pids);
58537da2899SCharles.Forsyth nexterror();
58637da2899SCharles.Forsyth }
58737da2899SCharles.Forsyth for(i = 0; i < npid; i++) {
58837da2899SCharles.Forsyth f = progpid(pids[i]);
58937da2899SCharles.Forsyth if(f != nil && f != currun())
59037da2899SCharles.Forsyth killprog(f, msg);
59137da2899SCharles.Forsyth }
59237da2899SCharles.Forsyth poperror();
59363ef3c30SCharles.Forsyth g->flags &= ~Pkilled;
59437da2899SCharles.Forsyth free(pids);
59537da2899SCharles.Forsyth return 1;
59637da2899SCharles.Forsyth }
59737da2899SCharles.Forsyth
59837da2899SCharles.Forsyth char changup[] = "channel hangup";
59937da2899SCharles.Forsyth
60037da2899SCharles.Forsyth void
killcomm(Progq ** q)60137da2899SCharles.Forsyth killcomm(Progq **q)
60237da2899SCharles.Forsyth {
60337da2899SCharles.Forsyth Prog *p;
60437da2899SCharles.Forsyth Progq *f;
60537da2899SCharles.Forsyth
60637da2899SCharles.Forsyth for (f = *q; f != nil; f = *q) {
60737da2899SCharles.Forsyth *q = f->next;
60837da2899SCharles.Forsyth p = f->prog;
60937da2899SCharles.Forsyth free(f);
61037da2899SCharles.Forsyth if(p == nil)
61137da2899SCharles.Forsyth return;
61237da2899SCharles.Forsyth p->ptr = nil;
61337da2899SCharles.Forsyth switch(p->state) {
61437da2899SCharles.Forsyth case Prelease:
61537da2899SCharles.Forsyth swiprog(p);
61637da2899SCharles.Forsyth break;
61737da2899SCharles.Forsyth case Psend:
61837da2899SCharles.Forsyth case Precv:
61937da2899SCharles.Forsyth p->kill = changup;
62037da2899SCharles.Forsyth addrun(p);
62137da2899SCharles.Forsyth break;
62237da2899SCharles.Forsyth case Palt:
62337da2899SCharles.Forsyth altgone(p);
62437da2899SCharles.Forsyth break;
62537da2899SCharles.Forsyth }
62637da2899SCharles.Forsyth }
62737da2899SCharles.Forsyth }
62837da2899SCharles.Forsyth
62937da2899SCharles.Forsyth void
addprog(Proc * p)63037da2899SCharles.Forsyth addprog(Proc *p)
63137da2899SCharles.Forsyth {
63237da2899SCharles.Forsyth Prog *n;
63337da2899SCharles.Forsyth
63437da2899SCharles.Forsyth n = malloc(sizeof(Prog));
63537da2899SCharles.Forsyth if(n == nil)
63637da2899SCharles.Forsyth panic("no memory");
63737da2899SCharles.Forsyth p->prog = n;
63837da2899SCharles.Forsyth n->osenv = p->env;
63937da2899SCharles.Forsyth }
64037da2899SCharles.Forsyth
64137da2899SCharles.Forsyth static void
cwakeme(Prog * p)64237da2899SCharles.Forsyth cwakeme(Prog *p)
64337da2899SCharles.Forsyth {
64437da2899SCharles.Forsyth Osenv *o;
64537da2899SCharles.Forsyth
64637da2899SCharles.Forsyth p->addrun = nil;
64737da2899SCharles.Forsyth o = p->osenv;
64837da2899SCharles.Forsyth Wakeup(o->rend);
64937da2899SCharles.Forsyth }
65037da2899SCharles.Forsyth
65137da2899SCharles.Forsyth static int
cdone(void * vp)65237da2899SCharles.Forsyth cdone(void *vp)
65337da2899SCharles.Forsyth {
65437da2899SCharles.Forsyth Prog *p = vp;
65537da2899SCharles.Forsyth
65637da2899SCharles.Forsyth return p->addrun == nil || p->kill != nil;
65737da2899SCharles.Forsyth }
65837da2899SCharles.Forsyth
65937da2899SCharles.Forsyth void
cblock(Prog * p)66037da2899SCharles.Forsyth cblock(Prog *p)
66137da2899SCharles.Forsyth {
66237da2899SCharles.Forsyth Osenv *o;
66337da2899SCharles.Forsyth
66437da2899SCharles.Forsyth p->addrun = cwakeme;
66537da2899SCharles.Forsyth o = p->osenv;
66637da2899SCharles.Forsyth o->rend = &up->sleep;
66737da2899SCharles.Forsyth release();
66837da2899SCharles.Forsyth
66937da2899SCharles.Forsyth /*
67037da2899SCharles.Forsyth * To allow cdone(p) safely after release,
67137da2899SCharles.Forsyth * p must be currun before the release.
67237da2899SCharles.Forsyth * Exits in the error case with the vm acquired.
67337da2899SCharles.Forsyth */
67437da2899SCharles.Forsyth if(waserror()) {
67537da2899SCharles.Forsyth acquire();
67637da2899SCharles.Forsyth p->addrun = nil;
67737da2899SCharles.Forsyth nexterror();
67837da2899SCharles.Forsyth }
67937da2899SCharles.Forsyth Sleep(o->rend, cdone, p);
68037da2899SCharles.Forsyth if (p->kill != nil)
68137da2899SCharles.Forsyth error(Eintr);
68237da2899SCharles.Forsyth poperror();
68337da2899SCharles.Forsyth acquire();
68437da2899SCharles.Forsyth }
68537da2899SCharles.Forsyth
68637da2899SCharles.Forsyth void
addrun(Prog * p)68737da2899SCharles.Forsyth addrun(Prog *p)
68837da2899SCharles.Forsyth {
68937da2899SCharles.Forsyth if(p->addrun != 0) {
69037da2899SCharles.Forsyth p->addrun(p);
69137da2899SCharles.Forsyth return;
69237da2899SCharles.Forsyth }
69337da2899SCharles.Forsyth p->state = Pready;
69437da2899SCharles.Forsyth p->link = nil;
69537da2899SCharles.Forsyth if(isched.runhd == nil)
69637da2899SCharles.Forsyth isched.runhd = p;
69737da2899SCharles.Forsyth else
69837da2899SCharles.Forsyth isched.runtl->link = p;
69937da2899SCharles.Forsyth
70037da2899SCharles.Forsyth isched.runtl = p;
70137da2899SCharles.Forsyth }
70237da2899SCharles.Forsyth
70337da2899SCharles.Forsyth Prog*
delrun(int state)70437da2899SCharles.Forsyth delrun(int state)
70537da2899SCharles.Forsyth {
70637da2899SCharles.Forsyth Prog *p;
70737da2899SCharles.Forsyth
70837da2899SCharles.Forsyth p = isched.runhd;
70937da2899SCharles.Forsyth p->state = state;
71037da2899SCharles.Forsyth isched.runhd = p->link;
71137da2899SCharles.Forsyth if(p->link == nil)
71237da2899SCharles.Forsyth isched.runtl = nil;
71337da2899SCharles.Forsyth
71437da2899SCharles.Forsyth return p;
71537da2899SCharles.Forsyth }
71637da2899SCharles.Forsyth
71737da2899SCharles.Forsyth void
delrunq(Prog * p)71837da2899SCharles.Forsyth delrunq(Prog *p)
71937da2899SCharles.Forsyth {
72037da2899SCharles.Forsyth Prog *prev, *f;
72137da2899SCharles.Forsyth
72237da2899SCharles.Forsyth prev = nil;
72337da2899SCharles.Forsyth for(f = isched.runhd; f; f = f->link) {
72437da2899SCharles.Forsyth if(f == p)
72537da2899SCharles.Forsyth break;
72637da2899SCharles.Forsyth prev = f;
72737da2899SCharles.Forsyth }
72837da2899SCharles.Forsyth if(f == nil)
72937da2899SCharles.Forsyth return;
73037da2899SCharles.Forsyth if(prev == nil)
73137da2899SCharles.Forsyth isched.runhd = p->link;
73237da2899SCharles.Forsyth else
73337da2899SCharles.Forsyth prev->link = p->link;
73437da2899SCharles.Forsyth if(p == isched.runtl)
73537da2899SCharles.Forsyth isched.runtl = prev;
73637da2899SCharles.Forsyth }
73737da2899SCharles.Forsyth
73837da2899SCharles.Forsyth Prog*
delruntail(int state)73937da2899SCharles.Forsyth delruntail(int state)
74037da2899SCharles.Forsyth {
74137da2899SCharles.Forsyth Prog *p;
74237da2899SCharles.Forsyth
74337da2899SCharles.Forsyth p = isched.runtl;
74437da2899SCharles.Forsyth delrunq(p);
74537da2899SCharles.Forsyth p->state = state;
74637da2899SCharles.Forsyth return p;
74737da2899SCharles.Forsyth }
74837da2899SCharles.Forsyth
74937da2899SCharles.Forsyth Prog*
currun(void)75037da2899SCharles.Forsyth currun(void)
75137da2899SCharles.Forsyth {
75237da2899SCharles.Forsyth return isched.runhd;
75337da2899SCharles.Forsyth }
75437da2899SCharles.Forsyth
75537da2899SCharles.Forsyth Prog*
schedmod(Module * m)75637da2899SCharles.Forsyth schedmod(Module *m)
75737da2899SCharles.Forsyth {
75837da2899SCharles.Forsyth Heap *h;
75937da2899SCharles.Forsyth Type *t;
76037da2899SCharles.Forsyth Prog *p;
76137da2899SCharles.Forsyth Modlink *ml;
76237da2899SCharles.Forsyth Frame f, *fp;
76337da2899SCharles.Forsyth
76437da2899SCharles.Forsyth ml = mklinkmod(m, 0);
76537da2899SCharles.Forsyth
76637da2899SCharles.Forsyth if(m->origmp != H && m->ntype > 0) {
76737da2899SCharles.Forsyth t = m->type[0];
76837da2899SCharles.Forsyth h = nheap(t->size);
76937da2899SCharles.Forsyth h->t = t;
77037da2899SCharles.Forsyth t->ref++;
77137da2899SCharles.Forsyth ml->MP = H2D(uchar*, h);
77237da2899SCharles.Forsyth newmp(ml->MP, m->origmp, t);
77337da2899SCharles.Forsyth }
77437da2899SCharles.Forsyth
77537da2899SCharles.Forsyth p = newprog(nil, ml);
77637da2899SCharles.Forsyth h = D2H(ml);
77737da2899SCharles.Forsyth h->ref--;
77837da2899SCharles.Forsyth p->R.PC = m->entry;
77937da2899SCharles.Forsyth fp = &f;
78037da2899SCharles.Forsyth R.s = &fp;
78137da2899SCharles.Forsyth f.t = m->entryt;
78237da2899SCharles.Forsyth newstack(p);
78337da2899SCharles.Forsyth initmem(m->entryt, p->R.FP);
78437da2899SCharles.Forsyth
78537da2899SCharles.Forsyth return p;
78637da2899SCharles.Forsyth }
78737da2899SCharles.Forsyth
78837da2899SCharles.Forsyth /*
78937da2899SCharles.Forsyth static char*
79037da2899SCharles.Forsyth m(Prog *p)
79137da2899SCharles.Forsyth {
79237da2899SCharles.Forsyth if(p)
79337da2899SCharles.Forsyth if(p->R.M)
79437da2899SCharles.Forsyth if(p->R.M->m)
79537da2899SCharles.Forsyth return p->R.M->m->name;
79637da2899SCharles.Forsyth return "nil";
79737da2899SCharles.Forsyth }
79837da2899SCharles.Forsyth */
79937da2899SCharles.Forsyth
80037da2899SCharles.Forsyth void
acquire(void)80137da2899SCharles.Forsyth acquire(void)
80237da2899SCharles.Forsyth {
80337da2899SCharles.Forsyth int empty;
80437da2899SCharles.Forsyth Prog *p;
80537da2899SCharles.Forsyth
80637da2899SCharles.Forsyth lock(&isched.l);
80737da2899SCharles.Forsyth if(isched.idle) {
80837da2899SCharles.Forsyth isched.idle = 0;
80937da2899SCharles.Forsyth unlock(&isched.l);
81037da2899SCharles.Forsyth }
81137da2899SCharles.Forsyth else {
81237da2899SCharles.Forsyth up->qnext = nil;
81337da2899SCharles.Forsyth if(isched.vmq != nil){
81437da2899SCharles.Forsyth empty = 0;
81537da2899SCharles.Forsyth isched.vmqt->qnext = up;
81637da2899SCharles.Forsyth }else{
81737da2899SCharles.Forsyth isched.vmq = up;
81837da2899SCharles.Forsyth empty = 1;
81937da2899SCharles.Forsyth }
82037da2899SCharles.Forsyth isched.vmqt = up;
82137da2899SCharles.Forsyth
82237da2899SCharles.Forsyth unlock(&isched.l);
82337da2899SCharles.Forsyth strcpy(up->text, "acquire");
82437da2899SCharles.Forsyth if(empty)
82537da2899SCharles.Forsyth Wakeup(&isched.irend);
82637da2899SCharles.Forsyth osblock();
82737da2899SCharles.Forsyth }
82837da2899SCharles.Forsyth
82937da2899SCharles.Forsyth if(up->type == Interp) {
83037da2899SCharles.Forsyth p = up->iprog;
83137da2899SCharles.Forsyth up->iprog = nil;
83237da2899SCharles.Forsyth irestore(p);
83337da2899SCharles.Forsyth }
83437da2899SCharles.Forsyth else
83537da2899SCharles.Forsyth p = up->prog;
83637da2899SCharles.Forsyth
83737da2899SCharles.Forsyth p->state = Pready;
83837da2899SCharles.Forsyth p->link = isched.runhd;
83937da2899SCharles.Forsyth isched.runhd = p;
84037da2899SCharles.Forsyth if(p->link == nil)
84137da2899SCharles.Forsyth isched.runtl = p;
84237da2899SCharles.Forsyth
84337da2899SCharles.Forsyth strcpy(up->text, "dis");
84437da2899SCharles.Forsyth }
84537da2899SCharles.Forsyth
84637da2899SCharles.Forsyth void
release(void)84737da2899SCharles.Forsyth release(void)
84837da2899SCharles.Forsyth {
84937da2899SCharles.Forsyth Proc *p, **pq;
85037da2899SCharles.Forsyth int f;
85137da2899SCharles.Forsyth
85237da2899SCharles.Forsyth if(up->type == Interp)
85337da2899SCharles.Forsyth up->iprog = isave();
85437da2899SCharles.Forsyth else
85537da2899SCharles.Forsyth delrun(Prelease);
85637da2899SCharles.Forsyth
85737da2899SCharles.Forsyth lock(&isched.l);
85837da2899SCharles.Forsyth if(*(pq = &isched.vmq) == nil && *(pq = &isched.idlevmq) == nil) {
85937da2899SCharles.Forsyth isched.idle = 1;
86037da2899SCharles.Forsyth f = isched.creating;
86137da2899SCharles.Forsyth isched.creating = 1;
86237da2899SCharles.Forsyth unlock(&isched.l);
86337da2899SCharles.Forsyth if(f == 0)
86437da2899SCharles.Forsyth kproc("dis", vmachine, nil, 0);
86537da2899SCharles.Forsyth return;
86637da2899SCharles.Forsyth }
86737da2899SCharles.Forsyth p = *pq;
86837da2899SCharles.Forsyth *pq = p->qnext;
86937da2899SCharles.Forsyth unlock(&isched.l);
87037da2899SCharles.Forsyth
87137da2899SCharles.Forsyth osready(p); /* wake up thread to run VM */
87237da2899SCharles.Forsyth strcpy(up->text, "released");
87337da2899SCharles.Forsyth }
87437da2899SCharles.Forsyth
87537da2899SCharles.Forsyth void
iyield(void)87637da2899SCharles.Forsyth iyield(void)
87737da2899SCharles.Forsyth {
87837da2899SCharles.Forsyth Proc *p;
87937da2899SCharles.Forsyth
88037da2899SCharles.Forsyth lock(&isched.l);
88137da2899SCharles.Forsyth p = isched.vmq;
88237da2899SCharles.Forsyth if(p == nil) {
88337da2899SCharles.Forsyth unlock(&isched.l);
88437da2899SCharles.Forsyth return;
88537da2899SCharles.Forsyth }
88637da2899SCharles.Forsyth isched.nyield++;
88737da2899SCharles.Forsyth isched.vmq = p->qnext;
88837da2899SCharles.Forsyth
88937da2899SCharles.Forsyth if(up->iprog != nil)
89037da2899SCharles.Forsyth panic("iyield but iprog, type %d", up->type);
89137da2899SCharles.Forsyth if(up->type != Interp){
89237da2899SCharles.Forsyth static int once;
89337da2899SCharles.Forsyth if(!once++)
89437da2899SCharles.Forsyth print("tell charles: #%p->type==%d\n", up, up->type);
89537da2899SCharles.Forsyth }
89637da2899SCharles.Forsyth up->qnext = isched.idlevmq;
89737da2899SCharles.Forsyth isched.idlevmq = up;
89837da2899SCharles.Forsyth
89937da2899SCharles.Forsyth unlock(&isched.l);
90037da2899SCharles.Forsyth osready(p); /* wake up acquiring kproc */
90137da2899SCharles.Forsyth strcpy(up->text, "yield");
90237da2899SCharles.Forsyth osblock(); /* sleep */
90337da2899SCharles.Forsyth strcpy(up->text, "dis");
90437da2899SCharles.Forsyth }
90537da2899SCharles.Forsyth
90637da2899SCharles.Forsyth void
startup(void)90737da2899SCharles.Forsyth startup(void)
90837da2899SCharles.Forsyth {
90937da2899SCharles.Forsyth
91037da2899SCharles.Forsyth up->type = Interp;
91137da2899SCharles.Forsyth up->iprog = nil;
91237da2899SCharles.Forsyth
91337da2899SCharles.Forsyth lock(&isched.l);
91437da2899SCharles.Forsyth isched.creating = 0;
91537da2899SCharles.Forsyth if(isched.idle) {
91637da2899SCharles.Forsyth isched.idle = 0;
91737da2899SCharles.Forsyth unlock(&isched.l);
91837da2899SCharles.Forsyth return;
91937da2899SCharles.Forsyth }
92037da2899SCharles.Forsyth up->qnext = isched.idlevmq;
92137da2899SCharles.Forsyth isched.idlevmq = up;
92237da2899SCharles.Forsyth unlock(&isched.l);
92337da2899SCharles.Forsyth
92437da2899SCharles.Forsyth osblock();
92537da2899SCharles.Forsyth }
92637da2899SCharles.Forsyth
92737da2899SCharles.Forsyth void
progexit(void)92837da2899SCharles.Forsyth progexit(void)
92937da2899SCharles.Forsyth {
93037da2899SCharles.Forsyth Prog *r;
93137da2899SCharles.Forsyth Module *m;
93237da2899SCharles.Forsyth int broken;
93337da2899SCharles.Forsyth char *estr, msg[ERRMAX+2*KNAMELEN];
93437da2899SCharles.Forsyth
93537da2899SCharles.Forsyth estr = up->env->errstr;
93637da2899SCharles.Forsyth broken = 0;
93737da2899SCharles.Forsyth if(estr[0] != '\0' && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0)
93837da2899SCharles.Forsyth broken = 1;
93937da2899SCharles.Forsyth
94037da2899SCharles.Forsyth r = up->iprog;
94137da2899SCharles.Forsyth if(r != nil)
94237da2899SCharles.Forsyth acquire();
94337da2899SCharles.Forsyth else
94437da2899SCharles.Forsyth r = currun();
94537da2899SCharles.Forsyth
94637da2899SCharles.Forsyth if(*estr == '\0' && r->flags & Pkilled)
94737da2899SCharles.Forsyth estr = "killed";
94837da2899SCharles.Forsyth
94937da2899SCharles.Forsyth m = R.M->m;
95037da2899SCharles.Forsyth if(broken){
95137da2899SCharles.Forsyth if(cflag){ /* only works on Plan9 for now */
95237da2899SCharles.Forsyth char *pc = strstr(estr, "pc=");
95337da2899SCharles.Forsyth
95437da2899SCharles.Forsyth if(pc != nil)
95537da2899SCharles.Forsyth R.PC = r->R.PC = (Inst*)strtol(pc+3, nil, 0); /* for debugging */
95637da2899SCharles.Forsyth }
95737da2899SCharles.Forsyth print("[%s] Broken: \"%s\"\n", m->name, estr);
95837da2899SCharles.Forsyth }
95937da2899SCharles.Forsyth
96037da2899SCharles.Forsyth snprint(msg, sizeof(msg), "%d \"%s\":%s", r->pid, m->name, estr);
96137da2899SCharles.Forsyth
96237da2899SCharles.Forsyth if(up->env->debug != nil) {
96337da2899SCharles.Forsyth dbgexit(r, broken, estr);
96437da2899SCharles.Forsyth broken = 1;
96537da2899SCharles.Forsyth /* must force it to break if in debug */
96637da2899SCharles.Forsyth }else if(broken && (!keepbroken || strncmp(estr, "out of memory", 13)==0 || memusehigh()))
96737da2899SCharles.Forsyth broken = 0; /* don't want them or short of memory */
96837da2899SCharles.Forsyth
96937da2899SCharles.Forsyth if(broken){
97037da2899SCharles.Forsyth tellsomeone(r, msg);
97137da2899SCharles.Forsyth r = isave();
97237da2899SCharles.Forsyth r->state = Pbroken;
97337da2899SCharles.Forsyth return;
97437da2899SCharles.Forsyth }
97537da2899SCharles.Forsyth
97637da2899SCharles.Forsyth gclock();
97737da2899SCharles.Forsyth destroystack(&R);
97837da2899SCharles.Forsyth delprog(r, msg);
97937da2899SCharles.Forsyth gcunlock();
98037da2899SCharles.Forsyth
98137da2899SCharles.Forsyth if(isched.head == nil)
98237da2899SCharles.Forsyth cleanexit(0);
98337da2899SCharles.Forsyth }
98437da2899SCharles.Forsyth
98537da2899SCharles.Forsyth void
disfault(void * reg,char * msg)98637da2899SCharles.Forsyth disfault(void *reg, char *msg)
98737da2899SCharles.Forsyth {
98837da2899SCharles.Forsyth Prog *p;
98937da2899SCharles.Forsyth
99037da2899SCharles.Forsyth USED(reg);
99137da2899SCharles.Forsyth
99237da2899SCharles.Forsyth if(strncmp(msg, Eintr, 6) == 0)
99337da2899SCharles.Forsyth exits(0);
99437da2899SCharles.Forsyth
99537da2899SCharles.Forsyth if(up == nil) {
99637da2899SCharles.Forsyth print("EMU: faults: %s\n", msg);
99737da2899SCharles.Forsyth cleanexit(0);
99837da2899SCharles.Forsyth }
99937da2899SCharles.Forsyth if(up->type != Interp) {
100037da2899SCharles.Forsyth print("SYS: process %s faults: %s\n", up->text, msg);
100137da2899SCharles.Forsyth cleanexit(0);
100237da2899SCharles.Forsyth }
100337da2899SCharles.Forsyth
100437da2899SCharles.Forsyth if(up->iprog != nil)
100537da2899SCharles.Forsyth acquire();
100637da2899SCharles.Forsyth
100737da2899SCharles.Forsyth p = currun();
100837da2899SCharles.Forsyth if(p == nil)
100937da2899SCharles.Forsyth panic("Interp faults with no dis prog");
101037da2899SCharles.Forsyth
101137da2899SCharles.Forsyth /* cause an exception in the dis prog. As for error(), but Plan 9 needs reg*/
101237da2899SCharles.Forsyth kstrcpy(up->env->errstr, msg, ERRMAX);
101337da2899SCharles.Forsyth oslongjmp(reg, up->estack[--up->nerr], 1);
101437da2899SCharles.Forsyth }
101537da2899SCharles.Forsyth
101637da2899SCharles.Forsyth void
vmachine(void * a)101737da2899SCharles.Forsyth vmachine(void *a)
101837da2899SCharles.Forsyth {
101937da2899SCharles.Forsyth Prog *r;
102037da2899SCharles.Forsyth Osenv *o;
102137da2899SCharles.Forsyth int cycles;
102237da2899SCharles.Forsyth static int gccounter;
102337da2899SCharles.Forsyth
102437da2899SCharles.Forsyth USED(a);
102537da2899SCharles.Forsyth
102637da2899SCharles.Forsyth startup();
102737da2899SCharles.Forsyth
102837da2899SCharles.Forsyth while(waserror()) {
102937da2899SCharles.Forsyth if(up->iprog != nil)
103037da2899SCharles.Forsyth acquire();
103137da2899SCharles.Forsyth if(handler(up->env->errstr) == 0) {
103237da2899SCharles.Forsyth propex(currun(), up->env->errstr);
103337da2899SCharles.Forsyth progexit();
103437da2899SCharles.Forsyth }
103537da2899SCharles.Forsyth up->env = &up->defenv;
103637da2899SCharles.Forsyth }
103737da2899SCharles.Forsyth
103837da2899SCharles.Forsyth cycles = 0;
103937da2899SCharles.Forsyth for(;;) {
104037da2899SCharles.Forsyth if(tready(nil) == 0) {
104137da2899SCharles.Forsyth execatidle();
104237da2899SCharles.Forsyth strcpy(up->text, "idle");
104337da2899SCharles.Forsyth Sleep(&isched.irend, tready, 0);
104437da2899SCharles.Forsyth strcpy(up->text, "dis");
104537da2899SCharles.Forsyth }
104637da2899SCharles.Forsyth
104737da2899SCharles.Forsyth if(isched.vmq != nil && (isched.runhd == nil || ++cycles > 2)){
104837da2899SCharles.Forsyth iyield();
104937da2899SCharles.Forsyth cycles = 0;
105037da2899SCharles.Forsyth }
105137da2899SCharles.Forsyth
105237da2899SCharles.Forsyth r = isched.runhd;
105337da2899SCharles.Forsyth if(r != nil) {
105437da2899SCharles.Forsyth o = r->osenv;
105537da2899SCharles.Forsyth up->env = o;
105637da2899SCharles.Forsyth
105737da2899SCharles.Forsyth FPrestore(&o->fpu);
105837da2899SCharles.Forsyth r->xec(r);
105937da2899SCharles.Forsyth FPsave(&o->fpu);
106037da2899SCharles.Forsyth
106137da2899SCharles.Forsyth if(isched.runhd != nil)
106237da2899SCharles.Forsyth if(r == isched.runhd)
106337da2899SCharles.Forsyth if(isched.runhd != isched.runtl) {
106437da2899SCharles.Forsyth isched.runhd = r->link;
106537da2899SCharles.Forsyth r->link = nil;
106637da2899SCharles.Forsyth isched.runtl->link = r;
106737da2899SCharles.Forsyth isched.runtl = r;
106837da2899SCharles.Forsyth }
106937da2899SCharles.Forsyth up->env = &up->defenv;
107037da2899SCharles.Forsyth }
107137da2899SCharles.Forsyth if(isched.runhd != nil)
107237da2899SCharles.Forsyth if((++gccounter&0xFF) == 0 || memlow()) {
107337da2899SCharles.Forsyth gcbusy++;
107437da2899SCharles.Forsyth up->type = BusyGC;
107537da2899SCharles.Forsyth pushrun(up->prog);
107637da2899SCharles.Forsyth rungc(isched.head);
107737da2899SCharles.Forsyth up->type = Interp;
107837da2899SCharles.Forsyth delrunq(up->prog);
107937da2899SCharles.Forsyth }
108037da2899SCharles.Forsyth }
108137da2899SCharles.Forsyth }
108237da2899SCharles.Forsyth
108337da2899SCharles.Forsyth void
disinit(void * a)108437da2899SCharles.Forsyth disinit(void *a)
108537da2899SCharles.Forsyth {
108637da2899SCharles.Forsyth Prog *p;
108737da2899SCharles.Forsyth Osenv *o;
108837da2899SCharles.Forsyth Module *root;
108937da2899SCharles.Forsyth char *initmod = a;
109037da2899SCharles.Forsyth
109137da2899SCharles.Forsyth if(waserror())
109237da2899SCharles.Forsyth panic("disinit error: %r");
109337da2899SCharles.Forsyth
109437da2899SCharles.Forsyth if(vflag)
109537da2899SCharles.Forsyth print("Initial Dis: \"%s\"\n", initmod);
109637da2899SCharles.Forsyth
109737da2899SCharles.Forsyth fmtinstall('D', Dconv);
109837da2899SCharles.Forsyth
109937da2899SCharles.Forsyth FPinit();
110037da2899SCharles.Forsyth FPsave(&up->env->fpu);
110137da2899SCharles.Forsyth
110237da2899SCharles.Forsyth opinit();
110337da2899SCharles.Forsyth modinit();
110437da2899SCharles.Forsyth excinit();
110537da2899SCharles.Forsyth
110637da2899SCharles.Forsyth root = load(initmod);
110737da2899SCharles.Forsyth if(root == 0) {
110837da2899SCharles.Forsyth kgerrstr(up->genbuf, sizeof up->genbuf);
110937da2899SCharles.Forsyth panic("loading \"%s\": %s", initmod, up->genbuf);
111037da2899SCharles.Forsyth }
111137da2899SCharles.Forsyth
111237da2899SCharles.Forsyth p = schedmod(root);
111337da2899SCharles.Forsyth
111437da2899SCharles.Forsyth memmove(p->osenv, up->env, sizeof(Osenv));
111537da2899SCharles.Forsyth o = p->osenv;
111637da2899SCharles.Forsyth incref(&o->pgrp->r);
111737da2899SCharles.Forsyth incref(&o->fgrp->r);
111837da2899SCharles.Forsyth incref(&o->egrp->r);
111937da2899SCharles.Forsyth if(o->sigs != nil)
112037da2899SCharles.Forsyth incref(&o->sigs->r);
112137da2899SCharles.Forsyth o->user = nil;
112237da2899SCharles.Forsyth kstrdup(&o->user, up->env->user);
112337da2899SCharles.Forsyth o->errstr = o->errbuf0;
112437da2899SCharles.Forsyth o->syserrstr = o->errbuf1;
112537da2899SCharles.Forsyth
112637da2899SCharles.Forsyth isched.idle = 1;
112737da2899SCharles.Forsyth poperror();
112837da2899SCharles.Forsyth vmachine(nil);
112937da2899SCharles.Forsyth }
113037da2899SCharles.Forsyth
113137da2899SCharles.Forsyth void
pushrun(Prog * p)113237da2899SCharles.Forsyth pushrun(Prog *p)
113337da2899SCharles.Forsyth {
113437da2899SCharles.Forsyth if(p->addrun != nil)
113537da2899SCharles.Forsyth panic("pushrun addrun");
113637da2899SCharles.Forsyth p->state = Pready;
113737da2899SCharles.Forsyth p->link = isched.runhd;
113837da2899SCharles.Forsyth isched.runhd = p;
113937da2899SCharles.Forsyth if(p->link == nil)
114037da2899SCharles.Forsyth isched.runtl = p;
114137da2899SCharles.Forsyth }
1142